import { stat } from 'node:fs/promises'
import { NextResponse } from 'next/server'
import { getSession } from '@/lib/auth'
import { db } from '@/lib/db'
import { visible } from '@/lib/scope'
import { absFromStored } from '@/lib/media'
import { triggerAgent } from '@/lib/agent-trigger'

export const runtime = 'nodejs'

// Matches the floor in /api/captures — below this a file cannot be a recording.
const MIN_AUDIO_BYTES = 2048

// POST /api/captures/:id/reprocess — re-run routing on the (possibly edited)
// transcript. Resets to PENDING and re-triggers the Mac agent, which deletes
// the stale Apple items (via staleExternalIds) and recreates from scratch.
export async function POST(_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, audioPath: true, textNote: true, transcript: true },
  })
  if (!capture) return NextResponse.json({ error: 'not found' }, { status: 404 })

  // Refuse to re-run something that cannot possibly come out differently.
  // Re-process is the right remedy when the AUDIO is fine and the run died —
  // whisper fell over, the token expired, the transcript was edited by hand.
  // It is not a remedy for a take that never recorded, and on 2026-10-06 that
  // distinction cost Eric an afternoon: a five-byte capture failed, he pressed
  // Re-process to clear the warning, and because re-queueing resets queuedAt
  // it restarted the six-hour window the health card reads. The button was a
  // loop — the one thing that looked like a fix was the thing keeping the dot
  // lit, and it would have stayed lit for as long as he kept pressing it.
  const hasWords = Boolean(capture.textNote?.trim() || capture.transcript?.trim())
  let audioBytes = 0
  if (capture.audioPath) {
    try { audioBytes = (await stat(absFromStored(capture.audioPath))).size } catch { audioBytes = 0 }
  }
  if (!hasWords && audioBytes < MIN_AUDIO_BYTES) {
    return NextResponse.json({
      error: capture.audioPath
        ? `nothing to re-process — the recording came through empty (${audioBytes} bytes). Delete this capture; the audio cannot be recovered.`
        : 'nothing to re-process — this capture has no audio and no text.',
    }, { status: 400 })
  }

  await db.capture.update({ where: { id }, data: { status: 'PENDING', error: null, queuedAt: new Date() } })

  triggerAgent(id).catch(err => {
    console.error(`[capture ${id}] reprocess trigger failed:`, err?.message || err)
  })

  return NextResponse.json({ ok: true })
}
