import { useState, useEffect } from 'react'
import { Link, NavLink, Routes, Route, useLocation, useNavigate, useParams } from 'react-router-dom'
import AdminPage from './AdminPage'
import QASection from './components/QASection'
import ContactForm from './components/ContactForm'
import { ColossiansStudyIndexPage, ColossiansStudyNotesPage, ColossiansStudySectionPage, StudyLandingPage } from './colossiansStudy'
import { SpotifyIcon } from './icons'
import type { SiteContent, ArchivedSeries, StudyProgram } from './content'
import { DEFAULTS } from './content'
import './App.css'

const SPOTIFY_EMBED_URL =
  'https://open.spotify.com/embed/show/0Gq1TzoJOdReSZ1gYQi8Xl?utm_source=generator&theme=0'
const CONSENT_KEY = 'vbn_analytics_consent_choice'
const HEADLINER_WIDGET_ID = 'WI_cmou3b4q7000701p0o9qmmcfj'

function toSpotifyEpisodeEmbedUrl(url: string | undefined): string {
  if (!url) return ''

  try {
    const parsed = new URL(url)
    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 isLikelySpotifyEpisodeUrl(url: string | undefined): boolean {
  if (!url) return false
  if (toSpotifyEpisodeEmbedUrl(url)) return true

  try {
    const parsed = new URL(url)
    const host = parsed.hostname.toLowerCase()
    const path = parsed.pathname.toLowerCase()

    if (host === 'creators.spotify.com' && path.includes('/episodes/')) return true
    if (host === 'anchor.fm' && path.includes('/episodes/')) return true
    if (host === 'podcasters.spotify.com' && path.includes('/episodes/')) return true
  } catch {
    return false
  }

  return false
}

function getHomepageFeaturedStudy(content: SiteContent): StudyProgram | null {
  const studies = Array.isArray(content.studies) ? content.studies : []
  if (studies.length === 0) return null
  return studies.find(study => study.showOnHomepage === true)
    ?? studies.find(study => study.status === 'active')
    ?? studies[0]
}

function HeadlinerWidget() {
  const [iframeSrc, setIframeSrc] = useState('')
  const [status, setStatus] = useState<'loading' | 'ready' | 'empty'>('loading')

  useEffect(() => {
    const getDiscoUrl = () => {
      const canonicalHref = document.querySelector('link[rel="canonical"]')?.getAttribute('href')
      const ogUrl = document.querySelector('meta[property="og:url"]')?.getAttribute('content')
      const base = canonicalHref || ogUrl
      if (!base) return window.location.href
      try {
        const parsed = new URL(base)
        return `${parsed.origin}${window.location.pathname}`
      } catch {
        return window.location.href
      }
    }

    const discoUrl = getDiscoUrl()
    const discoTitle = document.querySelector('meta[property="og:title"]')?.getAttribute('content') || document.title
    const src = `https://disco.headliner.link/d/web/widget.html?widgetId=${encodeURIComponent(HEADLINER_WIDGET_ID)}&url=${encodeURIComponent(discoUrl)}&title=${encodeURIComponent(discoTitle)}`

    const sessionId = `SS_siteforge_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`
    const query = new URLSearchParams({
      sessionId,
      url: discoUrl,
      widgetId: HEADLINER_WIDGET_ID,
    })

    fetch(`https://api.headliner.link/api/v1/widget/widget-request?${query.toString()}`)
      .then(r => (r.ok ? r.json() : Promise.reject(new Error('widget request failed'))))
      .then((data: { results?: unknown[] }) => {
        if (Array.isArray(data.results) && data.results.length > 0) {
          setIframeSrc(src)
          setStatus('ready')
          return
        }
        setStatus('empty')
      })
      .catch(() => {
        // If API probing fails, still attempt iframe rendering.
        setIframeSrc(src)
        setStatus('ready')
      })
  }, [])

  return (
    status === 'empty' ? null : (
    <div className="headliner-widget-wrap" aria-label="Featured listening widget">
      {status === 'ready' && iframeSrc && (
        <iframe
          src={iframeSrc}
          title="Featured listening widget"
          loading="lazy"
          className="headliner-widget-frame"
        />
      )}
    </div>
    )
  )
}

function StudyDownloadForm({ buttonText = 'Download Guide' }: { buttonText?: string }) {
  const [fields, setFields] = useState({ firstName: '', lastName: '', email: '' })
  const [subscribe, setSubscribe] = useState(true)
  const [honey, setHoney] = useState('')
  const [status, setStatus] = useState<'idle' | 'submitting' | 'error' | 'success'>('idle')
  const [errorMsg, setErrorMsg] = useState('')
  const [successMsg, setSuccessMsg] = useState('')
  const [downloadUrl, setDownloadUrl] = useState('')

  function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
    setFields(f => ({ ...f, [e.target.name]: e.target.value }))
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    setStatus('submitting')
    setErrorMsg('')
    setSuccessMsg('')
    setDownloadUrl('')

    try {
      const res = await fetch('/api/study-downloads/titus', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ ...fields, subscribe, _honey: honey }),
      })

      const data = await res.json().catch(() => ({})) as { message?: string; downloadUrl?: string }
      if (!res.ok || !data.downloadUrl) {
        setErrorMsg(data.message ?? 'Could not process your request. Please try again.')
        setStatus('error')
        return
      }

      setStatus('success')
      setSuccessMsg('Your download should start now. If not, use the link below.')
      setDownloadUrl(data.downloadUrl)
      window.location.assign(data.downloadUrl)
    } catch {
      setErrorMsg('Could not connect. Please try again later.')
      setStatus('error')
    }
  }

  return (
    <form className="study-download-form" onSubmit={handleSubmit} noValidate>
      <input
        type="text"
        className="contact-honeypot"
        tabIndex={-1}
        autoComplete="off"
        aria-hidden="true"
        value={honey}
        onChange={e => setHoney(e.target.value)}
      />
      <div className="study-download-grid">
        <label>
          First Name
          <input type="text" name="firstName" required autoComplete="given-name" value={fields.firstName} onChange={handleChange} />
        </label>
        <label>
          Last Name
          <input type="text" name="lastName" required autoComplete="family-name" value={fields.lastName} onChange={handleChange} />
        </label>
        <label>
          Email
          <input type="email" name="email" required autoComplete="email" value={fields.email} onChange={handleChange} />
        </label>
      </div>
      <label className="contact-consent">
        <input
          type="checkbox"
          checked={subscribe}
          onChange={e => setSubscribe(e.target.checked)}
        />
        <span>Subscribe me to updates from Verse by Verse with Nate.</span>
      </label>
      {status === 'error' && <p className="contact-error">{errorMsg}</p>}
      {status === 'success' && <p className="study-download-success">{successMsg}</p>}
      {status === 'success' && downloadUrl && (
        <p className="study-download-success">
          <a href={downloadUrl}>Click here if your download does not start automatically.</a>
        </p>
      )}
      <button type="submit" className="btn-primary" disabled={status === 'submitting'}>
        {status === 'submitting' ? 'Preparing Download...' : buttonText}
      </button>
    </form>
  )
}

