'use client'

import { useCallback, useEffect, useRef, useState } from 'react'
import Link from 'next/link'
import { ChevronLeft, Loader2, RefreshCw, Save, ListTodo, CalendarClock, Lightbulb, Sparkles, CheckCircle2, CalendarClock as Reschedule, Trash2, ClipboardList, ShoppingCart, Receipt, Star, AlertTriangle, AlarmClock, HandHeart, PartyPopper } from 'lucide-react'

interface Reminder { id: string; title: string; notes: string | null; dueDate: string | null; priority: number | null; list: string | null }
interface EventItem { id: string; title: string; notes: string | null; location: string | null; startsAt: string; endsAt: string | null; allDay: boolean; calendar: string | null; recurrence: string | null }
interface Thought { id: string; body: string; tags: string[] }
interface Chore { title: string; members: string[]; pointValue: number | null; penaltyPoints: number | null; announceAt?: string | null }
/** "18:30" -> "6:30pm" — the capture detail echoes what was said, not HH:MM. */
function to12h(hm: string): string {
  const m = /^(\d{2}):(\d{2})$/.exec(hm)
  if (!m) return hm
  const h = Number(m[1])
  const suffix = h < 12 ? 'am' : 'pm'
  const h12 = h % 12 === 0 ? 12 : h % 12
  return `${h12}:${m[2]}${suffix}`
}

interface SaleItem { category: string; quantity: number; unitPrice: number | null; lineTotal?: number | null }
interface Sale { customerName: string; phone: string | null; email: string | null; items: SaleItem[]; tradeValue?: number | null; tradeNote?: string | null; fulfillmentDate: string | null; fulfillmentTime: string | null; fulfillmentMethod: string | null; notes: string | null }
interface ExpenseItem { category: string; quantity: number | null; unitCost: number | null }
interface Expense { totalCost: number | null; source: string | null; date: string | null; items: ExpenseItem[]; notes: string | null }
interface PointsAward { members: string[]; points: number; reason: string | null }
interface TimerSet { speech: string; title?: string | null; inMinutes?: number | null; repeat?: string | null }
interface Prayer { content: string; members?: string[]; verseReference?: string | null }
interface Praise { content: string; members?: string[] }
interface Failure { kind: string; label: string; reason: string }
const TIMER_CADENCE: Record<string, string> = {
  once: 'said once',
  insistent: 'repeated for 5 min',
  untilDismissed: 'repeats until dismissed',
}
interface Detail {
  id: string; status: 'PENDING' | 'PROCESSING' | 'DONE' | 'FAILED'
  textNote: string | null; transcript: string | null; summary: string | null
  hasAudio: boolean; error: string | null; createdAt: string
  imageIds: string[]; reminders: Reminder[]; events: EventItem[]; thoughts: Thought[]; chores: Chore[]; sales: Sale[]; expenses: Expense[]; points: PointsAward[]; timers: TimerSet[]; prayers: Prayer[]; praises: Praise[]; failures: Failure[]
  /** Set when the capture was a question rather than something to file. */
  answer?: string | null
  completed: { title: string }[]
  updated: { title: string }[]
  deleted: { title: string }[]
}

