import { NextResponse } from 'next/server'
import { getSession } from '@/lib/auth'
import { db } from '@/lib/db'
import { visible } from '@/lib/scope'

export const runtime = 'nodejs'

// GET /api/captures/:id — full detail for the capture view.
export async function GET(_req: Request, { params }: { params: Promise<{ id: string }> }) {
  const session = await getSession()
  if (!session) return NextResponse.json({ error: 'unauthorized' }, { status: 401 })

  const { id } = await params
  const c = await db.capture.findFirst({
    where: { id, ...visible.capture(session.userId) },
    include: {
      images: { select: { id: true } },
      reminders: { include: { list: { select: { name: true } } }, orderBy: { createdAt: 'asc' } },
      events: { orderBy: { startsAt: 'asc' } },
      thoughts: { orderBy: { createdAt: 'asc' } },
    },
  })
  if (!c) return NextResponse.json({ error: 'not found' }, { status: 404 })

  interface ChoreRouted { title?: string; members?: string[]; pointValue?: number; penaltyPoints?: number }
  interface SaleItemRouted { category?: string; quantity?: number; unitPrice?: number }
  interface SaleRouted { customerName?: string; phone?: string; email?: string; items?: SaleItemRouted[]; fulfillmentDate?: string; fulfillmentTime?: string; fulfillmentMethod?: string; notes?: string }
  interface ExpenseItemRouted { category?: string; quantity?: number; unitCost?: number }
  interface ExpenseRouted { totalCost?: number; source?: string; date?: string; items?: ExpenseItemRouted[]; notes?: string }
  interface PointsRouted { members?: string[]; points?: number; reason?: string }
  interface PrayerRouted { content?: string; members?: unknown; verseReference?: string }
interface PraiseRouted { content?: string; members?: unknown }
interface TimerRouted { speech?: string; title?: string; inMinutes?: number; repeat?: string }
  interface FailureRouted { kind?: string; label?: string; reason?: string }
  const routing = (c.routing as { summary?: string; completed?: { title?: string }[]; updated?: { title?: string }[]; deleted?: { title?: string }[]; chores?: ChoreRouted[]; sales?: SaleRouted[]; expenses?: ExpenseRouted[]; points?: PointsRouted[]; timers?: TimerRouted[]; prayers?: PrayerRouted[]; praises?: PraiseRouted[]; failures?: FailureRouted[]; answer?: string } | null) || null
  const titles = (a?: { title?: string }[]) => (Array.isArray(a) ? a.map(x => ({ title: x.title || '' })) : [])
  return NextResponse.json({
    id: c.id,
    status: c.status,
    textNote: c.textNote,
    transcript: c.transcript,
    summary: routing?.summary || null,
    completed: titles(routing?.completed),
    updated: titles(routing?.updated),
    deleted: titles(routing?.deleted),
    hasAudio: !!c.audioPath,
    error: c.error,
    createdAt: c.createdAt,
    processedAt: c.processedAt,
    imageIds: c.images.map(i => i.id),
    reminders: c.reminders.map(r => ({
      id: r.id, title: r.title, notes: r.notes, dueDate: r.dueDate,
      priority: r.priority, list: r.list?.name || null, externalId: r.externalId,
    })),
    events: c.events.map(e => ({
      id: e.id, title: e.title, notes: e.notes, location: e.location,
      startsAt: e.startsAt, endsAt: e.endsAt, allDay: e.allDay, calendar: e.calendar,
      recurrence: e.recurrence,
    })),
    thoughts: c.thoughts.map(t => ({ id: t.id, body: t.body, tags: t.tags })),
    chores: Array.isArray(routing?.chores)
      ? routing.chores.map(ch => ({
          title: ch.title || '',
          members: Array.isArray(ch.members) ? ch.members.filter(m => typeof m === 'string') : [],
          pointValue: typeof ch.pointValue === 'number' ? ch.pointValue : null,
          penaltyPoints: typeof ch.penaltyPoints === 'number' ? ch.penaltyPoints : null,
        }))
      : [],
    sales: Array.isArray(routing?.sales)
      ? routing.sales.map(s => ({
          customerName: s.customerName || '',
          phone: typeof s.phone === 'string' ? s.phone : null,
          email: typeof s.email === 'string' ? s.email : null,
          items: Array.isArray(s.items)
            ? s.items
                .filter(it => typeof it.category === 'string')
                .map(it => ({
                  category: it.category || '',
                  quantity: typeof it.quantity === 'number' ? it.quantity : 0,
                  unitPrice: typeof it.unitPrice === 'number' ? it.unitPrice : null,
                }))
            : [],
          fulfillmentDate: typeof s.fulfillmentDate === 'string' ? s.fulfillmentDate : null,
          fulfillmentTime: typeof s.fulfillmentTime === 'string' ? s.fulfillmentTime : null,
          fulfillmentMethod: typeof s.fulfillmentMethod === 'string' ? s.fulfillmentMethod : null,
          notes: typeof s.notes === 'string' ? s.notes : null,
        }))
      : [],
    expenses: Array.isArray(routing?.expenses)
      ? routing.expenses.map(e => ({
          totalCost: typeof e.totalCost === 'number' ? e.totalCost : null,
          source: typeof e.source === 'string' ? e.source : null,
          date: typeof e.date === 'string' ? e.date : null,
          items: Array.isArray(e.items)
            ? e.items
                .filter(it => typeof it.category === 'string')
                .map(it => ({
                  category: it.category || '',
                  quantity: typeof it.quantity === 'number' ? it.quantity : null,
                  unitCost: typeof it.unitCost === 'number' ? it.unitCost : null,
                }))
            : [],
          notes: typeof e.notes === 'string' ? e.notes : null,
        }))
      : [],
    points: Array.isArray(routing?.points)
      ? routing.points.map(p => ({
          members: Array.isArray(p.members) ? p.members.filter(m => typeof m === 'string') : [],
          points: typeof p.points === 'number' ? p.points : 0,
          reason: typeof p.reason === 'string' ? p.reason : null,
        }))
      : [],
    timers: Array.isArray(routing?.timers)
      ? routing.timers.map(t => ({
          speech: typeof t.speech === 'string' ? t.speech : '',
          title: typeof t.title === 'string' ? t.title : null,
          inMinutes: typeof t.inMinutes === 'number' ? t.inMinutes : null,
          repeat: typeof t.repeat === 'string' ? t.repeat : null,
        }))
      : [],
    prayers: Array.isArray(routing?.prayers)
      ? routing.prayers.map(pr => ({
          content: typeof pr.content === 'string' ? pr.content : '',
          members: Array.isArray(pr.members) ? pr.members.filter((m): m is string => typeof m === 'string') : [],
          verseReference: typeof pr.verseReference === 'string' ? pr.verseReference : null,
        }))
      : [],
    praises: Array.isArray(routing?.praises)
      ? routing.praises.map(pr => ({
          content: typeof pr.content === 'string' ? pr.content : '',
          members: Array.isArray(pr.members) ? pr.members.filter((m): m is string => typeof m === 'string') : [],
        }))
      : [],
    failures: Array.isArray(routing?.failures)
      ? routing.failures.map(f => ({
          kind: typeof f.kind === 'string' ? f.kind : '',
          label: typeof f.label === 'string' ? f.label : '',
          reason: typeof f.reason === 'string' ? f.reason : '',
        }))
      : [],
    // Present when the capture was a question — the router answered instead of
    // filing anything, so this IS the result.
    answer: typeof routing?.answer === 'string' && routing.answer.trim() ? routing.answer.trim() : null,
  })
}

