import { GitHubRepository, GitHubStats, GitHubActivity, LanguageStats, RateLimitInfo, StarHistory } from "./types"

// Cache management
const cache = new Map<string, { data: any; timestamp: number; expiresAt: number }>()

// Docs mode detection
const isDocsMode = () => {
  return typeof window !== "undefined" && 
    (window.location.pathname.includes("/docs/") || 
     window.location.pathname.includes("/components/"))
}

// Get cache duration based on mode
const getCacheDuration = (defaultDuration: number) => {
  // Increase cache duration to 30 minutes in docs mode
  return isDocsMode() ? 1800000 : defaultDuration // 30 minutes : default
}

// Language colors
export const LANGUAGE_COLORS: Record<string, string> = {
  JavaScript: "#f7df1e",
  TypeScript: "#3178c6",
  Python: "#3776ab",
  Java: "#ed8b00",
  "C++": "#00599c",
  "C#": "#239120",
  Go: "#00add8",
  Rust: "#000000",
  Swift: "#fa7343",
  Kotlin: "#7f52ff",
  PHP: "#777bb4",
  Ruby: "#cc342d",
  HTML: "#e34f26",
  CSS: "#1572b6",
  Vue: "#4fc08d",
  React: "#61dafb",
  Shell: "#89e051",
  Dart: "#0175c2",
  Elixir: "#6e4a7e",
  Scala: "#c22d40",
  R: "#198ce7",
  Julia: "#9558b2",
  Lua: "#000080",
  Perl: "#39457e",
  Haskell: "#5e5086",
  Clojure: "#db5855",
  Erlang: "#b83998",
  Objective_C: "#438eff",
  // Add more as needed
}

// API base URL
const API_BASE = "https://api.github.com"

// Helper to make authenticated requests
async function githubFetch(url: string, token?: string): Promise<Response> {
  const headers: HeadersInit = {
    Accept: "application/vnd.github.v3+json",
  }

  if (token) {
    headers.Authorization = `token ${token}`
  }

  const response = await fetch(url, { headers })

  if (response.status === 403 && response.headers.get("X-RateLimit-Remaining") === "0") {
    const resetTime = parseInt(response.headers.get("X-RateLimit-Reset") || "0") * 1000
    const resetDate = new Date(resetTime)
    throw new Error(`GitHub API rate limit exceeded. Resets at ${resetDate.toLocaleTimeString()}`)
  }

  if (!response.ok) {
    throw new Error(`GitHub API error: ${response.status} ${response.statusText}`)
  }

  return response
}

// Get rate limit info
export async function getRateLimitInfo(token?: string): Promise<RateLimitInfo> {
  const cacheKey = `rate-limit-${token || "public"}`
  const cached = cache.get(cacheKey)

  if (cached && cached.expiresAt > Date.now()) {
    return cached.data
  }

  const response = await githubFetch(`${API_BASE}/rate_limit`, token)
  const data = await response.json()

  const rateLimitInfo: RateLimitInfo = {
    limit: data.rate.limit,
    remaining: data.rate.remaining,
    reset: data.rate.reset * 1000,
    used: data.rate.used,
  }

  cache.set(cacheKey, {
    data: rateLimitInfo,
    timestamp: Date.now(),
    expiresAt: Date.now() + getCacheDuration(60000), // Docs modunda daha uzun cache
  })

  return rateLimitInfo
}

// Fetch user repositories
export async function fetchUserRepositories(
  username: string,
  token?: string,
  options?: {
    sort?: string
    per_page?: number
    page?: number
  }
): Promise<GitHubRepository[]> {
  const params = new URLSearchParams({
    sort: options?.sort || "updated",
    per_page: String(options?.per_page || 100),
    page: String(options?.page || 1),
  })

  const cacheKey = `repos-${username}-${params.toString()}`
  const cached = cache.get(cacheKey)

  if (cached && cached.expiresAt > Date.now()) {
    return cached.data
  }

  const response = await githubFetch(`${API_BASE}/users/${username}/repos?${params}`, token)
  const repos = await response.json()

  cache.set(cacheKey, {
    data: repos,
    timestamp: Date.now(),
    expiresAt: Date.now() + getCacheDuration(300000), // 30 minutes in docs mode
  })

  return repos
}

