import { Prisma } from "@prisma/client";
import { NextResponse } from "next/server";
import { requireAdminApiUser } from "@/lib/auth/admin";
import { prisma } from "@/lib/prisma";
import { canTransitionProposalStatus } from "@/lib/proposals/status";
import { ProposalWorkflowStateSchema, computeWorkflowCompletionPercent, computeWorkflowGate } from "@/lib/proposals/workflow-state";

function isSchemaNotReadyError(error: unknown) {
  return error instanceof Prisma.PrismaClientKnownRequestError && (error.code === "P2021" || error.code === "P2022");
}

export async function POST(_: Request, context: { params: Promise<{ id: string }> }) {
  const user = await requireAdminApiUser();

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

  try {
    const { id } = await context.params;

    const proposal = await prisma.proposal.findFirst({
      where: {
        id,
        userId: user.id,
      },
      select: {
        id: true,
        status: true,
        workflowDraft: true,
      },
    });

    if (!proposal) {
      return NextResponse.json({ error: "Propuesta no encontrada." }, { status: 404 });
    }

    if (proposal.status === "ARCHIVED") {
      return NextResponse.json({ error: "No puedes marcar una propuesta archivada." }, { status: 400 });
    }

    const parsedWorkflow = ProposalWorkflowStateSchema.safeParse(proposal.workflowDraft);
    if (!parsedWorkflow.success) {
      return NextResponse.json({ error: "No hay flujo persistido valido para validar la propuesta." }, { status: 400 });
    }

    const workflow = parsedWorkflow.data;
    const gate = computeWorkflowGate(workflow);
    if (!gate.allReady) {
      return NextResponse.json(
        {
          error: "No se cumplen todos los requisitos para marcar como Lista para Envio.",
          gate,
        },
        { status: 400 },
      );
    }

    const completionPercent = computeWorkflowCompletionPercent(workflow);
    const persistedWorkflow = {
      ...workflow,
      readyMarked: true,
      step: 6,
    };

    const updated = await prisma.$transaction(async (tx) => {
      if (proposal.status === "DRAFT") {
        if (!canTransitionProposalStatus("DRAFT", "IN_PROGRESS")) {
          throw new Error("Transicion invalida de estatus.");
        }

        await tx.proposal.update({
          where: { id: proposal.id },
          data: { status: "IN_PROGRESS" },
        });
      }

      const current = await tx.proposal.findUnique({
        where: { id: proposal.id },
        select: { status: true },
      });

      if (!current) {
        throw new Error("Propuesta no encontrada.");
      }

      if (current.status !== "SUBMITTED" && !canTransitionProposalStatus(current.status, "SUBMITTED")) {
        throw new Error("Transicion invalida de estatus.");
      }

      return tx.proposal.update({
        where: { id: proposal.id },
        data: {
          status: "SUBMITTED",
          workflowDraft: persistedWorkflow as Prisma.InputJsonValue,
          completionPercent,
          currentStep: 6,
          readyForSubmissionAt: new Date(),
        },
        select: {
          id: true,
          status: true,
          currentStep: true,
          completionPercent: true,
          readyForSubmissionAt: true,
        },
      });
    });

    return NextResponse.json({
      ok: true,
      proposal: {
        id: updated.id,
        status: updated.status,
        currentStep: updated.currentStep,
        completionPercent: updated.completionPercent,
        readyForSubmissionAt: updated.readyForSubmissionAt ? updated.readyForSubmissionAt.toISOString() : null,
      },
      gate,
    });
  } catch (error) {
    if (isSchemaNotReadyError(error)) {
      return NextResponse.json(
        { error: "La base de datos aun no tiene los campos de persistencia de Gestion de Licitaciones. Ejecuta prisma migrate para continuar." },
        { status: 503 },
      );
    }

    return NextResponse.json({ error: "No fue posible marcar la propuesta como lista para envio." }, { status: 400 });
  }
}
