import express from 'express'
import path from 'node:path'
import { readFile } from 'node:fs/promises'
import { escapeHtml, escapeXml, injectSeoIntoHtml, normalizeSitemapPath } from '../helpers.js'
import {
  DIST_DIR,
  DIST_IMAGES_DIR,
  PUBLIC_IMAGES_DIR,
  UPLOADS_DIR,
  INDEX_FILE,
  DEFAULT_SEO,
  APP_VERSION,
  GIT_COMMIT,
} from '../config.js'
import { state } from '../state.js'
import { loadSiteContentFile } from '../data.js'
import { DATA_FILE } from '../config.js'
import { sanitizeRedirectRules } from '../study-helpers.js'

export function register(app) {
  const SALVATION_INDEX_FILE = path.join(DIST_DIR, 'salvation', 'index.html')

  app.get('/api/version', (_req, res) => {
    res.json({ version: APP_VERSION, commit: GIT_COMMIT })
  })

  app.get('/robots.txt', async (_req, res) => {
    let content = state.cachedSiteContent
    if (!content) {
      try {
        const parsed = await loadSiteContentFile(DATA_FILE)
        content = parsed.siteContent
      } catch { content = {} }
    }

    const seo = content?.seo ?? DEFAULT_SEO
    const canonical = seo.canonicalUrl || DEFAULT_SEO.canonicalUrl
    const root = canonical.endsWith('/') ? canonical.slice(0, -1) : canonical

    res.type('text/plain').send(
      ['User-agent: *', 'Allow: /', 'Disallow: /salvation', `Sitemap: ${root}/sitemap.xml`].join('\n'),
    )
  })

  app.get('/sitemap.xml', async (_req, res) => {
    let content = state.cachedSiteContent
    if (!content) {
      try {
        const parsed = await loadSiteContentFile(DATA_FILE)
        content = parsed.siteContent
      } catch { content = {} }
    }

    const seo = content?.seo ?? DEFAULT_SEO
    const canonical = seo.canonicalUrl || DEFAULT_SEO.canonicalUrl
    const root = canonical.endsWith('/') ? canonical.slice(0, -1) : canonical
    const paths = Array.isArray(seo.sitemapPaths) && seo.sitemapPaths.length > 0
      ? seo.sitemapPaths
      : DEFAULT_SEO.sitemapPaths

    const urls = paths
      .map(item => normalizeSitemapPath(item))
      .filter(Boolean)
      .map(item => `${root}${item}`)

    const xml = [
      '<?xml version="1.0" encoding="UTF-8"?>',
      '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
      ...urls.map(url => `  <url><loc>${escapeXml(url)}</loc></url>`),
      '</urlset>',
    ].join('\n')

    res.type('application/xml').send(xml)
  })

  // Redirect rules middleware
  app.use((req, res, next) => {
    const rules = sanitizeRedirectRules(state.cachedSiteContent?.redirects)
    const match = rules.find(rule => rule.path === req.path)
    if (!match) { next(); return }
    res.redirect(match.statusCode === 302 ? 302 : 301, match.target)
  })

  // Static files
  app.use('/images', express.static(DIST_IMAGES_DIR))
  app.use('/images', express.static(PUBLIC_IMAGES_DIR))
  app.use('/uploads', express.static(UPLOADS_DIR))

  // Explicitly serve salvation page on both paths without relying on slash redirects.
  app.get(['/salvation', '/salvation/'], (_req, res, next) => {
    res.sendFile(SALVATION_INDEX_FILE, err => {
      if (err) next()
    })
  })

  // Social share stub for questions
  app.get('/questions/share/:id', (req, res) => {
    const id = req.params.id
    if (!id || !/^[\w-]{1,120}$/.test(id)) {
      res.redirect(302, '/questions'); return
    }
    const sourceQuestions = state.questions
    const question = sourceQuestions.find(q => q.id === id && q.isApproved === true && q.answer)
    if (!question) {
      res.redirect(302, '/questions'); return
    }

    const BASE = 'https://versebyversewithnate.us'
    const canonicalUrl = `${BASE}/questions#qa-${encodeURIComponent(id)}`
    const shareUrl = `${BASE}/questions/share/${encodeURIComponent(id)}`
    const ogTitle = escapeHtml(question.question.length > 100
      ? `${question.question.slice(0, 97)}…`
      : question.question)
    const answerSnippet = question.answer.replace(/\n+/g, ' ').trim()
    const ogDescription = escapeHtml(answerSnippet.length > 200
      ? `${answerSnippet.slice(0, 197)}…`
      : answerSnippet)
    const ogImage = `${BASE}/images/banner.png`

    res.type('html').send(`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>${ogTitle} — Verse by Verse with Nate</title>
<meta name="description" content="${ogDescription}"/>
<meta property="og:type" content="article"/>
<meta property="og:site_name" content="Verse by Verse with Nate"/>
<meta property="og:url" content="${escapeHtml(shareUrl)}"/>
<meta property="og:title" content="${ogTitle}"/>
<meta property="og:description" content="${ogDescription}"/>
<meta property="og:image" content="${escapeHtml(ogImage)}"/>
<meta property="og:image:alt" content="${ogTitle}"/>
<meta name="twitter:card" content="summary_large_image"/>
<meta name="twitter:title" content="${ogTitle}"/>
<meta name="twitter:description" content="${ogDescription}"/>
<meta name="twitter:image" content="${escapeHtml(ogImage)}"/>
<link rel="canonical" href="${escapeHtml(shareUrl)}"/>
<meta http-equiv="refresh" content="0;url=${escapeHtml(canonicalUrl)}"/>
<script>location.replace(${JSON.stringify(canonicalUrl)})</script>
</head>
<body></body>
</html>`)
  })

  // SPA static files and fallback
  app.use(express.static(DIST_DIR))

  app.use(async (_req, res) => {
    try {
      const html = await readFile(INDEX_FILE, 'utf8')
      res.type('html').send(injectSeoIntoHtml(html, state.cachedSiteContent))
    } catch {
      res.status(503).send('Frontend build not found. Run "npm run build" first.')
    }
  })
}