function ResourceDownloadForm({ resourceId, buttonText }: { resourceId: string; buttonText: string }) {
  const [fields, setFields] = useState({ firstName: '', lastName: '', email: '' })
  const [subscribe, setSubscribe] = useState(true)
  const [honey, setHoney] = useState('')
  const [status, setStatus] = useState<'idle' | 'submitting' | 'error' | 'success'>('idle')
  const [errorMsg, setErrorMsg] = useState('')
  const [successMsg, setSuccessMsg] = useState('')
  const [downloadUrl, setDownloadUrl] = useState('')

  function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
    setFields(f => ({ ...f, [e.target.name]: e.target.value }))
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    setStatus('submitting')
    setErrorMsg('')
    setSuccessMsg('')
    setDownloadUrl('')

    try {
      const res = await fetch('/api/resource-download', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ resourceId, ...fields, subscribe, _honey: honey }),
      })

      const data = await res.json().catch(() => ({})) as { message?: string; downloadUrl?: string }
      if (!res.ok || !data.downloadUrl) {
        setErrorMsg(data.message ?? 'Could not process your request. Please try again.')
        setStatus('error')
        return
      }

      setStatus('success')
      setSuccessMsg('Your download should start now. If not, use the link below.')
      setDownloadUrl(data.downloadUrl)
      window.location.assign(data.downloadUrl)
    } catch {
      setErrorMsg('Could not connect. Please try again later.')
      setStatus('error')
    }
  }

  return (
    <form className="study-download-form" onSubmit={handleSubmit} noValidate>
      <input
        type="text"
        className="contact-honeypot"
        tabIndex={-1}
        autoComplete="off"
        aria-hidden="true"
        value={honey}
        onChange={e => setHoney(e.target.value)}
      />
      <div className="study-download-grid">
        <label>
          First Name
          <input type="text" name="firstName" required autoComplete="given-name" value={fields.firstName} onChange={handleChange} />
        </label>
        <label>
          Last Name
          <input type="text" name="lastName" required autoComplete="family-name" value={fields.lastName} onChange={handleChange} />
        </label>
        <label>
          Email
          <input type="email" name="email" required autoComplete="email" value={fields.email} onChange={handleChange} />
        </label>
      </div>
      <label className="contact-consent">
        <input
          type="checkbox"
          checked={subscribe}
          onChange={e => setSubscribe(e.target.checked)}
        />
        <span>Subscribe me to updates from Verse by Verse with Nate.</span>
      </label>
      {status === 'error' && <p className="contact-error">{errorMsg}</p>}
      {status === 'success' && <p className="study-download-success">{successMsg}</p>}
      {status === 'success' && downloadUrl && (
        <p className="study-download-success">
          <a href={downloadUrl}>Click here if your download does not start automatically.</a>
        </p>
      )}
      <button type="submit" className="btn-primary" disabled={status === 'submitting'}>
        {status === 'submitting' ? 'Preparing Download...' : buttonText}
      </button>
    </form>
  )
}

function buildCustomResourceDownloadId(id: string) {
  return `custom:${id}`
}

function buildArchivedResourceDownloadId(seriesId: string, linkId: string) {
  return `archived:${seriesId}:${linkId}`
}

function buildCustomDownloadPageId(id: string) {
  return `custom--${id}`
}

function buildArchivedDownloadPageId(seriesId: string, linkId: string) {
  return `archived--${seriesId}--${linkId}`
}

interface DownloadPageResource {
  id: string
  label: string
  imageUrl?: string
  summary: string
  tags: string[]
  buttonText: string
  resourceId: string
  amazonUrl?: string
  amazonLabel?: string
}

function resolveDownloadPageResource(content: SiteContent, pageId: string | undefined): DownloadPageResource | null {
  if (!pageId) return null

  if (pageId.startsWith('custom--')) {
    const customId = pageId.slice('custom--'.length)
    const resource = (content.customLinks ?? []).find(link => link.id === customId && link.placement === 'resources')
    if (!resource) return null

    return {
      id: pageId,
      label: resource.label,
      imageUrl: resource.imageUrl,
      summary: resource.description || 'Complete the short form below and your download will start right away.',
      tags: resource.tags ?? [],
      buttonText: `Download ${resource.label}`,
      resourceId: buildCustomResourceDownloadId(resource.id),
      amazonUrl: resource.amazonUrl,
      amazonLabel: resource.amazonLabel,
    }
  }

  if (pageId.startsWith('archived--')) {
    const [, seriesId, linkId] = pageId.split('--')
    const series = (content.archivedSeries ?? []).find(item => item.id === seriesId)
    const link = (series?.resourceLinks ?? []).find(item => item.id === linkId)
    if (!series || !link) return null

    return {
      id: pageId,
      label: link.label || series.title || 'Download Resource',
      imageUrl: series.imageUrl,
      summary: link.description || series.description || 'Fill out the form below to access this download from a previous study.',
      tags: [],
      buttonText: `Download ${link.label || series.title || 'Resource'}`,
      resourceId: buildArchivedResourceDownloadId(series.id, link.id),
      amazonUrl: link.amazonUrl,
      amazonLabel: link.amazonLabel,
    }
  }

  return null
}

function AnalyticsConsentBanner({ content }: { content: SiteContent }) {
  const [choice, setChoice] = useState<'unknown' | 'accepted' | 'declined'>(() => {
    const saved = localStorage.getItem(CONSENT_KEY)
    if (saved === 'accepted' || saved === 'declined') return saved
    return 'unknown'
  })

  async function sendChoice(consent: boolean) {
    await fetch('/api/analytics-consent', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ consent }),
    })
  }

  async function accept() {
    setChoice('accepted')
    localStorage.setItem(CONSENT_KEY, 'accepted')
    try {
      await sendChoice(true)
    } catch {
      // Keep local preference even if network fails.
    }
  }

  async function decline() {
    setChoice('declined')
    localStorage.setItem(CONSENT_KEY, 'declined')
    try {
      await sendChoice(false)
    } catch {
      // Keep local preference even if network fails.
    }
  }

  if (choice !== 'unknown') return null

  return (
    <div className="consent-banner" role="region" aria-label="Analytics consent">
      <p>{content.cookieBannerText || 'We use optional analytics cookies to measure visits and location trends for site improvement.'}</p>
      <div className="consent-actions">
        <button type="button" className="btn-primary" onClick={accept}>Accept</button>
        <button type="button" className="btn-secondary" onClick={decline}>Decline</button>
      </div>
    </div>
  )
}

interface Episode {
  title: string
  pubDate: string
  link: string
  description: string
  duration: string
  episode: string
}

function formatPubDate(raw: string): string {
  try {
    return new Date(raw).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' })
  } catch {
    return raw
  }
}

function SiteHeader({ content }: { content: SiteContent }) {
  const [menuOpen, setMenuOpen] = useState(false)
  const spotifyUrl = content.platformSpotifyUrl || '/spotify'

  return (
    <header className="site-header">
      <div className="header-inner">
        <Link to="/" className="header-logo" aria-label="Home">
          <img src="/book_icon.png" alt="" className="header-logo-img" />
        </Link>
        <button
          type="button"
          className="header-menu-btn"
          aria-expanded={menuOpen}
          aria-controls="site-nav"
          onClick={() => setMenuOpen(open => !open)}
        >
          {menuOpen ? 'Close' : 'Menu'}
        </button>
        <nav id="site-nav" className={`header-nav ${menuOpen ? 'header-nav--open' : ''}`}>
          <NavLink to="/episodes" className={({ isActive }) => `header-nav-link${isActive ? ' header-nav-link--active' : ''}`} onClick={() => setMenuOpen(false)}>Episodes</NavLink>
          <NavLink to="/questions" className={({ isActive }) => `header-nav-link${isActive ? ' header-nav-link--active' : ''}`} onClick={() => setMenuOpen(false)}>Q&amp;A</NavLink>
          <NavLink to="/study" className={({ isActive }) => `header-nav-link${isActive ? ' header-nav-link--active' : ''}`} onClick={() => setMenuOpen(false)}>Studies</NavLink>
          <NavLink to="/resources" className={({ isActive }) => `header-nav-link${isActive ? ' header-nav-link--active' : ''}`} onClick={() => setMenuOpen(false)}>Downloads</NavLink>
          <NavLink to="/about" className={({ isActive }) => `header-nav-link${isActive ? ' header-nav-link--active' : ''}`} onClick={() => setMenuOpen(false)}>About</NavLink>
          <NavLink to="/contact" className={({ isActive }) => `header-nav-link${isActive ? ' header-nav-link--active' : ''}`} onClick={() => setMenuOpen(false)}>Contact</NavLink>
          <a
            href={spotifyUrl}
            target="_blank"
            rel="noreferrer"
            className="header-cta"
          >
            {content.headerFollowLabel || 'Follow on Spotify'}
          </a>
        </nav>
      </div>
    </header>
  )
}

