import { z } from "zod";
import { NextResponse } from "next/server";
import { requireAdminApiUser } from "@/lib/auth/admin";
import { callOpenAiJsonSchema } from "@/lib/ai/openai";
import { storeAiSuggestionFromEnvelope } from "@/lib/ai/suggestions";
import { buildInstitutionalDossier, getAuditSimulationDetail, getLatestInstitutionalDossierSnapshot, listAuditSimulationsForUser } from "@/lib/audits/server";

const M10_PROMPT_VERSION = "m10_findings_v1";

const M10FindingsSchema = z.object({
  auditorLikelyFindings: z
    .array(
      z.object({
        area: z.string().min(4).max(120),
        finding: z.string().min(8).max(500),
        severity: z.enum(["alto", "medio", "bajo"]),
      }),
    )
    .max(20),
  missingEvidence: z.array(z.string().min(6).max(280)).max(20),
  topRisks: z.array(z.string().min(6).max(280)).max(12),
  remediationPlan: z
    .array(
      z.object({
        step: z.string().min(8).max(420),
        priority: z.enum(["alta", "media", "baja"]),
        ownerSuggestion: z.string().min(3).max(120),
        targetDate: z.string().min(4).max(40),
      }),
    )
    .max(20),
  confidence: z.enum(["low", "medium", "high"]),
});

const M10FindingsJsonSchema = {
  type: "object",
  additionalProperties: false,
  required: ["auditorLikelyFindings", "missingEvidence", "topRisks", "remediationPlan", "confidence"],
  properties: {
    auditorLikelyFindings: {
      type: "array",
      items: {
        type: "object",
        additionalProperties: false,
        required: ["area", "finding", "severity"],
        properties: {
          area: { type: "string" },
          finding: { type: "string" },
          severity: { type: "string", enum: ["alto", "medio", "bajo"] },
        },
      },
    },
    missingEvidence: {
      type: "array",
      items: { type: "string" },
    },
    topRisks: {
      type: "array",
      items: { type: "string" },
    },
    remediationPlan: {
      type: "array",
      items: {
        type: "object",
        additionalProperties: false,
        required: ["step", "priority", "ownerSuggestion", "targetDate"],
        properties: {
          step: { type: "string" },
          priority: { type: "string", enum: ["alta", "media", "baja"] },
          ownerSuggestion: { type: "string" },
          targetDate: { type: "string" },
        },
      },
    },
    confidence: { type: "string", enum: ["low", "medium", "high"] },
  },
} as const;

function parseString(value: unknown) {
  return typeof value === "string" ? value.trim() : "";
}

async function resolveSimulation(userId: string, simulationId: string) {
  if (simulationId) {
    return getAuditSimulationDetail(userId, simulationId);
  }

  const simulations = await listAuditSimulationsForUser(userId);
  return simulations.find((simulation) => simulation.status === "COMPLETED") ?? simulations[0] ?? null;
}

export async function POST(request: Request) {
  const user = await requireAdminApiUser();

  if (!user) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const body = (await request.json().catch(() => ({}))) as Record<string, unknown>;
  const simulationId = parseString(body.simulationId);
  const simulation = await resolveSimulation(user.id, simulationId);

  if (!simulation) {
    return NextResponse.json({ error: "No hay simulaciones disponibles para generar dictamen IA." }, { status: 400 });
  }

  const latestDossier = await getLatestInstitutionalDossierSnapshot(user.id);
  const dossier = latestDossier?.payload ?? (await buildInstitutionalDossier(user.id));

  const condensedContext = {
    simulation: {
      id: simulation.id,
      name: simulation.name,
      auditType: simulation.auditType,
      status: simulation.status,
      overallScore: simulation.overallScore,
      completedAt: simulation.completedAt,
      sections: simulation.sections,
    },
    dossier: {
      generatedAt: dossier.generatedAt,
      summary: dossier.summary,
      components: dossier.components,
    },
  };

  const systemPrompt = [
    "Eres auditor preventivo especializado en contratacion publica y cumplimiento documental en Mexico.",
    "Simula hallazgos probables de una revision formal sin modificar resultados deterministas existentes.",
    "Debes responder solo JSON valido en espanol.",
  ].join(" ");

  const userPrompt = [
    "Contexto actual de simulacion y expediente institucional:",
    JSON.stringify(condensedContext),
    "",
    "Genera:",
    "- auditorLikelyFindings: hallazgos probables por area y severidad.",
    "- missingEvidence: evidencia concreta faltante.",
    "- topRisks: riesgos principales priorizados.",
    "- remediationPlan: plan de remediacion con prioridad, responsable sugerido y fecha objetivo.",
  ].join("\n");

  const envelope = await callOpenAiJsonSchema({
    promptVersion: M10_PROMPT_VERSION,
    systemPrompt,
    userPrompt,
    outputSchema: M10FindingsSchema,
    schemaName: "m10_audit_findings",
    jsonSchema: M10FindingsJsonSchema as unknown as Record<string, unknown>,
    model: process.env.OPENAI_M10_MODEL?.trim() || undefined,
  });

  const payload =
    envelope.data ??
    ({
      auditorLikelyFindings: [],
      missingEvidence: [],
      topRisks: [],
      remediationPlan: [],
      confidence: envelope.confidence ?? "low",
    } satisfies z.infer<typeof M10FindingsSchema>);

  const persisted = await storeAiSuggestionFromEnvelope({
    userId: user.id,
    moduleKey: "M10",
    featureKey: "audit_findings",
    subjectType: "audit_simulation",
    subjectId: simulation.id,
    inputForHash: condensedContext,
    envelope,
    responsePayload: payload,
  });

  return NextResponse.json({
    ok: true,
    simulationId: simulation.id,
    ...payload,
    suggestionId: persisted.suggestionId,
    meta: {
      engine: envelope.engine,
      model: envelope.model,
      usage: envelope.usage,
      warnings: envelope.warnings,
      confidence: envelope.confidence,
    },
  });
}
