import { Prisma } from "@prisma/client";
import { NextResponse } from "next/server";
import { requireAdminApiUser } from "@/lib/auth/admin";
import { prisma } from "@/lib/prisma";
import {
  MAX_STRATEGIC_EVIDENCE_BYTES,
  isAllowedEvidenceMimeType,
  storeStrategicEvidenceFile,
} from "@/lib/strategic-diagnostic/evidence-storage";
import { mapSectionKeyToEnum, recomputeStrategicDiagnosticFromStoredData } from "@/lib/strategic-diagnostic/server";
import { STRATEGIC_SECTION_KEYS, type StrategicSectionKey } from "@/lib/strategic-diagnostic/types";

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

  const section = value.trim() as StrategicSectionKey;
  return STRATEGIC_SECTION_KEYS.includes(section) ? section : null;
}

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

  return value.trim();
}

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

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

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

  try {
    const formData = await request.formData();
    const section = parseSection(formData.get("section"));
    const category = parseCategory(formData.get("category"));
    const file = formData.get("file");

    if (!section) {
      return NextResponse.json({ error: "Seccion de evidencia invalida." }, { status: 400 });
    }

    if (!category) {
      return NextResponse.json({ error: "Categoria de evidencia requerida." }, { status: 400 });
    }

    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_STRATEGIC_EVIDENCE_BYTES) {
      return NextResponse.json({ error: "El archivo excede el limite de 10MB." }, { status: 400 });
    }

    if (!isAllowedEvidenceMimeType(file.type)) {
      return NextResponse.json({ error: "Tipo de archivo no permitido (usa PDF, DOC, DOCX, JPG o PNG)." }, { status: 400 });
    }

    const organization = await prisma.organization.findUnique({
      where: { userId: user.id },
      select: {
        id: true,
      },
    });

    if (!organization) {
      return NextResponse.json({ error: "No existe un perfil organizacional para este usuario." }, { status: 400 });
    }

    const fileBuffer = Buffer.from(await file.arrayBuffer());
    const stored = await storeStrategicEvidenceFile(user.id, file.name, file.type, fileBuffer);
    const row = await prisma.strategicDiagnosticEvidenceDocument.create({
      data: {
        organizationId: organization.id,
        userId: user.id,
        section: mapSectionKeyToEnum(section),
        category,
        fileName: stored.fileName,
        storedFileName: stored.storedFileName,
        filePath: stored.filePath,
        mimeType: stored.mimeType,
        sizeBytes: stored.sizeBytes,
        checksumSha256: stored.checksumSha256,
      },
      select: {
        id: true,
        category: true,
        fileName: true,
        filePath: true,
        mimeType: true,
        sizeBytes: true,
        createdAt: true,
      },
    });

    const snapshot = await recomputeStrategicDiagnosticFromStoredData(user.id);

    return NextResponse.json({
      ok: true,
      document: {
        id: row.id,
        section,
        category: row.category,
        fileName: row.fileName,
        filePath: row.filePath,
        mimeType: row.mimeType,
        sizeBytes: row.sizeBytes,
        createdAt: row.createdAt.toISOString(),
      },
      payload: snapshot,
    });
  } catch (error) {
    if (isSchemaNotReadyError(error)) {
      return NextResponse.json(
        { error: "La base de datos aun no tiene las tablas de evidencias de Modulo 2. Ejecuta prisma migrate para continuar." },
        { status: 503 },
      );
    }

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