import { NextResponse } from 'next/server'
import { db } from '@/lib/db'
import { userFromCaptureToken } from '@/lib/ingest-auth'
import { saveAudio, saveImage } from '@/lib/media'
import { triggerAgent } from '@/lib/agent-trigger'

export const runtime = 'nodejs'

// POST /api/ingest/capture — create a capture from a client that cannot hold a
// session cookie: an iOS Shortcut, a watch, a bot.
//
// Auth: Authorization: Bearer <personal capture token>. The token identifies a
// USER, not a device, so the capture is owned by that account and inherits its
// capabilities — an ingest token can never reach an integration the account
// itself cannot. Mint one with scripts/mint-capture-token.mjs.
//
// Body, either:
//   application/json      { "text": "..." }
//   multipart/form-data   audio=<file>, images=<file>…, text=<string>
//
// Returns { id } immediately; processing is async, exactly as the web recorder.

export async function POST(req: Request) {
  const user = await userFromCaptureToken(req)
  if (!user) return NextResponse.json({ error: 'unauthorized' }, { status: 401 })

  const ctype = req.headers.get('content-type') || ''
  let text: string | null = null
  let audioPath: string | null = null
  let audioMime: string | null = null
  let durationMs: number | null = null
  const savedImages: { path: string; thumbPath: string; width: number; height: number }[] = []

  if (ctype.includes('application/json')) {
    const body = await req.json().catch(() => ({}))
    text = typeof body?.text === 'string' ? body.text.trim() || null : null
  } else {
    const form = await req.formData().catch(() => null)
    if (!form) return NextResponse.json({ error: 'bad body' }, { status: 400 })
    text = ((form.get('text') as string | null) || '').trim() || null

    // Shortcuts' "Record Audio" yields m4a; a Telegram voice note would be ogg.
    // Either is fine — process-capture.sh normalises through ffmpeg regardless.
    const audio = form.get('audio') ?? form.get('file')
    if (audio instanceof File && audio.size > 0) {
      audioMime = audio.type || 'audio/mp4'
      audioPath = await saveAudio(Buffer.from(await audio.arrayBuffer()), audioMime)
      const d = Number(form.get('durationMs'))
      durationMs = Number.isFinite(d) && d > 0 ? d : null
    }
    for (const f of form.getAll('images')) {
      if (f instanceof File && f.size > 0) savedImages.push(await saveImage(Buffer.from(await f.arrayBuffer())))
    }
  }

  if (!audioPath && !text && savedImages.length === 0) {
    return NextResponse.json({ error: 'empty capture' }, { status: 400 })
  }

  const capture = await db.capture.create({
    data: {
      ownerId: user.id,
      source: 'INGEST',
      audioPath,
      audioMime,
      durationMs,
      textNote: text,
      images: { create: savedImages.map(i => ({ path: i.path, thumbPath: i.thumbPath, width: i.width, height: i.height })) },
    },
    select: { id: true },
  })

  // Best-effort, same contract as the web recorder: a trigger failure leaves the
  // capture PENDING for the stuck-capture sweep rather than failing the upload.
  triggerAgent(capture.id).catch(err =>
    console.error(`[ingest ${capture.id}] agent trigger failed:`, err?.message || err))

  return NextResponse.json({ id: capture.id, ok: true }, { status: 201 })
}