function SiteFooter({ content }: { content: SiteContent }) {
  const spotifyUrl = content.platformSpotifyUrl || '/spotify'
  const appleUrl = content.platformAppleUrl || '/apple'
  const youtubeUrl = content.platformYoutubeUrl || 'https://www.youtube.com/@blackzebraem5558'
  const amazonUrl = content.platformAmazonUrl || '/amazon'
  const creatorUrl = content.platformCreatorUrl || 'https://creators.spotify.com/pod/profile/nmemmert/'
  const facebookUrl = content.platformFacebookUrl || 'https://facebook.com/versebyversewithnate'
  const extraFooterLinks = (content.customLinks ?? []).filter(
    l => l.placement === 'footer' || l.placement === 'platforms',
  )

  return (
    <footer className="site-footer">
      <p className="footer-ornament">✦ &nbsp; ✦ &nbsp; ✦</p>
      <p className="footer-title">{content.footerTitle || 'Verse by Verse with Nate'}</p>
      <p className="footer-sub">{content.footerSubtitle || 'A Journey Through Scripture'}</p>
      {content.footerEmail && (
        <p className="footer-contact">
          Contact:{' '}
          <a href={`mailto:${content.footerEmail}`}>{content.footerEmail}</a>
        </p>
      )}
      <nav className="footer-links" aria-label="Footer links">
        <a href={spotifyUrl} target="_blank" rel="noreferrer">Spotify</a>
        <span aria-hidden="true">·</span>
        <a href={appleUrl} target="_blank" rel="noreferrer">Apple Podcasts</a>
        <span aria-hidden="true">·</span>
        <a href={youtubeUrl} target="_blank" rel="noreferrer">YouTube</a>
        <span aria-hidden="true">·</span>
        <a href={amazonUrl} target="_blank" rel="noreferrer">Amazon Music</a>
        <span aria-hidden="true">·</span>
        <a href={creatorUrl} target="_blank" rel="noreferrer">Creator Profile</a>
        <span aria-hidden="true">·</span>
        <a href={facebookUrl} target="_blank" rel="noreferrer">Facebook</a>
        {extraFooterLinks.length > 0 && (
          <>
            <span aria-hidden="true">·</span>
            <details className="footer-more-links">
              <summary>More Platforms</summary>
              <div className="footer-more-links-menu">
                {extraFooterLinks.map(link => (
                  <a key={link.id} href={link.url} target="_blank" rel="noreferrer">{link.label}</a>
                ))}
              </div>
            </details>
          </>
        )}
      </nav>
      <nav className="footer-links footer-links--legal" aria-label="Legal links">
        <Link to="/privacy">Privacy Policy</Link>
        <span aria-hidden="true">·</span>
        <Link to="/terms">Terms</Link>
      </nav>
      <p className="footer-copy">{content.footerCopyright || '© 2026 Nate Emmert · Made with faith.'}</p>
      {content.footerPrivacyNote && (
        <p className="footer-privacy">{content.footerPrivacyNote}</p>
      )}
    </footer>
  )
}

function PlatformButtons({ content }: { content: SiteContent }) {
  const spotifyUrl = content.platformSpotifyUrl || '/spotify'
  const youtubeUrl = content.platformYoutubeUrl || 'https://www.youtube.com/@blackzebraem5558'
  const amazonUrl = content.platformAmazonUrl || '/amazon'
  const facebookUrl = content.platformFacebookUrl || 'https://facebook.com/versebyversewithnate'
  const appleUrl = content.platformAppleUrl || '/apple'

  return (
    <div className="platform-buttons">
      <a href={appleUrl} target="_blank" rel="noreferrer" className="platform-btn platform-btn-image">
        <img src="/images/apple-podcasts-badge.svg" alt="Listen on Apple Podcasts" className="platform-badge" />
      </a>
      <a href={spotifyUrl} target="_blank" rel="noreferrer" className="platform-btn platform-btn-image">
        <img src="/images/listen-on-spotify.svg" alt="Listen on Spotify" className="platform-badge" />
      </a>
      <a href={youtubeUrl} target="_blank" rel="noreferrer" className="platform-btn platform-btn-image">
        <img src="/images/watch-on-youtube.svg" alt="Watch on YouTube" className="platform-badge" />
      </a>
      <a href={amazonUrl} target="_blank" rel="noreferrer" className="platform-btn platform-btn-image">
        <img src="/images/listen-on-amazon-music.svg" alt="Listen on Amazon Music" className="platform-badge" />
      </a>
      <a href={facebookUrl} target="_blank" rel="noreferrer" className="platform-btn platform-btn-image">
        <img src="/images/follow-on-facebook.svg" alt="Follow on Facebook" className="platform-badge" />
      </a>
      {(content.customLinks ?? []).filter(l => l.placement === 'platforms').map(l => (
        <a
          key={l.id}
          href={l.url}
          target="_blank"
          rel="noreferrer"
          className={`platform-btn ${l.imageUrl ? 'platform-btn-image' : 'custom-btn'}`}
          aria-label={`Listen on ${l.label}`}
        >
          {l.imageUrl
            ? <img src={l.imageUrl} alt={`Listen on ${l.label}`} className="platform-badge" />
            : l.label}
        </a>
      ))}
    </div>
  )
}

function AboutSection({ content }: { content: SiteContent }) {
  return (
    <section className="section-about" aria-label="About the show">
      <div className="section-inner about-inner">
        <div className="about-photo">
          <img src={content.aboutPhotoUrl || '/images/nate-photo.jpeg'} alt="Nate Emmert" />
          <div className="about-photo-divider" aria-hidden="true" />
          <div className="about-nate-copy">
            <p className="eyebrow">{content.aboutEyebrow || 'About Nate'}</p>
            <div className="about-nate-rule" aria-hidden="true" />
            <p>{content.aboutNate}</p>
            <Link to="/episodes" className="about-nate-cta">{content.aboutListenBtnLabel || 'Listen Now ↓'}</Link>
          </div>
        </div>
        <div className="about-text">
          <p className="eyebrow">{content.aboutShowEyebrow || 'About the Show'}</p>
          <h2>{content.aboutShowHeading}</h2>
          <p>{content.aboutShowP1}</p>
          <p>{content.aboutShowP2}</p>
          <div className="rule-divider" aria-hidden="true" />
          <img
            src={content.aboutVerseArtUrl || '/images/hebrews-4-12-verse-art.png'}
            alt="Hebrews 4:12 verse artwork"
            className="about-verse-art"
          />
        </div>
      </div>
    </section>
  )
}

function StudyGuideSection({ content }: { content: SiteContent }) {
  return (
    <section className="section-guide" aria-label="Companion study guide">
      <div className="section-inner guide-inner">
        <div className="guide-cover-art">
          <img
            src={content.seriesImageUrl || '/images/titus-cover.png'}
            alt={content.seriesTitle}
            className="guide-cover-img"
          />
        </div>
        <div className="guide-text">
          <p className="eyebrow">Downloads</p>
          <h1 className="guide-page-title">Study Guides and Downloads</h1>
          <p className="guide-page-intro">Start with the primary guide below, then explore the rest of the download library further down the page.</p>
          <p className="eyebrow">Free Download</p>
          <h2>{content.studyGuideTitle}</h2>
          <p>{content.studyGuideDescription}</p>
          <StudyDownloadForm buttonText={`Download ${content.studyGuideTitle || 'Guide'}`} />
          {content.studyGuideUrl && (
            <div className="guide-actions">
              <a
                href={content.studyGuideUrl}
                target="_blank"
                rel="noreferrer"
                className="btn-secondary"
              >
                {content.studyGuideAmazonButtonLabel || 'Get it on Amazon'}
              </a>
            </div>
          )}
        </div>
      </div>
    </section>
  )
}

function ContactSection({ content }: { content: SiteContent }) {
  return (
    <section className="section-contact" id="contact" aria-label="Contact form">
      <div className="section-inner contact-inner">
        <div className="contact-copy">
          <div className="contact-card">
            <p className="eyebrow">{content.contactEyebrow || 'Get in Touch'}</p>
            <h2>{content.contactHeading || 'Contact Nate'}</h2>

            <div className="contact-profile">
              <img
                src={content.contactPhotoUrl || '/images/nate-contact-photo.png'}
                alt={content.contactName || 'Nate'}
                className="contact-profile-photo"
              />
              <div className="contact-profile-meta">
                <p className="contact-profile-name">{content.contactName || 'Nate'}</p>
                <p className="contact-profile-role">{content.contactRole || 'Bible teacher · Lynchburg, VA'}</p>
              </div>
            </div>

            {content.contactQuote && (
              <blockquote className="contact-quote">
                <p>"{content.contactQuote}"</p>
              </blockquote>
            )}

            {content.contactIntro && (
              <p className="contact-intro">{content.contactIntro}</p>
            )}

            <div className="contact-points" aria-label="Contact response details">
              {content.contactPoint1 && (
                <div className="contact-point">
                  <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                    <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
                  </svg>
                  <span>{content.contactPoint1}</span>
                </div>
              )}
              {content.contactPoint2 && (
                <div className="contact-point">
                  <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                    <circle cx="12" cy="12" r="10" />
                    <polyline points="12 6 12 12 16 14" />
                  </svg>
                  <span>{content.contactPoint2}</span>
                </div>
              )}
            </div>

            {content.contactVerse && (
              <div className="contact-scripture">
                <p>
                  "{content.contactVerse}" -{' '}
                  <span className="contact-scripture-ref">{content.contactVerseRef}</span>
                </p>
              </div>
            )}
          </div>
        </div>
        <ContactForm />
      </div>
    </section>
  )
}