function fmt(iso: string | null, allDay = false): string {
  if (!iso) return ''
  const d = new Date(iso)
  return allDay
    ? d.toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric' })
    : d.toLocaleString(undefined, { weekday: 'short', month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' })
}

export function CaptureDetail({ id }: { id: string }) {
  const [d, setD] = useState<Detail | null>(null)
  const [transcript, setTranscript] = useState('')
  const [dirty, setDirty] = useState(false)
  const [busy, setBusy] = useState<'save' | 'reprocess' | 'discard' | null>(null)
  // The reprocess reply used to be dropped on the floor, so a refusal looked
  // exactly like a success that had not finished yet.
  const [actionError, setActionError] = useState<string | null>(null)
  const pollRef = useRef<ReturnType<typeof setInterval> | null>(null)

  const load = useCallback(async () => {
    const res = await fetch(`/api/captures/${id}`, { cache: 'no-store' })
    if (!res.ok) return
    const data: Detail = await res.json()
    setD(data)
    setTranscript(prev => (dirty ? prev : data.transcript || ''))
  }, [id, dirty])

  useEffect(() => {
    load()
    pollRef.current = setInterval(load, 3000)
    return () => { if (pollRef.current) clearInterval(pollRef.current) }
  }, [load])

  const save = useCallback(async () => {
    setBusy('save')
    await fetch(`/api/captures/${id}`, {
      method: 'PATCH', headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ transcript }),
    })
    setDirty(false); setBusy(null); load()
  }, [id, transcript, load])

  const reprocess = useCallback(async () => {
    setBusy('reprocess')
    if (dirty) {
      await fetch(`/api/captures/${id}`, {
        method: 'PATCH', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ transcript }),
      })
      setDirty(false)
    }
    const res = await fetch(`/api/captures/${id}/reprocess`, { method: 'POST' })
    if (!res.ok) {
      const body = await res.json().catch(() => ({}))
      setActionError(body?.error || `re-process failed (${res.status})`)
    } else {
      setActionError(null)
    }
    setBusy(null); load()
  }, [id, dirty, transcript, load])

  const discard = useCallback(async () => {
    setBusy('discard')
    const res = await fetch(`/api/captures/${id}`, { method: 'DELETE' })
    if (res.ok) { window.location.href = '/' ; return }
    const body = await res.json().catch(() => ({}))
    setActionError(body?.error || `could not discard (${res.status})`)
    setBusy(null)
  }, [id])

  if (!d) return <div className="p-8 text-center text-muted-foreground"><Loader2 className="h-5 w-5 animate-spin mx-auto" /></div>

  const processing = d.status === 'PENDING' || d.status === 'PROCESSING'

  return (
    <div className="min-h-screen max-w-md mx-auto flex flex-col">
      <header className="safe-top px-4 pb-3 flex items-center gap-2">
        <Link href="/" className="inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground">
          <ChevronLeft className="h-4 w-4" /> Dashboard
        </Link>
        <span className="ml-auto text-xs text-muted-foreground">{new Date(d.createdAt).toLocaleString()}</span>
      </header>

      <main className="flex-1 px-4 pb-10 space-y-5">
        {/* What the AI decided + did with this capture */}
        {!processing && (
          <div className="rounded-xl border border-primary/25 bg-primary/5 p-4">
            <div className="text-xs font-semibold text-primary mb-1.5 flex items-center gap-1.5">
              <Sparkles className="h-3.5 w-3.5" /> Action taken
            </div>
            {d.summary && <p className="text-sm mb-2">{d.summary}</p>}
            {d.failures?.length > 0 && (
              <div className="mb-2 rounded-lg border border-destructive/30 bg-destructive/5 p-2.5">
                <div className="flex items-center gap-1.5 text-xs font-semibold text-destructive mb-1">
                  <AlertTriangle className="h-3.5 w-3.5" /> Couldn&rsquo;t complete {d.failures.length} item{d.failures.length > 1 ? 's' : ''}
                </div>
                <ul className="space-y-0.5">
                  {d.failures.map((f, i) => (
                    <li key={i} className="text-xs">
                      <span className="font-medium">{f.label}</span>
                      <span className="text-muted-foreground"> — {f.reason}</span>
                    </li>
                  ))}
                </ul>
                <p className="text-[11px] text-muted-foreground mt-1">Fix the wording and Re-process, or do it manually in the app.</p>
              </div>
            )}
            {(d.completed.length > 0 || d.updated.length > 0 || d.deleted.length > 0) && (
              <div className="mb-2 space-y-1">
                {d.completed.map((c, i) => (
                  <div key={`c${i}`} className="flex items-center gap-1.5 text-sm text-emerald-600">
                    <CheckCircle2 className="h-4 w-4 shrink-0" /> Completed: <span className="font-medium">{c.title}</span>
                  </div>
                ))}
                {d.updated.map((c, i) => (
                  <div key={`u${i}`} className="flex items-center gap-1.5 text-sm text-blue-600">
                    <Reschedule className="h-4 w-4 shrink-0" /> Updated: <span className="font-medium">{c.title}</span>
                  </div>
                ))}
                {d.deleted.map((c, i) => (
                  <div key={`d${i}`} className="flex items-center gap-1.5 text-sm text-destructive">
                    <Trash2 className="h-4 w-4 shrink-0" /> Deleted: <span className="font-medium">{c.title}</span>
                  </div>
                ))}
              </div>
            )}
            {(() => {
              const parts: { icon: typeof ListTodo; label: string }[] = []
              if (d.reminders.length) parts.push({ icon: ListTodo, label: `${d.reminders.length} reminder${d.reminders.length > 1 ? 's' : ''}` })
              if (d.events.length) parts.push({ icon: CalendarClock, label: `${d.events.length} event${d.events.length > 1 ? 's' : ''}` })
              if (d.thoughts.length) parts.push({ icon: Lightbulb, label: `${d.thoughts.length} thought${d.thoughts.length > 1 ? 's' : ''}` })
              if (d.chores?.length) parts.push({ icon: ClipboardList, label: `${d.chores.length} chore${d.chores.length > 1 ? 's' : ''}` })
              if (d.sales?.length) parts.push({ icon: ShoppingCart, label: `${d.sales.length} sale${d.sales.length > 1 ? 's' : ''}` })
              if (d.expenses?.length) parts.push({ icon: Receipt, label: `${d.expenses.length} expense${d.expenses.length > 1 ? 's' : ''}` })
              if (d.points?.length) parts.push({ icon: Star, label: `${d.points.length} point adjustment${d.points.length > 1 ? 's' : ''}` })
              if (d.timers?.length) parts.push({ icon: AlarmClock, label: `${d.timers.length} timer${d.timers.length > 1 ? 's' : ''}` })
              if (d.prayers?.length) parts.push({ icon: HandHeart, label: `${d.prayers.length} prayer${d.prayers.length > 1 ? 's' : ''}` })
              if (d.praises?.length) parts.push({ icon: PartyPopper, label: `${d.praises.length} praise${d.praises.length > 1 ? 's' : ''}` })
              const acted = d.completed.length + d.updated.length + d.deleted.length
              if (d.answer) {
                // A question. Nothing was filed, and saying "nothing created"
                // under an answer reads as a failure rather than the point.
                return <p className="text-sm whitespace-pre-wrap">{d.answer}</p>
              }
              if (parts.length === 0 && acted === 0) {
                return <p className="text-sm text-muted-foreground">No reminders or events created.</p>
              }
              if (parts.length === 0) return null
              return (
                <div className="flex flex-wrap gap-2">
                  {parts.map((p, i) => {
                    const Icon = p.icon
                    return (
                      <span key={i} className="inline-flex items-center gap-1.5 text-xs font-medium rounded-full bg-card border border-border px-2.5 py-1">
                        <Icon className="h-3.5 w-3.5 text-primary" /> {p.label}
                      </span>
                    )
                  })}
                </div>
              )
            })()}
          </div>
        )}

        {d.hasAudio && (
          // eslint-disable-next-line jsx-a11y/media-has-caption
          <audio controls src={`/api/audio/${d.id}`} className="w-full" />
        )}

        {d.imageIds.length > 0 && (
          <div className="flex flex-wrap gap-2">
            {d.imageIds.map(iid => (
              // eslint-disable-next-line @next/next/no-img-element
              <img key={iid} src={`/api/image/${iid}?thumb=1`} alt="" className="w-20 h-20 rounded-lg object-cover border border-border" />
            ))}
          </div>
        )}

        {d.textNote && (
          <div>
            <div className="text-xs font-semibold text-muted-foreground mb-1">Typed note</div>
            <p className="text-sm rounded-lg bg-muted px-3 py-2">{d.textNote}</p>
          </div>
        )}

        {/* Transcript — editable for correction */}
        <div>
          <div className="text-xs font-semibold text-muted-foreground mb-1 flex items-center gap-2">
            Transcript {processing && <Loader2 className="h-3 w-3 animate-spin" />}
          </div>
          <textarea
            value={transcript}
            onChange={e => { setTranscript(e.target.value); setDirty(true) }}
            rows={4}
            placeholder={d.hasAudio ? 'Transcribing…' : 'No transcript'}
            className="w-full rounded-lg border border-input bg-background px-3 py-2 text-base resize-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
          />
          <div className="flex items-center gap-2 mt-2">
            <button
              onClick={save}
              disabled={!dirty || busy !== null}
              className="inline-flex items-center gap-1.5 text-sm rounded-lg border border-border px-3 h-9 disabled:opacity-40 hover:bg-muted"
            >
              {busy === 'save' ? <Loader2 className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />} Save
            </button>
            <button
              onClick={reprocess}
              disabled={busy !== null || processing}
              className="inline-flex items-center gap-1.5 text-sm font-medium rounded-lg bg-primary text-primary-foreground px-3 h-9 disabled:opacity-40 hover:bg-primary/90"
            >
              {busy === 'reprocess' ? <Loader2 className="h-4 w-4 animate-spin" /> : <RefreshCw className="h-4 w-4" />}
              Re-process
            </button>
            <button
              onClick={discard}
              disabled={busy !== null || processing}
              title="Delete this capture for good"
              className="inline-flex items-center gap-1.5 text-sm rounded-lg border border-border px-3 h-9 ml-auto text-muted-foreground disabled:opacity-40 hover:bg-destructive/10 hover:text-destructive"
            >
              {busy === 'discard' ? <Loader2 className="h-4 w-4 animate-spin" /> : <Trash2 className="h-4 w-4" />} Discard
            </button>
          </div>
          {actionError && <p className="text-sm text-destructive mt-2">{actionError}</p>}
          <p className="text-xs text-muted-foreground mt-1.5">Fix the transcript, then re-process to rebuild reminders/events from the corrected text.</p>
        </div>

        {d.status === 'FAILED' && d.error && (
          <p className="text-sm text-destructive">{d.error}</p>
        )}

        {/* What it became */}
        {d.reminders.length > 0 && (
          <Section icon={ListTodo} title="Reminders">
            {d.reminders.map(r => (
              <Item key={r.id} title={r.title} meta={[r.list, fmt(r.dueDate)].filter(Boolean).join(' · ')} note={r.notes} />
            ))}
          </Section>
        )}
        {d.events.length > 0 && (
          <Section icon={CalendarClock} title="Calendar">
            {d.events.map(e => (
              <Item key={e.id} title={e.title} meta={[e.calendar, fmt(e.startsAt, e.allDay), e.recurrence, e.location].filter(Boolean).join(' · ')} note={e.notes} />
            ))}
          </Section>
        )}
        {d.thoughts.length > 0 && (
          <Section icon={Lightbulb} title="Thoughts">
            {d.thoughts.map(t => (
              <Item key={t.id} title={t.body} meta={t.tags.join(', ')} />
            ))}
          </Section>
        )}
        {d.chores?.length > 0 && (
          <Section icon={ClipboardList} title="Chores app">
            {d.chores.map((ch, i) => (
              <Item
                key={i}
                title={ch.title}
                meta={[
                  ch.members.length ? `for ${ch.members.join(', ')}` : 'all kids · up for grabs',
                  `${ch.pointValue ?? 1} pt${(ch.pointValue ?? 1) === 1 ? '' : 's'}`,
                  ch.penaltyPoints ? `−${ch.penaltyPoints} if missed` : null,
                  // 24h from the app, said back the way it was spoken.
                  ch.announceAt ? `announces at ${to12h(ch.announceAt)}` : null,
                ].filter(Boolean).join(' · ')}
              />
            ))}
          </Section>
        )}
        {d.sales?.length > 0 && (
          <Section icon={ShoppingCart} title="FlockBase sale">
            {d.sales.map((s, i) => {
              // A stated whole-line total wins over quantity × unitPrice — the same
              // rule FlockBase applies when it creates the sale.
              const lineAmount = (it: SaleItem) =>
                it.lineTotal != null ? it.lineTotal : (it.unitPrice != null ? it.unitPrice * it.quantity : null)
              const total = s.items.reduce((sum, it) => sum + (lineAmount(it) ?? 0), 0)
              const when = [
                s.fulfillmentDate ? new Date(s.fulfillmentDate + 'T00:00:00').toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric' }) : null,
                s.fulfillmentTime || null,
                s.fulfillmentMethod || null,
              ].filter(Boolean).join(' · ')
              return (
                <li key={i} className="rounded-lg border border-border bg-card px-3 py-2">
                  <div className="text-sm font-medium">{s.customerName || '(no name — review)'}</div>
                  {(s.phone || s.email) && (
                    <div className="text-xs text-muted-foreground">{[s.phone, s.email].filter(Boolean).join(' · ')}</div>
                  )}
                  <ul className="mt-1 space-y-0.5">
                    {s.items.map((it, j) => {
                      const amount = lineAmount(it)
                      return (
                        <li key={j} className="text-xs text-muted-foreground flex justify-between gap-2">
                          <span>{it.quantity} × {it.category}{it.unitPrice != null ? ` @ $${it.unitPrice.toFixed(2)}` : ''}</span>
                          {amount != null && <span>${amount.toFixed(2)}</span>}
                        </li>
                      )
                    })}
                  </ul>
                  <div className="text-xs text-muted-foreground mt-1 flex justify-between gap-2">
                    <span>{when || 'PENDING'}</span>
                    {total > 0 && <span className="font-medium text-foreground">${total.toFixed(2)}</span>}
                  </div>
                  {s.tradeValue != null && s.tradeValue > 0 && (
                    <div className="text-xs text-muted-foreground mt-0.5">
                      Traded ${s.tradeValue.toFixed(2)}{s.tradeNote ? ` — ${s.tradeNote}` : ''}
                    </div>
                  )}
                  {s.notes && <div className="text-xs text-muted-foreground mt-0.5">{s.notes}</div>}
                </li>
              )
            })}
          </Section>
        )}
        {d.expenses?.length > 0 && (
          <Section icon={Receipt} title="FlockBase expense">
            {d.expenses.map((e, i) => {
              const when = e.date
                ? new Date(e.date + 'T00:00:00').toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric' })
                : 'today'
              return (
                <li key={i} className="rounded-lg border border-border bg-card px-3 py-2">
                  <div className="flex justify-between gap-2">
                    <span className="text-sm font-medium">{e.source || 'Expense'}</span>
                    {e.totalCost != null && <span className="text-sm font-medium">${e.totalCost.toFixed(2)}</span>}
                  </div>
                  <ul className="mt-1 space-y-0.5">
                    {e.items.map((it, j) => (
                      <li key={j} className="text-xs text-muted-foreground flex justify-between gap-2">
                        <span>{it.quantity != null && it.quantity > 1 ? `${it.quantity} × ` : ''}{it.category}{it.unitCost != null ? ` @ $${it.unitCost.toFixed(2)}` : ''}</span>
                        {it.unitCost != null && it.quantity != null && <span>${(it.unitCost * it.quantity).toFixed(2)}</span>}
                      </li>
                    ))}
                  </ul>
                  <div className="text-xs text-muted-foreground mt-1">{when}</div>
                  {e.notes && <div className="text-xs text-muted-foreground mt-0.5">{e.notes}</div>}
                </li>
              )
            })}
          </Section>
        )}
        {d.timers?.length > 0 && (
          <Section icon={AlarmClock} title="Spoken timers">
            {d.timers.map((t, i) => (
              <Item
                key={i}
                title={t.title || t.speech}
                meta={`${typeof t.inMinutes === 'number' && t.inMinutes > 0 ? `in ${t.inMinutes} min` : 'now'} · says "${t.speech}"${TIMER_CADENCE[t.repeat || ''] ? ` · ${TIMER_CADENCE[t.repeat || '']}` : ''}`}
              />
            ))}
          </Section>
        )}
        {d.prayers?.length > 0 && (
          <Section icon={HandHeart} title="Prayer queue">
            {d.prayers.map((pr, i) => (
              <Item
                key={i}
                title={pr.content}
                // Say where it went. A prayer that vanishes into an app you did
                // not open needs to tell you it is waiting, not just that it
                // was filed.
                meta={[
                  pr.members?.length ? `for ${pr.members.join(', ')}` : null,
                  pr.verseReference || null,
                  'waiting for the next prayer session',
                ].filter(Boolean).join(' · ')}
              />
            ))}
          </Section>
        )}
        {d.praises?.length > 0 && (
          <Section icon={PartyPopper} title="Praise queue">
            {d.praises.map((pr, i) => (
              <Item
                key={i}
                title={pr.content}
                meta={[
                  pr.members?.length ? `for ${pr.members.join(', ')}` : null,
                  'waiting for the next prayer session',
                ].filter(Boolean).join(' · ')}
              />
            ))}
          </Section>
        )}
        {d.points?.length > 0 && (
          <Section icon={Star} title="Chore points">
            {d.points.map((p, i) => (
              <Item
                key={i}
                title={`${p.points > 0 ? '+' : ''}${p.points} pt${Math.abs(p.points) === 1 ? '' : 's'} → ${p.members.join(', ')}`}
                meta={p.reason || undefined}
              />
            ))}
          </Section>
        )}
      </main>
    </div>
  )
}

function Section({ icon: Icon, title, children }: { icon: typeof ListTodo; title: string; children: React.ReactNode }) {
  return (
    <div>
      <div className="text-xs font-semibold text-muted-foreground mb-1.5 flex items-center gap-1.5">
        <Icon className="h-3.5 w-3.5" /> {title}
      </div>
      <ul className="space-y-1.5">{children}</ul>
    </div>
  )
}

function Item({ title, meta, note }: { title: string; meta?: string; note?: string | null }) {
  return (
    <li className="rounded-lg border border-border bg-card px-3 py-2">
      <div className="text-sm">{title}</div>
      {meta && <div className="text-xs text-muted-foreground mt-0.5">{meta}</div>}
      {note && <div className="text-xs text-muted-foreground mt-0.5">{note}</div>}
    </li>
  )
}
