import { MetadataRoute } from 'next'
import { SITE_URL } from '@/lib/seo'

type TldListResponse = {
  tlds: string[]
  latest_recorded_at: string | null
}

type BlogListResponse = {
  posts: Array<{ slug: string; published_at?: string | null; updated_at?: string | null }>
  total?: number
  limit?: number
  offset?: number
}

type ListingPublic = {
  slug: string
}

async function fetchJson<T>(url: string): Promise<T> {
  const res = await fetch(url, {
    // Cache to protect the backend. Sitemaps don't need to be real-time.
    next: { revalidate: 3600 },
  })
  if (!res.ok) {
    throw new Error(`Failed to fetch ${url}: ${res.status}`)
  }
  return (await res.json()) as T
}

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || SITE_URL
  const now = new Date()

  const staticPages: MetadataRoute.Sitemap = [
    { url: baseUrl, lastModified: now, changeFrequency: 'daily', priority: 1.0 },
    { url: `${baseUrl}/discover`, lastModified: now, changeFrequency: 'daily', priority: 0.9 },
    { url: `${baseUrl}/acquire`, lastModified: now, changeFrequency: 'hourly', priority: 0.9 },
    { url: `${baseUrl}/buy`, lastModified: now, changeFrequency: 'hourly', priority: 0.8 },
    { url: `${baseUrl}/auctions`, lastModified: now, changeFrequency: 'hourly', priority: 0.8 },
    { url: `${baseUrl}/yield`, lastModified: now, changeFrequency: 'weekly', priority: 0.8 },
    { url: `${baseUrl}/pricing`, lastModified: now, changeFrequency: 'weekly', priority: 0.8 },
    { url: `${baseUrl}/about`, lastModified: now, changeFrequency: 'monthly', priority: 0.5 },
    { url: `${baseUrl}/blog`, lastModified: now, changeFrequency: 'weekly', priority: 0.7 },
    { url: `${baseUrl}/contact`, lastModified: now, changeFrequency: 'monthly', priority: 0.4 },
    { url: `${baseUrl}/privacy`, lastModified: now, changeFrequency: 'yearly', priority: 0.2 },
    { url: `${baseUrl}/terms`, lastModified: now, changeFrequency: 'yearly', priority: 0.2 },
    { url: `${baseUrl}/imprint`, lastModified: now, changeFrequency: 'yearly', priority: 0.2 },
    { url: `${baseUrl}/cookies`, lastModified: now, changeFrequency: 'yearly', priority: 0.2 },
    // We intentionally do not include /login and /register in the sitemap.
  ]

  const out: MetadataRoute.Sitemap = [...staticPages]

  // ----------------------------
  // Discover (TLD) pages (DB-driven)
  // ----------------------------
  try {
    const tlds = await fetchJson<TldListResponse>(`${baseUrl}/api/v1/tld-prices/tlds?limit=20000`)
    const lastMod = tlds.latest_recorded_at ? new Date(tlds.latest_recorded_at) : now
    for (const tld of tlds.tlds || []) {
      if (!tld) continue
      out.push({
        url: `${baseUrl}/discover/${encodeURIComponent(tld)}`,
        lastModified: lastMod,
        changeFrequency: 'daily',
        priority: 0.7,
      })
    }
  } catch {
    // If DB isn't ready yet, we still serve a valid sitemap for static pages.
  }

  // ----------------------------
  // Blog post pages
  // ----------------------------
  try {
    const limit = 200
    const maxPages = 25 // hard safety cap
    let offset = 0
    let page = 0

    while (page < maxPages) {
      const blog = await fetchJson<BlogListResponse>(`${baseUrl}/api/v1/blog/posts?limit=${limit}&offset=${offset}`)
      const posts = blog.posts || []
      for (const post of posts) {
        if (!post?.slug) continue
        const ts = post.updated_at || post.published_at
        out.push({
          url: `${baseUrl}/blog/${encodeURIComponent(post.slug)}`,
          lastModified: ts ? new Date(ts) : now,
          changeFrequency: 'weekly',
          priority: 0.6,
        })
      }

      // Stop when API reports total or when a page is not full.
      if (typeof blog.total === 'number' && offset + limit >= blog.total) break
      if (posts.length < limit) break

      offset += limit
      page += 1
    }
  } catch {
    // ignore
  }

  // ----------------------------
  // Public listing pages (Pounce Direct)
  // ----------------------------
  try {
    const limit = 50
    const maxPages = 30 // 1500 listings max in sitemap
    for (let page = 0; page < maxPages; page += 1) {
      const offset = page * limit
      const listings = await fetchJson<ListingPublic[]>(
        `${baseUrl}/api/v1/listings?limit=${limit}&offset=${offset}&clean_only=true&sort_by=newest`
      )
      const rows = listings || []
      for (const l of rows) {
        if (!l?.slug) continue
        out.push({
          url: `${baseUrl}/buy/${encodeURIComponent(l.slug)}`,
          lastModified: now,
          changeFrequency: 'daily',
          priority: 0.6,
        })
      }
      if (rows.length < limit) break
    }
  } catch {
    // ignore
  }

  return out
}