function PodcastHighlightsSection({ content }: { content: SiteContent }) {
  const links = content.podcastFeaturedLinks ?? []
  if (links.length === 0) return null

  return (
    <section className="section-resources" aria-label="Podcast highlights">
      <div className="section-inner">
        <h2 className="section-heading">
          <span className="ornament">✦</span> Podcast Highlights{' '}
          <span className="ornament">✦</span>
        </h2>
        <div className="resources-list">
          {links.map(link => {
            const hasRichContent = !!(
              link.embedUrl
              || isLikelySpotifyEpisodeUrl(link.url)
              || (link.discussionQuestions ?? []).length > 0
              || link.showNotes
            )
            const label = <>{link.episodeNumber ? `Ep. ${link.episodeNumber}: ` : ''}{link.title || link.url}</>
            // Use external link only when there's a url AND no rich detail-page content
            if (!hasRichContent && link.url) {
              return (
                <a key={link.id} href={link.url} target="_blank" rel="noreferrer" className="resource-link">
                  {label}
                </a>
              )
            }
            // Otherwise always route to the internal detail page
            return (
              <Link key={link.id} to={`/episodes/${link.id}`} className="resource-link">
                {label}
              </Link>
            )
          })}
        </div>
      </div>
    </section>
  )
}

function DownloadLibrarySection({ content }: { content: SiteContent }) {
  const resources = (content.customLinks ?? []).filter(link => link.placement === 'resources')
  const archivedWithResources = (content.archivedSeries ?? []).filter(series => (series.resourceLinks ?? []).length > 0)

  if (resources.length === 0 && archivedWithResources.length === 0) return null

  return (
    <section className="section-resources section-download-library" aria-label="Download library">
      <div className="section-inner">
        <div className="download-library-head">
          <p className="eyebrow">Download Library</p>
          <h2 className="section-heading">More guides, worksheets, and past study downloads.</h2>
          <p className="download-library-copy">Keep the main guide featured at the top, and use this library for every other download you want available on the page.</p>
        </div>

        {resources.length > 0 && (
          <div className="download-library-group">
            <div className="download-library-group-head">
              <h3>Current Downloads</h3>
              <p>Extra files you want people to grab right now.</p>
            </div>
            <div className="resources-list">
              {resources.map(resource => (
                <Link key={resource.id} to={`/downloads/${buildCustomDownloadPageId(resource.id)}`} className="resource-download-card resource-download-card--link">
                  <div className="resource-download-header">
                    {resource.imageUrl && (
                      <img src={resource.imageUrl} alt={resource.label} className="resource-link-image" />
                    )}
                    <div className="resource-download-meta">
                      <span className="resource-link-label">{resource.label}</span>
                      {resource.description && <p className="resource-link-description">{resource.description}</p>}
                      {(resource.tags ?? []).length > 0 && (
                        <div className="resource-link-tags">{(resource.tags ?? []).join(', ')}</div>
                      )}
                      <span className="resource-link-action">Open download page →</span>
                    </div>
                  </div>
                </Link>
              ))}
            </div>
          </div>
        )}

        {archivedWithResources.length > 0 && (
          <div className="download-library-group">
            <div className="download-library-group-head">
              <h3>Previous Studies</h3>
              <p>Downloads from earlier series that you still want available.</p>
            </div>
            {archivedWithResources.map(series => (
              <div key={series.id} className="archive-series-resources">
                <div className="download-library-series-head">
                  <h4>{series.title || 'Archived Study'}</h4>
                  {series.description && <p>{series.description}</p>}
                </div>
                <div className="resources-list">
                  {(series.resourceLinks ?? []).map(link => (
                    <Link key={link.id} to={`/downloads/${buildArchivedDownloadPageId(series.id, link.id)}`} className="resource-download-card resource-download-card--link">
                      <div className="resource-download-header">
                        {series.imageUrl && (
                          <img src={series.imageUrl} alt={series.title || 'Archived study'} className="resource-link-image" />
                        )}
                        <div className="resource-download-meta">
                          <span className="resource-link-label">{link.label || series.title || 'Download Resource'}</span>
                          {link.description && <p className="resource-link-description">{link.description}</p>}
                          <span className="resource-link-action">Open download page →</span>
                        </div>
                      </div>
                    </Link>
                  ))}
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    </section>
  )
}

function DownloadDetailPage({ content }: { content: SiteContent }) {
  const { id } = useParams<{ id: string }>()
  const resource = resolveDownloadPageResource(content, id)

  if (!resource) {
    return (
      <main className="thanks-page" aria-label="Download not found">
        <div className="thanks-card">
          <p className="eyebrow">Downloads</p>
          <h1>Download not found</h1>
          <p>The download you requested is not available right now.</p>
          <Link to="/resources" className="btn-primary">Back to Downloads</Link>
        </div>
      </main>
    )
  }

  return (
    <main className="thanks-page download-detail-page" aria-label={resource.label}>
      <div className="thanks-card download-detail-card">
        <p className="eyebrow">Downloads</p>
        <h1>{resource.label}</h1>
        <p>{resource.summary}</p>

        {resource.imageUrl && (
          <div className="download-detail-art">
            <img src={resource.imageUrl} alt={resource.label} className="guide-cover-img" />
          </div>
        )}

        {resource.tags.length > 0 && (
          <div className="resource-link-tags">{resource.tags.join(', ')}</div>
        )}

        <div className="download-detail-form-wrap">
          <ResourceDownloadForm resourceId={resource.resourceId} buttonText={resource.buttonText} />
        </div>

        <div className="download-detail-actions">
          {resource.amazonUrl && (
            <a href={resource.amazonUrl} target="_blank" rel="noreferrer" className="btn-secondary">
              {resource.amazonLabel || 'Get it on Amazon'}
            </a>
          )}
          <Link to="/resources" className="btn-secondary">Back to Downloads</Link>
        </div>
      </div>
    </main>
  )
}

function ShareShowButton() {
  const [feedback, setFeedback] = useState('')

  async function handleShare() {
    const shareUrl = window.location.origin
    const shareTitle = 'Verse by Verse with Nate'
    const shareText = 'Check out Verse by Verse with Nate.'
    try {
      if (navigator.share) {
        await navigator.share({ title: shareTitle, text: shareText, url: shareUrl })
        setFeedback('Shared successfully.')
        return
      }
      if (navigator.clipboard?.writeText) {
        await navigator.clipboard.writeText(shareUrl)
        setFeedback('Link copied. Share it with a friend.')
        return
      }
      setFeedback(`Copy this link: ${shareUrl}`)
    } catch {
      setFeedback('Share canceled.')
    }
  }

  return (
    <div className="share-show-wrap">
      <button type="button" className="btn-primary btn-share-show" onClick={handleShare}>
        Share the Show
      </button>
      {feedback && <p className="share-feedback">{feedback}</p>}
    </div>
  )
}

function CustomBlocksSection({ content, page }: { content: SiteContent; page: string }) {
  const blocks = (content.customBlocks ?? []).filter(block => {
    const blockPage = block.page ?? 'downloads'
    return blockPage === page
  })
  if (blocks.length === 0) return null
  return (
    <>
      {blocks.map(block => (
        <section key={block.id} className="section-custom-block" aria-label={block.heading}>
          <div className="section-inner custom-block-inner">
            <h2>{block.heading}</h2>
            <p>{block.body}</p>
          </div>
        </section>
      ))}
    </>
  )
}

function LandingPage({ content }: { content: SiteContent }) {
  const featuredStudy = getHomepageFeaturedStudy(content)

  return (
    <div className="site">
      <SiteHeader content={content} />
      <CustomBlocksSection content={content} page="homepage" />

      {/* ── HERO ── */}
      <section className="hero" aria-label="Show introduction">
        <div className="hero-art">
          <div className="art-glow" aria-hidden="true" />
          <img
            src="/images/podcast-art.jpeg"
            alt="Verse by Verse with Nate podcast artwork"
            className="podcast-art"
          />
        </div>
        <div className="hero-text">
          <p className="eyebrow">{content.eyebrow}</p>
          <h1 className="hero-title">Verse by Verse</h1>
          <p className="with-nate">
            <span className="word-with">with </span>Nate
          </p>
          <div className="rule-divider" aria-hidden="true" />
          <p className="tagline">{content.heroTagline}</p>
          <div className="hero-ctas">
            <a
              href={content.platformSpotifyUrl || '/spotify'}
              target="_blank"
              rel="noreferrer"
              className="btn-primary"
            >
              <SpotifyIcon />
              {content.heroBtnSpotify || 'Listen on Spotify'}
            </a>
            <Link to="/episodes" className="btn-secondary">{content.heroBtnEpisodes || 'Explore Episodes ↓'}</Link>
            <Link to="/start-here" className="btn-secondary btn-start-here">{content.heroBtnStartHere || 'New here? Start here →'}</Link>
          </div>
        </div>
      </section>

      <section className="section-series" id="series" aria-label="Current series">
        <div className="section-inner">
          <h2 className="section-heading">
            <span className="ornament">✦</span> Current Series{' '}
            <span className="ornament">✦</span>
          </h2>
          <div className="series-grid">
            <article className="series-card">
              <img
                src={content.seriesImageUrl}
                alt={content.seriesTitle}
                className="series-art"
              />
              <div className="series-info">
                <p className="series-label">{content.seriesLabel}</p>
                <h3>{content.seriesTitle}</h3>
                <p>{content.seriesDescription}</p>
                <a
                  href={content.seriesListenUrl || content.platformSpotifyUrl || '/spotify'}
                  target="_blank"
                  rel="noreferrer"
                  className="btn-primary"
                >
                  <SpotifyIcon />
                  {content.seriesListenBtnLabel || 'Listen to Series'}
                </a>
                <Link to="/resources" className="btn-secondary">{content.seriesDownloadsBtnLabel || 'View Downloads'}</Link>
              </div>
            </article>
          </div>
        </div>
      </section>

      <section className="section-home-jump" aria-label="Homepage navigation">
        <div className="section-inner">
          <div className="home-jump-head">
            <p className="eyebrow">{content.whereToNextEyebrow || 'Where to Next'}</p>
            <h2 className="section-heading">{content.whereToNextHeading || 'Choose the page you need.'}</h2>
          </div>
          <div className="home-jump-grid">
            {(content.whereToNextCards ?? []).map(card => (
              <Link key={card.id} to={card.path} className="home-jump-card">
                <h3>{card.title}</h3>
                <p>{card.description}</p>
              </Link>
            ))}
            {featuredStudy && (
              <Link to={`/study/${featuredStudy.slug || ''}`} className="home-jump-card home-jump-card--featured">
                <div className="home-jump-featured-head">
                  <p className="eyebrow">{featuredStudy.homepageEyebrow || 'Study'}</p>
                  {featuredStudy.showNewTag && <span className="home-jump-new-tag">{featuredStudy.newTagLabel || 'NEW'}</span>}
                </div>
                <h3>{featuredStudy.title}</h3>
                <p>{featuredStudy.description || 'Explore this study track with lesson notes, commentary, and guided questions.'}</p>
              </Link>
            )}
          </div>
        </div>
      </section>

      <section className="section-share" aria-label="Share the show">
        <div className="section-inner section-share-inner">
          <div className="share-text">
            <h2 className="section-heading" style={{ textAlign: 'left', marginBottom: '0.75rem' }}>
              {content.shareHeading || 'Help one more person hear the Word this week.'}
            </h2>
            <p className="share-p">{content.shareP || 'Scan the QR code or text the show link to a friend who needs encouragement today.'}</p>
            <ShareShowButton />
          </div>
          <img src="/images/qr-code.jpg" alt="QR code to share the show" className="share-qr" />
        </div>
      </section>

      <SiteFooter content={content} />

      <AnalyticsConsentBanner content={content} />
    </div>
  )
}

function EpisodeDetailPage({ content }: { content: SiteContent }) {
  const { id } = useParams<{ id: string }>()
  const episode = (content.podcastFeaturedLinks ?? []).find(e => e.id === id)
  const [resolvedEmbedUrl, setResolvedEmbedUrl] = useState('')

  useEffect(() => {
    let cancelled = false

    if (!episode) {
      setResolvedEmbedUrl('')
      return () => {
        cancelled = true
      }
    }

    const manualEmbed = episode.embedUrl?.trim() ?? ''
    if (manualEmbed) {
      setResolvedEmbedUrl(manualEmbed)
      return () => {
        cancelled = true
      }
    }

    if (!episode.url) {
      setResolvedEmbedUrl('')
      return () => {
        cancelled = true
      }
    }

    try {
      const urlObj = new URL(episode.url)
      const host = urlObj.hostname.toLowerCase()

      if (host === 'open.spotify.com') {
        const fromUrl = toSpotifyEpisodeEmbedUrl(episode.url)
        if (fromUrl) {
          setResolvedEmbedUrl(fromUrl)
          return () => {
            cancelled = true
          }
        }
      }
    } catch {
      // ignore
    }

    if (!isLikelySpotifyEpisodeUrl(episode.url)) {
      setResolvedEmbedUrl('')
      return () => {
        cancelled = true
      }
    }

    setResolvedEmbedUrl('')
    fetch(`/api/spotify/embed-url?url=${encodeURIComponent(episode.url)}`)
      .then(r => (r.ok ? r.json() : Promise.reject(new Error('embed resolve failed'))))
      .then((data: { embedUrl?: string }) => {
        if (cancelled) return
        setResolvedEmbedUrl(data.embedUrl?.trim() ?? '')
      })
      .catch(() => {
        if (cancelled) return
        setResolvedEmbedUrl('')
      })

    return () => {
      cancelled = true
    }
  }, [episode])

  if (!episode) {
    return (
      <div className="site">
        <SiteHeader content={content} />
        <section className="section-player">
          <div className="section-inner" style={{ textAlign: 'center', padding: '4rem 1rem' }}>
            <h2>Episode not found</h2>
            <p>This episode highlight doesn't exist or may have been removed.</p>
            <Link to="/episodes" className="btn-primary" style={{ marginTop: '1.5rem', display: 'inline-block' }}>← Back to Episodes</Link>
          </div>
        </section>
        <SiteFooter content={content} />
        <AnalyticsConsentBanner content={content} />
      </div>
    )
  }

  const questions = episode.discussionQuestions ?? []

  return (
    <div className="site">
      <SiteHeader content={content} />
      <section className="section-episode-detail" aria-label={episode.title}>
        <div className="section-inner">
          <Link to="/episodes" className="episode-detail-back">← Back to Episodes</Link>

          {episode.episodeNumber && (
            <p className="episode-detail-number">Episode {episode.episodeNumber}</p>
          )}
          <h1 className="episode-detail-title">{episode.title}</h1>
          {episode.summary && <p className="episode-detail-summary">{episode.summary}</p>}

          {resolvedEmbedUrl && (
            <div className="episode-detail-embed">
              <iframe
                src={resolvedEmbedUrl}
                title={episode.title}
                width="100%"
                height="152"
                frameBorder="0"
                allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture"
                loading="lazy"
              />
            </div>
          )}

          {episode.url && (
            <a href={episode.url} target="_blank" rel="noreferrer" className="btn-primary episode-detail-listen-btn">
              Listen on Podcast Platform →
            </a>
          )}

          {episode.showNotes && (
            <div className="episode-detail-show-notes">
              <h2 className="episode-detail-section-heading">Show Notes</h2>
              <p>{episode.showNotes}</p>
            </div>
          )}

          {questions.length > 0 && (
            <div className="episode-detail-questions">
              <h2 className="episode-detail-section-heading">Discussion Questions</h2>
              <ol className="episode-detail-questions-list">
                {questions.map((q, i) => (
                  <li key={i}>{q}</li>
                ))}
              </ol>
            </div>
          )}
        </div>
      </section>
      <SiteFooter content={content} />
      <AnalyticsConsentBanner content={content} />
    </div>
  )
}

function EpisodesPage({ content }: { content: SiteContent }) {
  const [allEpisodes, setAllEpisodes] = useState<Episode[]>([])
  const [loading, setLoading] = useState(true)
  const [failed, setFailed] = useState(false)

  useEffect(() => {
    fetch('/api/episodes/all')
      .then(r => (r.ok ? r.json() : Promise.reject(new Error('fetch failed'))))
      .then((data: { episodes: Episode[] }) => {
        if (data.episodes.length === 0) setFailed(true)
        else setAllEpisodes(data.episodes)
        setLoading(false)
      })
      .catch(() => {
        setFailed(true)
        setLoading(false)
      })
  }, [])

  const archivedSeries = content.archivedSeries ?? []

  const archivedEpisodeNums = new Set<number>(
    archivedSeries.flatMap(s => {
      if (!s.episodeRange) return []
      const nums: number[] = []
      for (let i = s.episodeRange.from; i <= s.episodeRange.to; i++) nums.push(i)
      return nums
    })
  )

  const currentEpisodes = allEpisodes.filter(ep => {
    const num = parseInt(ep.episode, 10)
    return isNaN(num) || !archivedEpisodeNums.has(num)
  })

  function episodesForSeries(series: ArchivedSeries) {
    if (!series.episodeRange) return []
    const { from, to } = series.episodeRange
    return allEpisodes.filter(ep => {
      const num = parseInt(ep.episode, 10)
      return !isNaN(num) && num >= from && num <= to
    })
  }

  function renderEpisodeCards(episodes: Episode[]) {
    return (
      <div className="episode-list">
        {episodes.map((ep, idx) => (
          <a
            key={idx}
            href={ep.link || content.platformSpotifyUrl || '/spotify'}
            target="_blank"
            rel="noreferrer"
            className="episode-card"
          >
            <div className="episode-card-meta">
              {ep.episode && <span className="episode-number">Ep. {ep.episode}</span>}
              {ep.pubDate && <span className="episode-date">{formatPubDate(ep.pubDate)}</span>}
              {ep.duration && <span className="episode-duration">{ep.duration}</span>}
            </div>
            <h3 className="episode-title">{ep.title}</h3>
            {ep.description && <p className="episode-desc">{ep.description}</p>}
            <span className="episode-listen-cta">
              <SpotifyIcon /> Listen →
            </span>
          </a>
        ))}
      </div>
    )
  }

  const spotifyFallback = (
    <div className="embed-wrap">
      <iframe
        title="Verse by Verse with Nate"
        src={SPOTIFY_EMBED_URL}
        width="100%"
        height="352"
        frameBorder="0"
        allowFullScreen
        allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture"
        loading="lazy"
        style={{ borderRadius: '14px' }}
      />
    </div>
  )

  const loadingSkeleton = (
    <div className="episode-list-loading">
      {[1, 2, 3].map(i => <div key={i} className="episode-skeleton" aria-hidden="true" />)}
    </div>
  )

  return (
    <div className="site">
      <SiteHeader content={content} />
      <section className="section-player" aria-label="Current series episodes">
        <div className="section-inner">
          <h2 className="section-heading">
            <span className="ornament">✦</span> {content.seriesLabel || 'Now Playing'}{' '}
            <span className="ornament">✦</span>
          </h2>
          {content.seriesTitle && <p className="episode-series-subtitle">{content.seriesTitle}</p>}
          {loading
            ? loadingSkeleton
            : failed || currentEpisodes.length === 0
              ? spotifyFallback
              : renderEpisodeCards(currentEpisodes)}
          <PlatformButtons content={content} />
          <HeadlinerWidget />
        </div>
      </section>

      {archivedSeries.map(series => {
        const episodes = episodesForSeries(series)
        return (
          <section key={series.id} className="section-player" aria-label={series.title}>
            <div className="section-inner">
              <h2 className="section-heading">
                <span className="ornament">✦</span> {series.label || 'Archived Study'}{' '}
                <span className="ornament">✦</span>
              </h2>
              {series.title && <p className="episode-series-subtitle">{series.title}</p>}
              {series.description && <p className="episode-series-desc">{series.description}</p>}
              {loading
                ? loadingSkeleton
                : episodes.length > 0
                  ? renderEpisodeCards(episodes)
                  : series.listenUrl
                    ? (
                      <a href={series.listenUrl} target="_blank" rel="noreferrer" className="btn-primary" style={{ display: 'inline-block', marginBottom: '1.5rem' }}>
                        Listen to Full Series →
                      </a>
                    )
                    : null}
            </div>
          </section>
        )
      })}

      <PodcastHighlightsSection content={content} />
      <CustomBlocksSection content={content} page="episodes" />
      <SiteFooter content={content} />
      <AnalyticsConsentBanner content={content} />
    </div>
  )
}

function ResourcesPage({ content }: { content: SiteContent }) {
  return (
    <div className="site">
      <SiteHeader content={content} />
      <StudyGuideSection content={content} />
      <DownloadLibrarySection content={content} />
      <CustomBlocksSection content={content} page="downloads" />
      <SiteFooter content={content} />
      <AnalyticsConsentBanner content={content} />
    </div>
  )
}

function AboutPage({ content }: { content: SiteContent }) {
  return (
    <div className="site">
      <SiteHeader content={content} />
      <AboutSection content={content} />
      <CustomBlocksSection content={content} page="about" />
      <SiteFooter content={content} />
      <AnalyticsConsentBanner content={content} />
    </div>
  )
}

function ContactPage({ content }: { content: SiteContent }) {
  return (
    <div className="site">
      <SiteHeader content={content} />
      <ContactSection content={content} />
      <CustomBlocksSection content={content} page="contact" />
      <SiteFooter content={content} />
      <AnalyticsConsentBanner content={content} />
    </div>
  )
}

function StartHerePage({ content }: { content: SiteContent }) {
  return (
    <main className="thanks-page" aria-label="Start Here">
      <div className="thanks-card" style={{ maxWidth: '980px', width: '100%' }}>
        <p className="eyebrow">Verse by Verse with Nate</p>
        <h1>{content.startHereHeading}</h1>
        <p>
          {content.startHereIntro}
        </p>

        <div className="start-grid" style={{ marginTop: '1.25rem' }}>
          <article className="start-card">
            <h3>{content.startHereStep1Title}</h3>
            <p>{content.startHereStep1Body}</p>
            <Link to="/episodes" className="btn-secondary">{content.startHereStep1Cta}</Link>
          </article>
          <article className="start-card">
            <h3>{content.startHereStep2Title}</h3>
            <p>{content.startHereStep2Body}</p>
            <a href="/#qa" className="btn-secondary">{content.startHereStep2Cta}</a>
          </article>
          <article className="start-card">
            <h3>{content.startHereStep3Title}</h3>
            <p>{content.startHereStep3Body}</p>
            <Link to="/contact" className="btn-primary">{content.startHereStep3Cta}</Link>
          </article>
        </div>

        <div style={{ marginTop: '1.4rem' }}>
          <Link to="/" className="btn-secondary">Back to Site</Link>
        </div>
      </div>
    </main>
  )
}

function ThankYouPage() {
  const navigate = useNavigate()
  const [secondsLeft, setSecondsLeft] = useState(15)

  useEffect(() => {
    const timeoutId = window.setTimeout(() => {
      navigate('/')
    }, 15000)

    const intervalId = window.setInterval(() => {
      setSecondsLeft(s => (s > 0 ? s - 1 : 0))
    }, 1000)

    return () => {
      window.clearTimeout(timeoutId)
      window.clearInterval(intervalId)
    }
  }, [navigate])

  return (
    <main className="thanks-page" aria-label="Thank you">
      <div className="thanks-card">
        <p className="eyebrow">Message Received</p>
        <h1>Thank You</h1>
        <p>
          Your message was sent successfully. We appreciate you reaching out and will get back to you soon.
        </p>
        <p className="thanks-countdown">Returning to the main site in {secondsLeft} seconds...</p>
        <button type="button" className="btn-primary" onClick={() => navigate('/')}>
          Go Back Now
        </button>
      </div>
    </main>
  )
}

function SubscribePage() {
  const navigate = useNavigate()
  const [firstName, setFirstName] = useState('')
  const [lastName, setLastName] = useState('')
  const [email, setEmail] = useState('')
  const [honey, setHoney] = useState('')
  const [status, setStatus] = useState<'idle' | 'submitting' | 'error'>('idle')
  const [errorMsg, setErrorMsg] = useState('')

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    setStatus('submitting')
    setErrorMsg('')

    try {
      const res = await fetch('/api/contact', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          firstName,
          lastName,
          email,
          messageType: 'general',
          message: 'Newsletter signup from subscribe page',
          subscribe: true,
          _honey: honey,
        }),
      })

      if (!res.ok) {
        const data = await res.json().catch(() => ({}))
        setErrorMsg((data as { message?: string }).message ?? 'Something went wrong. Please try again.')
        setStatus('error')
        return
      }

      navigate('/subscribe/thanks')
    } catch {
      setErrorMsg('Could not connect. Please try again later.')
      setStatus('error')
    }
  }

  return (
    <main className="thanks-page" aria-label="Subscribe">
      <div className="thanks-card subscribe-card">
        <p className="eyebrow">Verse by Verse with Nate</p>
        <h1>Subscribe for Updates</h1>
        <p>
          Get ministry updates and new episode announcements by email.
        </p>

        <form className="contact-form subscribe-form" onSubmit={handleSubmit} noValidate>
          <input
            type="text"
            className="contact-honeypot"
            tabIndex={-1}
            autoComplete="off"
            aria-hidden="true"
            value={honey}
            onChange={e => setHoney(e.target.value)}
          />
          <label>
            First Name
            <input
              type="text"
              name="firstName"
              required
              autoComplete="given-name"
              value={firstName}
              onChange={e => setFirstName(e.target.value)}
            />
          </label>
          <label>
            Last Name
            <input
              type="text"
              name="lastName"
              required
              autoComplete="family-name"
              value={lastName}
              onChange={e => setLastName(e.target.value)}
            />
          </label>
          <label>
            Email
            <input
              type="email"
              name="email"
              required
              autoComplete="email"
              value={email}
              onChange={e => setEmail(e.target.value)}
            />
          </label>

          {status === 'error' && <p className="contact-error">{errorMsg}</p>}

          <button type="submit" className="btn-primary" disabled={status === 'submitting'}>
            {status === 'submitting' ? 'Subscribing…' : 'Subscribe'}
          </button>
          <Link to="/" className="btn-secondary">Back to Site</Link>
        </form>
      </div>
    </main>
  )
}

function SubscribeThankYouPage() {
  return (
    <main className="thanks-page" aria-label="Subscription confirmed">
      <div className="thanks-card">
        <p className="eyebrow">Verse by Verse with Nate</p>
        <h1>You are subscribed</h1>
        <p>
          Thank you for subscribing. You will receive future ministry updates and episode announcements.
        </p>
        <Link to="/" className="btn-primary">Back to Site</Link>
      </div>
    </main>
  )
}

function LegalPage({ title, body }: { title: string; body: string[] }) {
  return (
    <main className="thanks-page" aria-label={title}>
      <div className="thanks-card">
        <p className="eyebrow">Verse by Verse with Nate</p>
        <h1>{title}</h1>
        {body.map((line, idx) => (
          <p key={`${title}-${idx}`}>{line}</p>
        ))}
        <Link to="/" className="btn-primary">Back to Site</Link>
      </div>
    </main>
  )
}

function AdminShell({ content, onSave }: { content: SiteContent; onSave: (c: SiteContent) => void }) {
  const [status, setStatus] = useState<'checking' | 'authenticated' | 'unauthenticated' | 'misconfigured'>('checking')
  const [password, setPassword] = useState('')
  const [errorMsg, setErrorMsg] = useState('')
  const [submitting, setSubmitting] = useState(false)
  // TOTP two-step state
  const [totpRequired, setTotpRequired] = useState(false)
  const [pendingToken, setPendingToken] = useState('')
  const [totpCode, setTotpCode] = useState('')

  useEffect(() => {
    fetch('/api/admin-auth/status')
      .then(r => (r.ok ? r.json() : Promise.reject(new Error('Status failed'))))
      .then(data => {
        const next = data as { authenticated?: boolean; configured?: boolean }
        if (next.configured === false) {
          setStatus('misconfigured')
          return
        }
        setStatus(next.authenticated ? 'authenticated' : 'unauthenticated')
      })
      .catch(() => {
        setStatus('unauthenticated')
      })
  }, [])

  async function handleLogin(e: React.FormEvent) {
    e.preventDefault()
    setSubmitting(true)
    setErrorMsg('')
    try {
      const res = await fetch('/api/admin-auth/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ password }),
      })
      const data = await res.json().catch(() => ({})) as { ok?: boolean; totpRequired?: boolean; pendingToken?: string; message?: string }
      if (!res.ok) {
        setErrorMsg(data.message ?? 'Login failed.')
        setSubmitting(false)
        return
      }
      if (data.totpRequired && data.pendingToken) {
        setPendingToken(data.pendingToken)
        setTotpRequired(true)
        setPassword('')
        setSubmitting(false)
        return
      }
      setStatus('authenticated')
      setPassword('')
    } catch {
      setErrorMsg('Login failed.')
    } finally {
      setSubmitting(false)
    }
  }

  async function handleTotpVerify(e: React.FormEvent) {
    e.preventDefault()
    setSubmitting(true)
    setErrorMsg('')
    try {
      const res = await fetch('/api/admin-auth/totp-verify', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ pendingToken, code: totpCode }),
      })
      const data = await res.json().catch(() => ({})) as { ok?: boolean; usedRecoveryCode?: boolean; remainingRecoveryCodes?: number; message?: string }
      if (!res.ok) {
        setErrorMsg(data.message ?? 'Invalid code.')
        setSubmitting(false)
        return
      }
      setStatus('authenticated')
      setTotpCode('')
    } catch {
      setErrorMsg('Verification failed.')
    } finally {
      setSubmitting(false)
    }
  }

  function handleBackToPassword() {
    setTotpRequired(false)
    setPendingToken('')
    setTotpCode('')
    setErrorMsg('')
  }

  async function handleLogout() {
    try {
      await fetch('/api/admin-auth/logout', { method: 'POST' })
    } finally {
      setStatus('unauthenticated')
      setTotpRequired(false)
      setPendingToken('')
    }
  }

  if (status === 'authenticated') {
    return <AdminPage content={content} onSave={onSave} onLogout={handleLogout} />
  }

  return (
    <main className="admin-auth-page" aria-label="Admin sign in">
      <div className="admin-auth-card">
        <p className="eyebrow">Admin Access</p>
        <h1>{status === 'misconfigured' ? 'Admin Not Configured' : 'Sign in to Admin'}</h1>
        {status === 'checking' && <p className="admin-auth-note">Checking session...</p>}
        {status === 'misconfigured' && (
          <p className="admin-auth-note">Set the ADMIN_PASSWORD environment variable on the server to enable admin login.</p>
        )}
        {status === 'unauthenticated' && !totpRequired && (
          <form className="admin-auth-form" onSubmit={handleLogin}>
            <label>
              Password
              <input
                type="password"
                value={password}
                onChange={e => setPassword(e.target.value)}
                autoComplete="current-password"
                required
              />
            </label>
            {errorMsg && <p className="admin-auth-error">{errorMsg}</p>}
            <button type="submit" className="btn-primary" disabled={submitting}>
              {submitting ? 'Signing In…' : 'Sign In'}
            </button>
            <Link to="/" className="btn-secondary">Back to Site</Link>
          </form>
        )}
        {status === 'unauthenticated' && totpRequired && (
          <form className="admin-auth-form" onSubmit={handleTotpVerify}>
            <p className="admin-auth-note">Enter the 6-digit code from your authenticator app, or one of your recovery codes.</p>
            <label>
              Code
              <input
                type="text"
                inputMode="numeric"
                value={totpCode}
                onChange={e => setTotpCode(e.target.value)}
                autoComplete="one-time-code"
                placeholder="000000 or XXXX-XXXX-XXXX"
                autoFocus
                required
              />
            </label>
            {errorMsg && <p className="admin-auth-error">{errorMsg}</p>}
            <button type="submit" className="btn-primary" disabled={submitting}>
              {submitting ? 'Verifying…' : 'Verify'}
            </button>
            <button type="button" className="btn-secondary" onClick={handleBackToPassword}>Back</button>
          </form>
        )}
      </div>
    </main>
  )
}

