/**
 * POST /api/bureau/launch — quick-launch endpoint for the homepage form.
 *
 * Accepts the same validation as the chat tool's request_investigation but
 * via REST so the QuickLaunch component (homepage) can fire jobs without
 * routing through the chat agent. Validates by kind:
 *   - hypothesis_tournament: requires `question`
 *   - contradiction_scan / outlier_scan / case_report: requires `topic`
 *   - red_team_review / calibrate_hypothesis: requires `hypothesis_id` (H-NNNN)
 *   - witness_analysis: requires `person_id` (kebab-case)
 *   - evidence_chain: requires `doc_id` (optional `chunks`, `claim`)
 *
 * Returns { job_id, status_url, eta_seconds, kind, detective }.
 *
 * Auth: requires an authenticated user when Supabase is configured. The
 * triggered_by field carries the email so audit ties back to a person.
 */
import { NextResponse } from "next/server";
import { pgQuery } from "@/lib/retrieval/db";
import { createClient, isSupabaseConfigured } from "@/lib/supabase/server";

export const runtime = "nodejs";
export const dynamic = "force-dynamic";

const KINDS = new Set([
  "hypothesis_tournament", "evidence_chain", "contradiction_scan",
  "red_team_review", "witness_analysis", "outlier_scan",
  "calibrate_hypothesis", "case_report",
]);

const DETECTIVE: Record<string, string> = {
  hypothesis_tournament: "holmes",
  evidence_chain:        "locard",
  contradiction_scan:    "dupin",
  red_team_review:       "schneier",
  witness_analysis:      "poirot",
  outlier_scan:          "taleb",
  calibrate_hypothesis:  "tetlock",
  case_report:           "case-writer",
};

const ETA: Record<string, number> = {
  hypothesis_tournament: 60,
  evidence_chain:        150,
  contradiction_scan:    60,
  red_team_review:       30,
  witness_analysis:      45,
  outlier_scan:          50,
  calibrate_hypothesis:  30,
  case_report:           180,
};

export async function POST(request: Request) {
  let body: Record<string, unknown>;
  try {
    body = await request.json();
  } catch {
    return NextResponse.json({ error: "invalid_json" }, { status: 400 });
  }
  const kind = String(body.kind ?? "").trim();
  if (!KINDS.has(kind)) {
    return NextResponse.json({ error: "bad_kind", message: `kind must be one of: ${[...KINDS].join(", ")}` }, { status: 400 });
  }

  let triggered_by = "user:anonymous";
  if (isSupabaseConfigured()) {
    const supabase = await createClient();
    const { data: { user } } = await supabase.auth.getUser();
    if (!user) {
      return NextResponse.json({ error: "unauthenticated" }, { status: 401 });
    }
    triggered_by = `user:${user.email ?? user.id}`;
  }

  // Validate per-kind payload + build it.
  const payload: Record<string, unknown> = {};
  switch (kind) {
    case "hypothesis_tournament": {
      const q = String(body.question ?? "").trim();
      if (!q) return NextResponse.json({ error: "question_required" }, { status: 400 });
      payload.question = q;
      if (typeof body.doc_id === "string" && body.doc_id.trim()) payload.doc_id = body.doc_id.trim();
      payload.lang = body.lang === "en" ? "en" : "pt";
      break;
    }
    case "evidence_chain": {
      const doc = String(body.doc_id ?? "").trim();
      if (!doc) return NextResponse.json({ error: "doc_id_required" }, { status: 400 });
      payload.doc_id = doc;
      if (Array.isArray(body.chunks)) {
        payload.chunks = (body.chunks as unknown[]).filter((c): c is string => typeof c === "string");
      }
      if (typeof body.claim === "string" && body.claim.trim()) payload.claim = body.claim.trim();
      break;
    }
    case "contradiction_scan":
    case "outlier_scan":
    case "case_report": {
      const topic = String(body.topic ?? "").trim();
      if (!topic) return NextResponse.json({ error: "topic_required" }, { status: 400 });
      payload.topic = topic;
      if (typeof body.doc_id === "string" && body.doc_id.trim()) payload.doc_id = body.doc_id.trim();
      payload.lang = body.lang === "en" ? "en" : "pt";
      if (kind === "case_report" && typeof body.slug === "string" && /^[a-z0-9][a-z0-9-]*$/.test(body.slug)) {
        payload.slug = body.slug;
      }
      break;
    }
    case "red_team_review":
    case "calibrate_hypothesis": {
      const hyp = String(body.hypothesis_id ?? "").trim();
      if (!/^H-\d{4}$/.test(hyp)) return NextResponse.json({ error: "hypothesis_id_required", message: "format: H-NNNN" }, { status: 400 });
      payload.hypothesis_id = hyp;
      payload.lang = body.lang === "en" ? "en" : "pt";
      break;
    }
    case "witness_analysis": {
      const pid = String(body.person_id ?? "").trim();
      if (!/^[a-z0-9][a-z0-9-]*$/.test(pid)) return NextResponse.json({ error: "person_id_required", message: "kebab-case e.g. 'donald-keyhoe'" }, { status: 400 });
      payload.person_id = pid;
      payload.lang = body.lang === "en" ? "en" : "pt";
      break;
    }
  }

  try {
    const rows = await pgQuery<{ job_id: string }>(
      `INSERT INTO public.investigation_jobs (kind, payload, triggered_by, status)
       VALUES ($1, $2::jsonb, $3, 'queued')
       RETURNING job_id`,
      [kind, JSON.stringify(payload), triggered_by],
    );
    const job_id = rows[0]?.job_id;
    if (!job_id) return NextResponse.json({ error: "insert_failed" }, { status: 500 });
    return NextResponse.json({
      job_id, kind,
      detective: DETECTIVE[kind],
      status: "queued",
      status_url: `/jobs/${job_id}`,
      eta_seconds: ETA[kind] ?? 60,
    });
  } catch (e) {
    return NextResponse.json({ error: "db_unavailable", message: (e as Error).message }, { status: 503 });
  }
}
