import { Prisma } from "@prisma/client";
import { NextResponse } from "next/server";
import { requireAdminApiUser } from "@/lib/auth/admin";
import { prisma } from "@/lib/prisma";
import {
  MAX_PROPOSAL_DOCUMENT_BYTES,
  isAllowedProposalMimeType,
  storeProposalDocument,
} from "@/lib/proposals/storage";

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

function toProposalPayload(
  proposal: {
    id: string;
    title: string;
    issuingEntity: string;
    summary: string;
    status: string;
    sourceLicitationId: string | null;
    createdAt: Date;
    updatedAt: Date;
    documents: Array<{
      id: string;
      fileName: string;
      mimeType: string;
      sizeBytes: number;
      createdAt: Date;
    }>;
  } & {
    currentStep?: number;
    completionPercent?: number;
    readyForSubmissionAt?: Date | null;
  },
) {
  return {
    id: proposal.id,
    title: proposal.title,
    issuingEntity: proposal.issuingEntity,
    summary: proposal.summary,
    currentStep: proposal.currentStep ?? 1,
    completionPercent: proposal.completionPercent ?? 0,
    readyForSubmissionAt: proposal.readyForSubmissionAt ? proposal.readyForSubmissionAt.toISOString() : null,
    status: proposal.status,
    sourceLicitationId: proposal.sourceLicitationId,
    createdAt: proposal.createdAt.toISOString(),
    updatedAt: proposal.updatedAt.toISOString(),
    documents: proposal.documents.map((document) => ({
      id: document.id,
      fileName: document.fileName,
      mimeType: document.mimeType,
      sizeBytes: document.sizeBytes,
      createdAt: document.createdAt.toISOString(),
    })),
  };
}

export async function POST(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 formData = await request.formData();
    const file = formData.get("file");

    if (!(file instanceof File)) {
      return NextResponse.json({ error: "Archivo requerido." }, { status: 400 });
    }

    if (file.size <= 0) {
      return NextResponse.json({ error: "El archivo esta vacio." }, { status: 400 });
    }

    if (file.size > MAX_PROPOSAL_DOCUMENT_BYTES) {
      return NextResponse.json({ error: "El archivo excede el limite de 20MB." }, { status: 400 });
    }

    if (!isAllowedProposalMimeType(file.type)) {
      return NextResponse.json({ error: "Tipo de archivo no permitido (PDF, DOC, DOCX, XLSX, JPG o PNG)." }, { 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 fileBuffer = Buffer.from(await file.arrayBuffer());
    const stored = await storeProposalDocument(user.id, proposal.id, file.name, file.type, fileBuffer);

    await prisma.proposalDocument.create({
      data: {
        proposalId: proposal.id,
        userId: user.id,
        fileName: stored.fileName,
        storedFileName: stored.storedFileName,
        filePath: stored.filePath,
        mimeType: stored.mimeType,
        sizeBytes: stored.sizeBytes,
        checksumSha256: stored.checksumSha256,
      },
    });

    if (proposal.status === "DRAFT") {
      await prisma.proposal.update({
        where: { id: proposal.id },
        data: {
          status: "IN_PROGRESS",
        },
      });
    }

    const updated = await prisma.proposal.findUnique({
      where: { id: proposal.id },
      select: {
        id: true,
        title: true,
        issuingEntity: true,
        summary: true,
        status: true,
        sourceLicitationId: true,
        createdAt: true,
        updatedAt: true,
        documents: {
          orderBy: [{ createdAt: "desc" }],
          select: {
            id: true,
            fileName: true,
            mimeType: true,
            sizeBytes: true,
            createdAt: true,
          },
        },
      },
    });

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

    return NextResponse.json({
      ok: true,
      proposal: toProposalPayload(updated),
    });
  } catch (error) {
    if (isSchemaNotReadyError(error)) {
      return NextResponse.json(
        { error: "La base de datos aun no tiene las tablas de Gestion de Licitaciones. Ejecuta prisma migrate para continuar." },
        { status: 503 },
      );
    }

    return NextResponse.json({ error: "No fue posible subir el documento." }, { status: 400 });
  }
}