function QuestionsPage({ content }: { content: SiteContent }) {
  return (
    <main className="thanks-page" aria-label="Questions and Answers">
      <div className="thanks-card" style={{ maxWidth: '1000px', width: '100%' }}>
        <QASection />
        <CustomBlocksSection content={content} page="questions" />
        <div style={{ marginTop: '2rem', textAlign: 'center' }}>
          <Link to="/" className="btn-secondary">Back to Site</Link>
        </div>
      </div>
    </main>
  )
}

function PreviewPage() {
  const [content, setContent] = useState<SiteContent | null>(null)
  const [status, setStatus] = useState<'loading' | 'ready' | 'error'>('loading')
  const [previewView, setPreviewView] = useState<string>('homepage')

  useEffect(() => {
    fetch('/api/admin-content?source=draft')
      .then(r => (r.ok ? r.json() : Promise.reject(new Error('Preview failed'))))
      .then(data => {
        if (data?.siteContent) {
          setContent({ ...DEFAULTS, ...data.siteContent })
          setStatus('ready')
          return
        }
        setStatus('error')
      })
      .catch(() => {
        setStatus('error')
      })
  }, [])

  // Listen for live content updates + view from the admin parent frame
  useEffect(() => {
    function handleMessage(e: MessageEvent) {
      if (e.origin !== window.location.origin) return
      if (e.data?.type === 'admin-preview-content' && e.data.content) {
        setContent({ ...DEFAULTS, ...e.data.content })
        setStatus('ready')
        if (e.data.view) setPreviewView(e.data.view)
      }
    }
    window.addEventListener('message', handleMessage)
    return () => window.removeEventListener('message', handleMessage)
  }, [])

  if (status === 'loading') {
    return (
      <main className="thanks-page" aria-label="Draft preview loading">
        <div className="thanks-card">
          <p className="eyebrow">Admin Preview</p>
          <h1>Loading draft preview...</h1>
          <p>Only signed-in admins can view this page.</p>
        </div>
      </main>
    )
  }

  if (status === 'error' || !content) {
    return (
      <main className="thanks-page" aria-label="Draft preview unavailable">
        <div className="thanks-card">
          <p className="eyebrow">Admin Preview</p>
          <h1>Draft preview unavailable</h1>
          <p>Sign into admin and save a draft first.</p>
          <Link to="/admin" className="btn-primary">Back to Admin</Link>
        </div>
      </main>
    )
  }

  if (previewView === 'start-here') return <StartHerePage content={content} />
  if (previewView === 'about') return <AboutPage content={content} />
  if (previewView === 'contact') return <ContactPage content={content} />
  if (previewView === 'current-series' || previewView === 'archived-series' || previewView === 'episode-highlights') {
    return <EpisodesPage content={content} />
  }
  return <LandingPage content={content} />
}

