import { sanitizeUrl } from '../study-helpers.js'

const RSS_FEED_URL = 'https://anchor.fm/s/11068d290/podcast/rss'
let episodesCache = null
let episodesCacheAt = 0
let rawXmlCache = null
const EPISODES_CACHE_TTL = 30 * 60 * 1000

function extractCdata(raw) {
  const cdata = /^<!\[CDATA\[([\s\S]*?)\]\]>$/.exec(raw.trim())
  return cdata ? cdata[1].trim() : raw.trim()
}

function parseRssItems(xml, limit = Infinity) {
  const items = []
  const itemRegex = /<item>([\s\S]*?)<\/item>/g
  let match
  while ((match = itemRegex.exec(xml)) !== null && items.length < limit) {
    const block = match[1]
    const titleRaw = /<title>([\s\S]*?)<\/title>/.exec(block)?.[1] ?? ''
    const title = extractCdata(titleRaw)
    if (!title) continue

    const pubDate = (/<pubDate>([\s\S]*?)<\/pubDate>/.exec(block)?.[1] ?? '').trim()
    const guidRaw = /<guid[^>]*>([\s\S]*?)<\/guid>/.exec(block)?.[1] ?? ''
    const guid = extractCdata(guidRaw)
    const enclosureUrl = /<enclosure[^>]+url="([^"]+)"/.exec(block)?.[1] ?? ''
    const link = guid.startsWith('http') ? guid : enclosureUrl
    const descRaw = /<description>([\s\S]*?)<\/description>/.exec(block)?.[1] ?? ''
    const descText = extractCdata(descRaw).replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim()
    const duration = (/<itunes:duration>([\s\S]*?)<\/itunes:duration>/.exec(block)?.[1] ?? '').trim()
    const episode = (/<itunes:episode>([\s\S]*?)<\/itunes:episode>/.exec(block)?.[1] ?? '').trim()
    const season = (/<itunes:season>([\s\S]*?)<\/itunes:season>/.exec(block)?.[1] ?? '').trim()
    items.push({
      title, pubDate, link,
      audioUrl: enclosureUrl,
      description: descText.slice(0, 220) + (descText.length > 220 ? '…' : ''),
      duration, episode, season,
    })
  }
  return items
}

export async function fetchAllEpisodes() {
  const now = Date.now()
  if (episodesCache && (now - episodesCacheAt) < EPISODES_CACHE_TTL) {
    return episodesCache
  }
  const controller = new AbortController()
  const timeout = setTimeout(() => controller.abort(), 8000)
  const response = await fetch(RSS_FEED_URL, { signal: controller.signal })
  clearTimeout(timeout)
  if (!response.ok) throw new Error(`RSS fetch failed: ${response.status}`)
  const xml = await response.text()
  rawXmlCache = xml
  const episodes = parseRssItems(xml)
  episodesCache = episodes
  episodesCacheAt = now
  return episodes
}

export async function fetchRawFeedXml() {
  await fetchAllEpisodes()
  return rawXmlCache
}

function toSpotifyEpisodeEmbedUrl(urlValue) {
  if (!urlValue) return ''
  try {
    const parsed = new URL(urlValue)
    if (parsed.protocol !== 'https:') return ''
    const host = parsed.hostname.toLowerCase()
    const parts = parsed.pathname.split('/').filter(Boolean)
    if (host === 'open.spotify.com') {
      if (parts[0] === 'embed' && parts[1] === 'episode' && parts[2]) {
        return `https://open.spotify.com/embed/episode/${parts[2]}?utm_source=generator`
      }
      if (parts[0] === 'episode' && parts[1]) {
        return `https://open.spotify.com/embed/episode/${parts[1]}?utm_source=generator`
      }
    }
  } catch { return '' }
  return ''
}

