import { type NextRequest, NextResponse } from "next/server"

import { env } from "@/env/server"
import { dt } from "@/lib/dt"
import { createCounter } from "@/server/telemetry"

import {
  getEntries,
  getSyncToken,
  saveEntries,
  saveLastUpdatedDate,
  saveSitemapData,
  saveSyncToken,
} from "@/utils/sitemap"

import { contentstackSync } from "./sync"
import { mapEntriesToSitemapData, mergeEntries } from "./utils"

export const dynamic = "force-dynamic"

export async function GET(request: NextRequest) {
  const generateSitemapCounter = createCounter("sitemap", "generate")
  const metricsGenerateSitemap = generateSitemapCounter.init()
  try {
    metricsGenerateSitemap.start()

    const headersList = request.headers
    const secret = headersList.get("x-sitemap-sync-secret")

    if (secret !== env.SITEMAP_SYNC_SECRET) {
      throw Error(
        `Can't sync and generate sitemap, invalid secret, received secret: ${secret}`
      )
    }

    const syncToken = await getSyncToken()
    const currentEntries = await getEntries()

    const responseData = await contentstackSync(syncToken)
    const mergedEntries = mergeEntries(currentEntries, responseData.entries)

    const entriesSaveCounter = createCounter("sitemap", "entries.save")
    const metricsEntriesSave = entriesSaveCounter.init({
      entriesCount: mergedEntries.length,
    })

    metricsEntriesSave.start()
    await saveEntries(mergedEntries)
    metricsEntriesSave.success()

    const sitemapData = mapEntriesToSitemapData(mergedEntries)
    const lastUpdated = dt().utc().format()

    const saveDataCounter = createCounter("sitemap", "data.save")
    const metricsDataSave = saveDataCounter.init({
      sitemapEntriesCount: sitemapData.length,
      lastUpdated,
    })
    metricsDataSave.start()
    await saveSitemapData(sitemapData)
    await saveLastUpdatedDate(lastUpdated)
    metricsDataSave.success()

    if (syncToken !== responseData.syncToken) {
      const syncTokenSaveCounter = createCounter("sitemap", "syncToken.save")
      const metricsSyncTokenSave = syncTokenSaveCounter.init({
        syncToken: responseData.syncToken,
      })
      metricsSyncTokenSave.start()
      await saveSyncToken(responseData.syncToken)
      metricsSyncTokenSave.success()
    }

    metricsGenerateSitemap.success()

    return NextResponse.json({
      message: "Sitemap data generated and stored successfully!",
      now: dt().utc().format(),
    })
  } catch (error) {
    metricsGenerateSitemap.fail(error)

    return NextResponse.json(
      {
        error: "Failed to generate sitemap",
        now: dt().utc().format(),
      },
      { status: 500, statusText: "Internal Server Error" }
    )
  }
}