export default function App() {
  const [content, setContent] = useState<SiteContent>(DEFAULTS)
  const navigate = useNavigate()
  const location = useLocation()

  useEffect(() => {
    fetch('/api/admin-content')
      .then(r => (r.ok ? r.json() : null))
      .then(data => {
        if (data?.siteContent) {
          setContent(c => ({ ...c, ...data.siteContent }))
        }
      })
      .catch(() => {})
  }, [])

  useEffect(() => {
    if (location.pathname !== '/' || !location.hash) return

    const legacyHashRouteMap: { [key: string]: string } = {
      '#listen': '/episodes',
      '#about': '/about',
      '#qa': '/questions',
      '#contact': '/contact',
      '#series': '/resources',
      '#archives': '/resources',
      '#resources': '/resources',
      '#start-here': '/start-here',
    }

    const redirectPath = legacyHashRouteMap[location.hash.toLowerCase()]
    if (!redirectPath) return

    navigate(redirectPath, { replace: true })
  }, [location.hash, location.pathname, navigate])

  useEffect(() => {
    const seo = content.seo ?? DEFAULTS.seo

    const ensureMeta = (selector: string, createAttrs: { [key: string]: string }) => {
      const found = document.head.querySelector(selector)
      if (found) return found as HTMLMetaElement
      const meta = document.createElement('meta')
      Object.entries(createAttrs).forEach(([key, value]) => {
        meta.setAttribute(key, value)
      })
      document.head.appendChild(meta)
      return meta
    }

    const ensureCanonical = () => {
      const found = document.head.querySelector('link[rel="canonical"]')
      if (found) return found as HTMLLinkElement
      const link = document.createElement('link')
      link.setAttribute('rel', 'canonical')
      document.head.appendChild(link)
      return link
    }

    document.title = seo.title || DEFAULTS.seo.title
    ensureMeta('meta[name="description"]', { name: 'description' }).setAttribute('content', seo.description || DEFAULTS.seo.description)
    ensureMeta('meta[name="robots"]', { name: 'robots' }).setAttribute('content', seo.robotsPolicy || DEFAULTS.seo.robotsPolicy)
    ensureMeta('meta[property="og:title"]', { property: 'og:title' }).setAttribute('content', seo.ogTitle || seo.title || DEFAULTS.seo.ogTitle)
    ensureMeta('meta[property="og:description"]', { property: 'og:description' }).setAttribute('content', seo.ogDescription || seo.description || DEFAULTS.seo.ogDescription)
    ensureMeta('meta[property="og:image"]', { property: 'og:image' }).setAttribute('content', seo.ogImage || DEFAULTS.seo.ogImage)
    ensureMeta('meta[property="og:url"]', { property: 'og:url' }).setAttribute('content', seo.canonicalUrl || DEFAULTS.seo.canonicalUrl)
    ensureCanonical().setAttribute('href', seo.canonicalUrl || DEFAULTS.seo.canonicalUrl)
  }, [content])

  return (
    <>
      <Routes>
        <Route path="/" element={<LandingPage content={content} />} />
      <Route path="/start-here" element={<StartHerePage content={content} />} />
        <Route path="/study" element={<StudyLandingPage content={content} />} />
        <Route path="/study/:studySlug" element={<ColossiansStudyIndexPage content={content} />} />
        <Route path="/study/:studySlug/notes" element={<ColossiansStudyNotesPage content={content} />} />
        <Route path="/study/:studySlug/:sectionId" element={<ColossiansStudySectionPage content={content} />} />
      <Route path="/episodes" element={<EpisodesPage content={content} />} />
      <Route path="/episodes/:id" element={<EpisodeDetailPage content={content} />} />
      <Route path="/resources" element={<ResourcesPage content={content} />} />
      <Route path="/downloads/:id" element={<DownloadDetailPage content={content} />} />
      <Route path="/about" element={<AboutPage content={content} />} />
      <Route path="/contact" element={<ContactPage content={content} />} />
      <Route path="/questions" element={<QuestionsPage content={content} />} />
      <Route path="/thanks" element={<ThankYouPage />} />
      <Route path="/subscribe" element={<SubscribePage />} />
      <Route path="/subscribe/thanks" element={<SubscribeThankYouPage />} />
      <Route path="/admin" element={<AdminShell content={content} onSave={setContent} />} />
      <Route path="/preview" element={<PreviewPage />} />
      <Route
        path="/privacy"
        element={(
          <LegalPage
            title={content.legal?.privacyTitle ?? DEFAULTS.legal.privacyTitle}
            body={content.legal?.privacyBody ?? DEFAULTS.legal.privacyBody}
          />
        )}
      />
      <Route
        path="/terms"
        element={(
          <LegalPage
            title={content.legal?.termsTitle ?? DEFAULTS.legal.termsTitle}
            body={content.legal?.termsBody ?? DEFAULTS.legal.termsBody}
          />
        )}
      />
    </Routes>
    <BackToTopButton />
  </>
)
}

function BackToTopButton() {
  const [visible, setVisible] = useState(false)

  useEffect(() => {
    const onScroll = () => setVisible(window.scrollY > 320)
    window.addEventListener('scroll', onScroll)
    onScroll()
    return () => window.removeEventListener('scroll', onScroll)
  }, [])

  if (!visible) return null

  return (
    <button
      type="button"
      className="back-to-top"
      onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
      aria-label="Scroll back to top"
    >
      ↑ Top
    </button>
  )
}