function decodeEscapedJsonUrl(value) {
  return String(value || '').replace(/\\u002F/g, '/').replace(/\\\//g, '/')
}

function extractSpotifyEpisodeIdFromCreatorHtml(html, sourceUrl) {
  const input = String(html || '')
  if (!input) return ''
  const sourceEpisodeSlug = /-([A-Za-z0-9]+)(?:\/|$)/.exec(sourceUrl)?.[1] ?? ''
  const blockRegex = /"episodeId":"([^"]+)"[\s\S]*?"spotifyUrl":"([^"]+)"/g
  let match
  let firstEpisodeId = ''
  while ((match = blockRegex.exec(input)) !== null) {
    const episodeSlug = match[1]
    const spotifyUrl = decodeEscapedJsonUrl(match[2])
    const episodeId = /\/episode\/([A-Za-z0-9]+)/.exec(spotifyUrl)?.[1]
    if (!firstEpisodeId && episodeId) firstEpisodeId = episodeId
    if (sourceEpisodeSlug && episodeSlug === sourceEpisodeSlug && episodeId) return episodeId
  }
  if (firstEpisodeId) return firstEpisodeId
  const urlMatch = /"spotifyUrl":"(https:\\u002F\\u002Fopen\.spotify\.com\\u002Fepisode\\u002F([A-Za-z0-9]+))/.exec(input)
  return urlMatch ? (urlMatch[2] || '') : ''
}

function isAllowedSpotifyResolverHost(hostname) {
  const host = String(hostname || '').toLowerCase()
  return host === 'open.spotify.com' || host === 'creators.spotify.com' || host === 'anchor.fm' || host === 'podcasters.spotify.com'
}

export function register(app) {
  app.get('/api/spotify/embed-url', async (req, res) => {
    const incoming = typeof req.query.url === 'string' ? req.query.url.trim() : ''
    const safeInput = sanitizeUrl(incoming)

    if (!safeInput || safeInput.startsWith('/')) {
      res.status(400).json({ message: 'A valid episode URL is required.' }); return
    }

    let parsed
    try {
      parsed = new URL(safeInput)
    } catch {
      res.status(400).json({ message: 'Malformed URL.' }); return
    }

    if (parsed.protocol !== 'https:' || !isAllowedSpotifyResolverHost(parsed.hostname)) {
      res.status(400).json({ message: 'Unsupported episode URL host.' }); return
    }

    const directEmbed = toSpotifyEpisodeEmbedUrl(safeInput)
    if (directEmbed) {
      res.json({ embedUrl: directEmbed, resolvedFrom: 'direct' }); return
    }

    try {
      const controller = new AbortController()
      const timeout = setTimeout(() => controller.abort(), 8000)
      const response = await fetch(safeInput, {
        signal: controller.signal,
        headers: { 'User-Agent': 'Siteforge/1.0 (+https://versebyversewithnate.us)', Accept: 'text/html' },
      })
      clearTimeout(timeout)

      if (!response.ok) {
        res.status(404).json({ message: 'Could not fetch episode page.' }); return
      }

      const html = await response.text()
      const spotifyEpisodeId = extractSpotifyEpisodeIdFromCreatorHtml(html, safeInput)

      if (!spotifyEpisodeId) {
        res.status(404).json({ message: 'Could not resolve Spotify episode ID from page.' }); return
      }

      const embedUrl = `https://open.spotify.com/embed/episode/${spotifyEpisodeId}?utm_source=generator`
      res.json({ embedUrl, resolvedFrom: 'page-fetch' })
    } catch (err) {
      console.error('[spotify/embed-url] resolve error:', err.message)
      res.status(500).json({ message: 'Could not resolve Spotify embed URL right now.' })
    }
  })

  app.get('/api/episodes', async (_req, res) => {
    try {
      const episodes = await fetchAllEpisodes()
      res.json({ episodes: episodes.slice(0, 6) })
    } catch (err) {
      console.error('[episodes] RSS fetch error:', err.message)
      res.json({ episodes: (episodesCache ?? []).slice(0, 6) })
    }
  })

  app.get('/api/episodes/all', async (_req, res) => {
    try {
      const episodes = await fetchAllEpisodes()
      res.json({ episodes })
    } catch (err) {
      console.error('[episodes/all] RSS fetch error:', err.message)
      res.json({ episodes: episodesCache ?? [] })
    }
  })

  app.get('/api/episode-audio', async (_req, res) => {
    try {
      const episodes = await fetchAllEpisodes()
      res.json({ episodes: episodes.map(e => ({ title: e.title, audioUrl: e.audioUrl, duration: e.duration, episode: e.episode })) })
    } catch (err) {
      console.error('[episode-audio] RSS fetch error:', err.message)
      res.json({ episodes: (episodesCache ?? []).map(e => ({ title: e.title, audioUrl: e.audioUrl, duration: e.duration, episode: e.episode })) })
    }
  })
}