// Fetch single repository
export async function fetchRepository(
  owner: string,
  repo: string,
  token?: string
): Promise<GitHubRepository> {
  const cacheKey = `repo-${owner}-${repo}`
  const cached = cache.get(cacheKey)

  if (cached && cached.expiresAt > Date.now()) {
    return cached.data
  }

  const response = await githubFetch(`${API_BASE}/repos/${owner}/${repo}`, token)
  const repository = await response.json()

  cache.set(cacheKey, {
    data: repository,
    timestamp: Date.now(),
    expiresAt: Date.now() + getCacheDuration(300000), // 30 minutes in docs mode
  })

  return repository
}

// Fetch repository contributors count
export async function fetchContributorsCount(
  owner: string,
  repo: string,
  token?: string
): Promise<number> {
  const cacheKey = `contributors-${owner}-${repo}`
  const cached = cache.get(cacheKey)

  if (cached && cached.expiresAt > Date.now()) {
    return cached.data
  }

  try {
    const response = await githubFetch(
      `${API_BASE}/repos/${owner}/${repo}/contributors?per_page=1&anon=true`,
      token
    )
    
    // Get total count from Link header
    const linkHeader = response.headers.get("Link")
    if (linkHeader) {
      const match = linkHeader.match(/page=(\d+)>; rel="last"/)
      if (match) {
        const count = parseInt(match[1])
        cache.set(cacheKey, {
          data: count,
          timestamp: Date.now(),
          expiresAt: Date.now() + getCacheDuration(3600000), // 30 minutes in docs mode
        })
        return count
      }
    }
    
    // If no pagination, count the results
    const contributors = await response.json()
    const count = contributors.length
    
    cache.set(cacheKey, {
      data: count,
      timestamp: Date.now(),
      expiresAt: Date.now() + getCacheDuration(3600000), // 30 minutes in docs mode
    })
    
    return count
  } catch (error) {
    console.error("Failed to fetch contributors:", error)
    return 0
  }
}

// Fetch repository star history (limited without token)
export async function fetchStarHistory(
  owner: string,
  repo: string,
  token?: string
): Promise<StarHistory[]> {
  const cacheKey = `star-history-${owner}-${repo}`
  const cached = cache.get(cacheKey)

  if (cached && cached.expiresAt > Date.now()) {
    return cached.data
  }

  try {
    // This is a simplified version - for full star history you'd need
    // to use the stargazers API with Accept: application/vnd.github.v3.star+json
    // header and paginate through all results
    const response = await githubFetch(`${API_BASE}/repos/${owner}/${repo}`, token)
    const repoData = await response.json()
    
    // For now, return current count as single data point
    const history: StarHistory[] = [{
      date: new Date().toISOString(),
      count: repoData.stargazers_count,
      repository: repoData.full_name,
    }]
    
    cache.set(cacheKey, {
      data: history,
      timestamp: Date.now(),
      expiresAt: Date.now() + getCacheDuration(3600000), // 30 minutes in docs mode
    })
    
    return history
  } catch (error) {
    console.error("Failed to fetch star history:", error)
    return []
  }
}

