const DEFAULT_API_PATH = '/api'
const INDEXNOW_ENDPOINT = 'https://api.indexnow.org/indexnow'

function normalizeBase(value) {
  return String(value || '').trim().replace(/\/$/, '')
}

function ensureAbsolute(base, path) {
  return `${normalizeBase(base)}${String(path).startsWith('/') ? path : `/${path}`}`
}

async function fetchJson(url) {
  const response = await fetch(url, {
    headers: {
      Accept: 'application/json',
    },
  })

  if (!response.ok) {
    throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`)
  }

  return response.json()
}

function collectStaticRoutes(siteSettings) {
  const routes = [
    '/',
    '/about',
    '/articles',
    '/categories',
    '/tags',
    '/timeline',
    '/reviews',
    '/friends',
    '/rss.xml',
    '/sitemap.xml',
    '/llms.txt',
    '/llms-full.txt',
    '/indexnow-key.txt',
  ]

  if (siteSettings?.ai_enabled || siteSettings?.ai?.enabled) {
    routes.push('/ask')
  }

  return routes
}

async function main() {
  const indexNowKey = String(process.env.INDEXNOW_KEY || '').trim()
  if (!indexNowKey) {
    throw new Error('Missing INDEXNOW_KEY environment variable.')
  }

  const configuredSiteUrl = normalizeBase(process.env.SITE_URL || process.env.PUBLIC_SITE_URL || '')
  const configuredApiBaseUrl = normalizeBase(
    process.env.INTERNAL_API_BASE_URL || process.env.PUBLIC_API_BASE_URL || '',
  )

  const bootstrapApiBaseUrl = configuredApiBaseUrl || `${configuredSiteUrl}${DEFAULT_API_PATH}`
  if (!bootstrapApiBaseUrl) {
    throw new Error('Missing SITE_URL/PUBLIC_SITE_URL or API base URL for IndexNow submission.')
  }

  const siteSettings = await fetchJson(`${bootstrapApiBaseUrl}/site_settings`).catch(() => null)
  const siteUrl = normalizeBase(configuredSiteUrl || siteSettings?.site_url || '')
  if (!siteUrl) {
    throw new Error('Unable to determine canonical SITE_URL for IndexNow submission.')
  }

  const apiBaseUrl = configuredApiBaseUrl || `${siteUrl}${DEFAULT_API_PATH}`

  const [posts, categories, tags, reviews] = await Promise.all([
    fetchJson(`${apiBaseUrl}/posts`).catch(() => []),
    fetchJson(`${apiBaseUrl}/categories`).catch(() => []),
    fetchJson(`${apiBaseUrl}/tags`).catch(() => []),
    fetchJson(`${apiBaseUrl}/reviews`).catch(() => []),
  ])

  const urls = new Set(collectStaticRoutes(siteSettings).map((path) => ensureAbsolute(siteUrl, path)))

  for (const post of posts) {
    if (!post?.slug || post?.noindex === true) continue
    urls.add(ensureAbsolute(siteUrl, `/articles/${encodeURIComponent(post.slug)}`))
  }

  for (const category of categories) {
    const token = category?.slug || category?.name
    if (!token) continue
    urls.add(ensureAbsolute(siteUrl, `/categories/${encodeURIComponent(token)}`))
  }

  for (const tag of tags) {
    const token = tag?.slug || tag?.name
    if (!token) continue
    urls.add(ensureAbsolute(siteUrl, `/tags/${encodeURIComponent(token)}`))
  }

  for (const review of reviews) {
    if (!review?.id) continue
    urls.add(ensureAbsolute(siteUrl, `/reviews/${review.id}`))
  }

  const payload = {
    host: new URL(siteUrl).host,
    key: indexNowKey,
    keyLocation: ensureAbsolute(siteUrl, '/indexnow-key.txt'),
    urlList: [...urls],
  }

  const response = await fetch(INDEXNOW_ENDPOINT, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json; charset=utf-8',
    },
    body: JSON.stringify(payload),
  })

  const responseText = await response.text().catch(() => '')
  if (!response.ok) {
    throw new Error(`IndexNow submission failed: ${response.status} ${response.statusText}\n${responseText}`)
  }

  console.log(`IndexNow submitted ${payload.urlList.length} URLs for ${siteUrl}`)
  if (responseText) {
    console.log(responseText)
  }
}

main().catch((error) => {
  console.error(error instanceof Error ? error.message : error)
  process.exitCode = 1
})
