import { NextResponse } from 'next/server'
import { timingSafeEqual } from 'node:crypto'
import { db } from '@/lib/db'

// Callback invoked by the home-Mac wrapper script. Shares the
// IDENTIFY_CALLBACK_SECRET with the identify endpoint — single-user infra
// so reusing the token is fine.
//
// Body fields:
//   status         "RUNNING" | "SUCCEEDED" | "FAILED"   (required)
//   transcript     string                                (optional — set after whisper)
//   resultItemIds  string[]                              (optional — set on SUCCEEDED)
//   reasoning      string                                (optional — short explanation)
//   errorMessage   string                                (optional)
//   logTail        string                                (optional — last ~4KB of log)

const STATUS_SET = new Set(['RUNNING', 'SUCCEEDED', 'FAILED'])

export async function POST(
  req: Request,
  { params }: { params: Promise<{ id: string }> },
) {
  if (!isAuthorized(req)) {
    return new NextResponse('Unauthorized', { status: 401 })
  }

  const { id } = await params
  if (!/^[0-9a-f-]{36}$/i.test(id)) {
    return new NextResponse('Bad id', { status: 400 })
  }

  let body: {
    status?: string
    transcript?: string
    resultItemIds?: unknown
    reasoning?: string
    errorMessage?: string
    logTail?: string
  }
  try {
    body = await req.json()
  } catch {
    return new NextResponse('Bad JSON', { status: 400 })
  }

  const status = body.status?.toUpperCase()
  if (!status || !STATUS_SET.has(status)) {
    return new NextResponse('Bad status', { status: 400 })
  }

  const now = new Date()
  const data: Record<string, unknown> = { status }
  if (status === 'RUNNING') data.runningAt = now
  if (status === 'SUCCEEDED' || status === 'FAILED') data.finishedAt = now
  if (typeof body.transcript === 'string') data.transcript = body.transcript.slice(0, 8000)
  if (typeof body.reasoning === 'string') data.reasoning = body.reasoning.slice(0, 4000)
  if (typeof body.errorMessage === 'string') data.errorMessage = body.errorMessage.slice(0, 1000)
  if (typeof body.logTail === 'string') data.logTail = body.logTail.slice(0, 8000)
  if (Array.isArray(body.resultItemIds)) {
    const cleaned = body.resultItemIds
      .filter((x): x is string => typeof x === 'string' && /^[0-9a-f-]{36}$/i.test(x))
      .slice(0, 50)
    data.resultItemIds = cleaned
  }

  try {
    await db.aISearchSession.update({ where: { id }, data })
  } catch {
    return new NextResponse('Session not found', { status: 404 })
  }

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

function isAuthorized(req: Request): boolean {
  const expected = process.env.IDENTIFY_CALLBACK_SECRET
  if (!expected) return false
  const header = req.headers.get('authorization') || ''
  const m = header.match(/^Bearer\s+(.+)$/i)
  if (!m) return false
  const provided = m[1]
  const a = Buffer.from(provided)
  const b = Buffer.from(expected)
  if (a.length !== b.length) return false
  return timingSafeEqual(a, b)
}