// PATCH /api/captures/:id — edit the transcript and/or typed note (correction).
// DELETE /api/captures/:id — discard a capture for good.
//
// Exists because a capture could previously be created and never removed, and
// one that cannot be processed had no way out: on 2026-10-06 a five-byte
// recording failed, Re-process could only fail it again, and the only advice
// available was to wait six hours for a health card to stop mentioning it.
//
// Safe to cascade: Attachment is the only thing that hangs off a capture by a
// required link, so the images go with it. Reminders, events and thoughts
// reference it through an OPTIONAL sourceId, so they survive and merely lose
// the back-link to where they came from — deleting the input must never delete
// what it produced.
export async function DELETE(_req: Request, { params }: { params: Promise<{ id: string }> }) {
  const session = await getSession()
  if (!session) return NextResponse.json({ error: 'unauthorized' }, { status: 401 })

  const { id } = await params
  const capture = await db.capture.findFirst({ where: { id, ...visible.capture(session.userId) }, select: { id: true } })
  if (!capture) return NextResponse.json({ error: 'not found' }, { status: 404 })

  await db.capture.delete({ where: { id } })
  return NextResponse.json({ ok: true })
}

export async function PATCH(req: Request, { params }: { params: Promise<{ id: string }> }) {
  const session = await getSession()
  if (!session) return NextResponse.json({ error: 'unauthorized' }, { status: 401 })

  const { id } = await params
  const body = await req.json().catch(() => ({}))
  const data: { transcript?: string; textNote?: string } = {}
  if (typeof body.transcript === 'string') data.transcript = body.transcript
  if (typeof body.textNote === 'string') data.textNote = body.textNote
  if (Object.keys(data).length === 0) return NextResponse.json({ error: 'nothing to update' }, { status: 400 })

  const { count } = await db.capture.updateMany({ where: { id, ...visible.capture(session.userId) }, data })
  if (count === 0) return NextResponse.json({ error: 'not found' }, { status: 404 })
  return NextResponse.json({ ok: true })
}
