import { NextResponse } from 'next/server'
import { z } from 'zod'
import { db } from '@/lib/db'
import { getSession } from '@/lib/auth'
import { saveAudio } from '@/lib/media'

export const runtime = 'nodejs'
export const dynamic = 'force-dynamic'

// POST /api/digest/reply — ask something of a digest, typed or spoken.
//
// Session auth: this is Eric talking, and the owner recorded here is who
// anything created later will belong to.
//
// It only QUEUES. The model runs on the mini, so the answer arrives on the next
// poll rather than in this response — and a spoken question is not even read
// here, because whisper lives on the mini too. The UI shows it as pending so
// the delay is visible rather than looking like a dropped request.
//
// Accepts JSON (typed) or multipart (spoken), because the two inputs are the
// same request with a different body and splitting them into two endpoints
// would mean two of everything downstream.
export async function POST(req: Request) {
  const session = await getSession()
  if (!session) return NextResponse.json({ error: 'unauthorized' }, { status: 401 })

  let digestId = ''
  let prompt = ''
  let audioPath: string | null = null
  let audioMime: string | null = null

  if ((req.headers.get('content-type') || '').includes('multipart/form-data')) {
    const form = await req.formData()
    digestId = String(form.get('digestId') || '')
    prompt = String(form.get('prompt') || '').trim()
    const audio = form.get('audio')
    if (audio instanceof File && audio.size > 0) {
      audioMime = audio.type || 'audio/webm'
      audioPath = await saveAudio(Buffer.from(await audio.arrayBuffer()), audioMime)
    }
  } else {
    const raw = await req.json().catch(() => null)
    const parsed = z.object({
      digestId: z.string().min(1).max(64),
      prompt: z.string().min(1).max(2000),
    }).safeParse(raw)
    if (!parsed.success) return NextResponse.json({ error: 'digestId and prompt required' }, { status: 400 })
    digestId = parsed.data.digestId
    prompt = parsed.data.prompt.trim()
  }

  if (!digestId) return NextResponse.json({ error: 'digestId required' }, { status: 400 })
  // One or the other must carry the question. Silence with no text is a stray
  // tap on the mic, not a request, and queueing it would spend a Claude call to
  // discover there was nothing to answer.
  if (!prompt && !audioPath) return NextResponse.json({ error: 'say or type something' }, { status: 400 })

  const digest = await db.digest.findUnique({ where: { id: digestId }, select: { id: true } })
  if (!digest) return NextResponse.json({ error: 'no such digest' }, { status: 404 })

  const reply = await db.digestReply.create({
    data: { digestId: digest.id, ownerId: session.userId, prompt, audioPath, audioMime },
    select: { id: true, prompt: true, status: true, createdAt: true },
  })
  return NextResponse.json({ ok: true, reply })
}
