import type { APIRoute } from 'astro'

import { api, DEFAULT_SITE_SETTINGS } from '../lib/api/client'

export const prerender = false

function escapeXml(value: string) {
  return value
    .replaceAll('&', '&amp;')
    .replaceAll('<', '&lt;')
    .replaceAll('>', '&gt;')
    .replaceAll('"', '&quot;')
    .replaceAll("'", '&apos;')
}

function ensureAbsoluteUrl(baseUrl: string, path: string) {
  const normalizedBase = baseUrl.replace(/\/$/, '')
  return `${normalizedBase}${path.startsWith('/') ? path : `/${path}`}`
}

export const GET: APIRoute = async ({ request }) => {
  const fallbackOrigin = new URL(request.url).origin

  let siteSettings = DEFAULT_SITE_SETTINGS
  let posts = await api.getRawPosts().catch(() => [])
  const reviews = await api.getReviews().catch(() => [])
  const categories = await api.getCategories().catch(() => [])
  const tags = await api.getTags().catch(() => [])

  try {
    siteSettings = await api.getSiteSettings()
  } catch {
    siteSettings = DEFAULT_SITE_SETTINGS
  }

  const siteUrl = (siteSettings.siteUrl || fallbackOrigin).replace(/\/$/, '')
  const nowIso = new Date().toISOString()

  const staticRoutes = [
    '/',
    '/about',
    '/articles',
    '/categories',
    '/tags',
    '/timeline',
    '/reviews',
    '/friends',
    '/rss.xml',
    '/llms.txt',
    '/llms-full.txt',
  ]

  if (siteSettings.ai.enabled) {
    staticRoutes.push('/ask')
  }

  const staticUrls = staticRoutes.map((path) => ({
    loc: ensureAbsoluteUrl(siteUrl, path),
    lastmod: nowIso,
    changefreq: path === '/' ? 'hourly' : 'daily',
    priority: path === '/' ? '1.0' : '0.8',
  }))

  const postUrls = posts
    .filter((post) => !post.noindex)
    .map((post) => ({
    loc: ensureAbsoluteUrl(siteUrl, `/articles/${post.slug}`),
    lastmod: new Date(post.updated_at || post.created_at).toISOString(),
    changefreq: 'weekly',
    priority: post.pinned ? '0.9' : '0.7',
  }))

  const reviewUrls = reviews.map((review) => ({
    loc: ensureAbsoluteUrl(siteUrl, `/reviews/${review.id}`),
    lastmod: new Date(review.updated_at || review.created_at).toISOString(),
    changefreq: 'monthly',
    priority: '0.6',
  }))

  const categoryUrls = categories.map((category) => ({
    loc: ensureAbsoluteUrl(siteUrl, `/categories/${encodeURIComponent(category.slug || category.name)}`),
    lastmod: nowIso,
    changefreq: 'weekly',
    priority: '0.7',
  }))

  const tagUrls = tags.map((tag) => ({
    loc: ensureAbsoluteUrl(siteUrl, `/tags/${encodeURIComponent(tag.slug || tag.name)}`),
    lastmod: nowIso,
    changefreq: 'weekly',
    priority: '0.7',
  }))

  const dedupedUrls = new Map<string, { loc: string; lastmod: string; changefreq: string; priority: string }>()

  for (const item of [
    ...staticUrls,
    ...postUrls,
    ...reviewUrls,
    ...categoryUrls,
    ...tagUrls,
  ]) {
    dedupedUrls.set(item.loc, item)
  }

  const xmlBody = [...dedupedUrls.values()]
    .map(
      (item) => `
  <url>
    <loc>${escapeXml(item.loc)}</loc>
    <lastmod>${escapeXml(item.lastmod)}</lastmod>
    <changefreq>${item.changefreq}</changefreq>
    <priority>${item.priority}</priority>
  </url>`,
    )
    .join('')

  const xml = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">${xmlBody}
</urlset>`

  return new Response(xml, {
    headers: {
      'Content-Type': 'application/xml; charset=utf-8',
      'Cache-Control': 'public, max-age=600',
    },
  })
}