// Calculate repository statistics
export function calculateStats(repositories: GitHubRepository[]): GitHubStats {
  const totalStars = repositories.reduce((sum, repo) => sum + repo.stargazers_count, 0)
  const totalForks = repositories.reduce((sum, repo) => sum + repo.forks_count, 0)
  const totalWatchers = repositories.reduce((sum, repo) => sum + repo.watchers_count, 0)
  const totalIssues = repositories.reduce((sum, repo) => sum + repo.open_issues_count, 0)
  
  const avgStarsPerRepo = repositories.length > 0 ? totalStars / repositories.length : 0
  
  const mostStarredRepo = repositories.reduce((max, repo) => 
    repo.stargazers_count > (max?.stargazers_count || 0) ? repo : max
  , null as GitHubRepository | null)
  
  // Calculate language statistics
  const languageMap = new Map<string, number>()
  repositories.forEach(repo => {
    if (repo.language) {
      languageMap.set(repo.language, (languageMap.get(repo.language) || 0) + 1)
    }
  })
  
  const totalRepos = repositories.length
  const languages: LanguageStats[] = Array.from(languageMap.entries())
    .map(([language, count]) => ({
      language,
      count,
      percentage: (count / totalRepos) * 100,
      color: LANGUAGE_COLORS[language] || "#6b7280",
    }))
    .sort((a, b) => b.count - a.count)
  
  // Generate recent activity (mock for now)
  const recentActivity: GitHubActivity[] = repositories
    .slice(0, 5)
    .map(repo => ({
      type: "star" as const,
      repository: repo.full_name,
      timestamp: repo.updated_at,
      description: `Repository updated`,
    }))
  
  return {
    totalStars,
    totalForks,
    totalWatchers,
    totalIssues,
    avgStarsPerRepo,
    mostStarredRepo,
    recentActivity,
    languages,
  }
}

// Format numbers for display
export function formatNumber(num: number): string {
  if (num >= 1000000) {
    return (num / 1000000).toFixed(1) + "M"
  }
  if (num >= 1000) {
    return (num / 1000).toFixed(1) + "k"
  }
  return num.toString()
}

// Format date for display
export function formatDate(dateString: string): string {
  const date = new Date(dateString)
  const now = new Date()
  const diffMs = now.getTime() - date.getTime()
  const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24))
  
  if (diffDays === 0) {
    const diffHours = Math.floor(diffMs / (1000 * 60 * 60))
    if (diffHours === 0) {
      const diffMinutes = Math.floor(diffMs / (1000 * 60))
      return `${diffMinutes} minutes ago`
    }
    return `${diffHours} hours ago`
  }
  
  if (diffDays === 1) return "yesterday"
  if (diffDays < 7) return `${diffDays} days ago`
  if (diffDays < 30) return `${Math.floor(diffDays / 7)} weeks ago`
  if (diffDays < 365) return `${Math.floor(diffDays / 30)} months ago`
  
  return date.toLocaleDateString("en-US", {
    year: "numeric",
    month: "short",
    day: "numeric",
  })
}

// Clear cache
export function clearCache(pattern?: string): void {
  if (pattern) {
    for (const key of cache.keys()) {
      if (key.includes(pattern)) {
        cache.delete(key)
      }
    }
  } else {
    cache.clear()
  }
}

// Export data as JSON
export function exportData(data: any, filename: string): void {
  const jsonString = JSON.stringify(data, null, 2)
  const blob = new Blob([jsonString], { type: "application/json" })
  const url = URL.createObjectURL(blob)
  
  const link = document.createElement("a")
  link.href = url
  link.download = filename
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
  
  URL.revokeObjectURL(url)
}

// Export data as CSV
export function exportAsCSV(repositories: GitHubRepository[], filename: string): void {
  const headers = [
    "Name",
    "Owner",
    "Stars",
    "Forks",
    "Watchers",
    "Issues",
    "Language",
    "Description",
    "URL",
    "Created",
    "Updated",
  ]
  
  const rows = repositories.map(repo => [
    repo.name,
    repo.owner.login,
    repo.stargazers_count,
    repo.forks_count,
    repo.watchers_count,
    repo.open_issues_count,
    repo.language || "",
    repo.description || "",
    repo.html_url,
    new Date(repo.created_at).toLocaleDateString(),
    new Date(repo.updated_at).toLocaleDateString(),
  ])
  
  const csvContent = [
    headers.join(","),
    ...rows.map(row => row.map(cell => `"${cell}"`).join(",")),
  ].join("\n")
  
  const blob = new Blob([csvContent], { type: "text/csv" })
  const url = URL.createObjectURL(blob)
  
  const link = document.createElement("a")
  link.href = url
  link.download = filename
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
  
  URL.revokeObjectURL(url)
}