import { Prisma, type ProposalStatus } 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, clampWorkflowStep, computeWorkflowCompletionPercent, computeWorkflowGate, type ProposalWorkflowState } from "@/lib/proposals/workflow-state";

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

function parseWorkflowState(value: unknown): ProposalWorkflowState | null {
  const parsed = ProposalWorkflowStateSchema.safeParse(value);
  if (!parsed.success) {
    return null;
  }

  return {
    ...parsed.data,
    step: clampWorkflowStep(parsed.data.step),
  };
}

function nextStatusFromDraft(progressStatus: ProposalStatus, completionPercent: number): ProposalStatus {
  if (completionPercent <= 0 || progressStatus !== "DRAFT") {
    return progressStatus;
  }

  return canTransitionProposalStatus(progressStatus, "IN_PROGRESS") ? "IN_PROGRESS" : progressStatus;
}

export async function GET(_: 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,
        currentStep: true,
        completionPercent: true,
        readyForSubmissionAt: true,
        workflowDraft: true,
      },
    });

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

    const workflow = parseWorkflowState(proposal.workflowDraft);
    const gate = workflow ? computeWorkflowGate(workflow) : null;

    return NextResponse.json({
      ok: true,
      proposal: {
        id: proposal.id,
        status: proposal.status,
        currentStep: proposal.currentStep,
        completionPercent: proposal.completionPercent,
        readyForSubmissionAt: proposal.readyForSubmissionAt ? proposal.readyForSubmissionAt.toISOString() : null,
      },
      workflow,
      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 cargar el flujo de trabajo." }, { status: 400 });
  }
}

export async function PATCH(request: 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 body = (await request.json()) as Record<string, unknown>;
    const workflow = parseWorkflowState(body.workflow);

    if (!workflow) {
      return NextResponse.json({ error: "Workflow invalido." }, { status: 400 });
    }

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

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

    const gate = computeWorkflowGate(workflow);
    const completionPercent = computeWorkflowCompletionPercent(workflow);
    const nextStatus = nextStatusFromDraft(proposal.status, completionPercent);

    const updated = await prisma.proposal.update({
      where: { id: proposal.id },
      data: {
        workflowDraft: workflow as Prisma.InputJsonValue,
        currentStep: workflow.step,
        completionPercent,
        ...(proposal.status !== nextStatus ? { status: nextStatus } : {}),
        ...(gate.allReady ? {} : { readyForSubmissionAt: null }),
      },
      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 guardar el flujo de trabajo." }, { status: 400 });
  }
}

