import type { Prisma } from "@prisma/client";
import { NextResponse } from "next/server";
import { requireAdminApiUser } from "@/lib/auth/admin";
import { prisma } from "@/lib/prisma";
import { evaluateDiagnosis, parseDiagnosisAnswers } from "@/lib/legal/diagnosis";
import { LegalDiagnosisAnswerInputSchema } from "@/lib/legal/types";

function parseJsonBody(body: unknown) {
  return typeof body === "object" && body !== null ? (body as Record<string, unknown>) : {};
}

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

function extractContractId(value: unknown) {
  if (typeof value !== "string") {
    return null;
  }

  const normalized = value.trim();
  return normalized ? normalized : null;
}

function logContinuityHandoff(event: string, data: Record<string, unknown>) {
  console.info(
    "[continuity_handoff]",
    JSON.stringify({
      event,
      at: new Date().toISOString(),
      ...data,
    }),
  );
}

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

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

  const body = parseJsonBody(await request.json().catch(() => ({})));
  const parsed = LegalDiagnosisAnswerInputSchema.safeParse(body);

  if (!parsed.success) {
    return NextResponse.json({ error: "Datos de respuesta invalidos." }, { status: 400 });
  }

  const input = parsed.data;
  logContinuityHandoff("m9_diagnosis_answer_received", {
    userId: user.id,
    diagnosisId: input.diagnosisId,
    finalize: Boolean(input.finalize),
  });

  const diagnosis = await prisma.legalDiagnosis.findFirst({
    where: {
      id: input.diagnosisId,
      userId: user.id,
    },
    select: {
      id: true,
      answersJson: true,
      totalSteps: true,
      legalCaseId: true,
    },
  });

  if (!diagnosis) {
    return NextResponse.json({ error: "Diagnostico no encontrado." }, { status: 404 });
  }

  const currentAnswers =
    diagnosis.answersJson && typeof diagnosis.answersJson === "object" && !Array.isArray(diagnosis.answersJson)
      ? (diagnosis.answersJson as Record<string, unknown>)
      : {};

  const mergedAnswers = {
    ...currentAnswers,
    ...input.answers,
  };

  const normalizedAnswers = parseDiagnosisAnswers(mergedAnswers);
  const recommendation = evaluateDiagnosis(normalizedAnswers);
  const nextStep = input.finalize ? diagnosis.totalSteps : Math.min(diagnosis.totalSteps, input.stepIndex + 1);

  let legalCaseId = diagnosis.legalCaseId;
  const persistedContractId = extractContractId(mergedAnswers.contractId);
  logContinuityHandoff("m9_diagnosis_contract_context", {
    userId: user.id,
    diagnosisId: diagnosis.id,
    persistedContractId,
    hasLegalCaseAlready: Boolean(legalCaseId),
  });

  if (input.finalize && !legalCaseId) {
    if (persistedContractId) {
      const ownedContract = await prisma.contractRecord.findFirst({
        where: {
          id: persistedContractId,
          userId: user.id,
        },
        select: {
          id: true,
        },
      });

      if (!ownedContract) {
        return NextResponse.json({ error: "El contrato vinculado al diagnostico ya no esta disponible." }, { status: 400 });
      }
    }

    const createdCase = await prisma.legalCase.create({
      data: {
        userId: user.id,
        contractId: persistedContractId,
        caseType: recommendation.suggestedCaseType,
        severity: recommendation.suggestedSeverity,
        counterparty: stringOrEmpty(mergedAnswers.counterparty) || "Contraparte por validar",
        description: stringOrEmpty(mergedAnswers.description) || "Caso generado desde diagnostico legal asistido.",
        amountAtRisk: normalizedAnswers.amountAtRisk,
        status: "OPEN",
      },
      select: {
        id: true,
      },
    });

    legalCaseId = createdCase.id;
    logContinuityHandoff("m9_case_autocreated_from_diagnosis", {
      userId: user.id,
      diagnosisId: diagnosis.id,
      legalCaseId,
      contractId: persistedContractId,
    });
  }

  const updated = await prisma.legalDiagnosis.update({
    where: {
      id: diagnosis.id,
    },
    data: {
      stepIndex: nextStep,
      answersJson: mergedAnswers as Prisma.InputJsonValue,
      recommendedRouteJson: recommendation as unknown as Prisma.InputJsonValue,
      legalCaseId,
    },
    select: {
      id: true,
      legalCaseId: true,
      stepIndex: true,
      totalSteps: true,
      answersJson: true,
      recommendedRouteJson: true,
      updatedAt: true,
    },
  });

  return NextResponse.json({
    ok: true,
    diagnosis: {
      id: updated.id,
      legalCaseId: updated.legalCaseId,
      stepIndex: updated.stepIndex,
      totalSteps: updated.totalSteps,
      answers: updated.answersJson,
      recommendation: updated.recommendedRouteJson,
      updatedAt: updated.updatedAt.toISOString(),
    },
  });
}
