import mammoth from 'mammoth'
import { requireAdminAuth } from '../auth.js'
import { state } from '../state.js'
import { queueEpisodeScriptsWrite } from '../data.js'
import { MAX_EPISODE_SCRIPT_LENGTH } from '../config.js'

/**
 * Simple whitespace-normalised search over episode script text.
 * Returns { episodeNumber, title, filename, snippet, score } for matches.
 */
function searchScripts(query) {
  if (!query || query.trim().length < 2) return []
  const q = query.trim().toLowerCase()
  const words = q.split(/\s+/).filter(w => w.length >= 2)
  const results = []

  for (const [episodeNumber, entry] of Object.entries(state.episodeScripts)) {
    if (!entry?.text) continue
    const text = entry.text.toLowerCase()

    // Count how many words appear in the text
    const matchCount = words.filter(w => text.includes(w)).length
    if (matchCount === 0) continue

    // Find a snippet around the first matching word
    const firstWord = words.find(w => text.includes(w))
    const idx = firstWord ? text.indexOf(firstWord) : 0
    const start = Math.max(0, idx - 80)
    const end = Math.min(entry.text.length, idx + 180)
    let snippet = entry.text.slice(start, end).replace(/\s+/g, ' ').trim()
    if (start > 0) snippet = '…' + snippet
    if (end < entry.text.length) snippet = snippet + '…'

    results.push({
      episodeNumber,
      title: entry.title ?? `Episode ${episodeNumber}`,
      filename: entry.filename ?? '',
      snippet,
      score: matchCount / words.length, // 0–1: fraction of query words found
    })
  }

  return results.sort((a, b) => b.score - a.score).slice(0, 8)
}

export function register(app) {
  // Public script search — called by the frontend global search
  app.get('/api/episode-scripts/search', (req, res) => {
    const q = typeof req.query.q === 'string' ? req.query.q.trim() : ''
    if (!q || q.length < 2) { res.json({ results: [] }); return }
    res.json({ results: searchScripts(q) })
  })

  // Admin: list all uploaded scripts
  app.get('/api/admin-episode-scripts', requireAdminAuth, (_req, res) => {
    const list = Object.entries(state.episodeScripts).map(([episodeNumber, entry]) => ({
      episodeNumber,
      title: entry.title ?? `Episode ${episodeNumber}`,
      filename: entry.filename ?? '',
      uploadedAt: entry.uploadedAt ?? null,
      wordCount: entry.text ? entry.text.split(/\s+/).filter(Boolean).length : 0,
    }))
    list.sort((a, b) => Number(a.episodeNumber) - Number(b.episodeNumber))
    res.json({ scripts: list })
  })

  // Admin: upload a docx script for an episode
  app.post('/api/admin-episode-scripts/:episodeNumber', requireAdminAuth, async (req, res) => {
    const episodeNumber = req.params.episodeNumber?.trim()
    if (!episodeNumber || !/^\d+$/.test(episodeNumber)) {
      res.status(400).json({ message: 'Episode number must be a positive integer.' }); return
    }

    const dataUrl = typeof req.body?.dataUrl === 'string' ? req.body.dataUrl : ''
    const filename = typeof req.body?.filename === 'string' ? req.body.filename.trim() : `episode-${episodeNumber}.docx`
    const title = typeof req.body?.title === 'string' ? req.body.title.trim() : `Episode ${episodeNumber}`

    if (!dataUrl.startsWith('data:')) {
      res.status(400).json({ message: 'dataUrl must be a valid data URL.' }); return
    }

    const base64 = dataUrl.split(',')[1] ?? ''
    if (!base64) { res.status(400).json({ message: 'Empty file.' }); return }

    const buffer = Buffer.from(base64, 'base64')
    if (buffer.length === 0 || buffer.length > 20 * 1024 * 1024) {
      res.status(400).json({ message: 'File must be between 1 byte and 20MB.' }); return
    }

    let text
    try {
      const result = await mammoth.extractRawText({ buffer })
      text = result.value.replace(/\r\n/g, '\n').replace(/\r/g, '\n').trim()
    } catch (err) {
      console.error('[episode-scripts] mammoth extraction failed:', err.message)
      res.status(422).json({ message: 'Could not extract text from file. Make sure it is a valid .docx file.' }); return
    }

    if (!text || text.length < 10) {
      res.status(422).json({ message: 'No readable text found in document.' }); return
    }

    // Trim to max length
    if (text.length > MAX_EPISODE_SCRIPT_LENGTH) {
      text = text.slice(0, MAX_EPISODE_SCRIPT_LENGTH)
    }

    state.episodeScripts[episodeNumber] = {
      title,
      filename,
      text,
      uploadedAt: new Date().toISOString(),
      wordCount: text.split(/\s+/).filter(Boolean).length,
    }
    queueEpisodeScriptsWrite()

    res.json({
      ok: true,
      episodeNumber,
      wordCount: state.episodeScripts[episodeNumber].wordCount,
    })
  })

  // Admin: delete a script
  app.delete('/api/admin-episode-scripts/:episodeNumber', requireAdminAuth, (req, res) => {
    const episodeNumber = req.params.episodeNumber?.trim()
    if (!state.episodeScripts[episodeNumber]) {
      res.status(404).json({ message: 'Script not found.' }); return
    }
    delete state.episodeScripts[episodeNumber]
    queueEpisodeScriptsWrite()
    res.json({ ok: true })
  })
}
