import { Prisma, WorkshopEvidenceValidationStatus, WorkshopProgressStatus } 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 { getTalleresSnapshot } from "@/lib/talleres/server";
import { validateWorkshopEvidenceSync } from "@/lib/talleres/validation";

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

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

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 workshopId = parseString(formData.get("workshopId"));
    const file = formData.get("file");

    if (!workshopId) {
      return NextResponse.json({ error: "workshopId es requerido." }, { 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 workshop = await prisma.developmentWorkshop.findUnique({
      where: { id: workshopId },
      select: { id: true },
    });

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

    const fileBuffer = Buffer.from(await file.arrayBuffer());
    const stored = await storeStrategicEvidenceFile(user.id, file.name, file.type, fileBuffer);
    const now = new Date();

    try {
      const validation = validateWorkshopEvidenceSync({
        fileName: stored.fileName,
        mimeType: stored.mimeType,
        sizeBytes: stored.sizeBytes,
      });

      const validationStatus =
        validation.status === "APPROVED" ? WorkshopEvidenceValidationStatus.APPROVED : WorkshopEvidenceValidationStatus.REJECTED;

      const evidence = await prisma.developmentWorkshopEvidence.create({
        data: {
          workshopId,
          userId: user.id,
          validationStatus,
          validationReason: validation.reason,
          validationConfidence: validation.confidence,
          validatedAt: now,
          fileName: stored.fileName,
          storedFileName: stored.storedFileName,
          filePath: stored.filePath,
          mimeType: stored.mimeType,
          sizeBytes: stored.sizeBytes,
          checksumSha256: stored.checksumSha256,
        },
      });

      await prisma.developmentWorkshopProgress.upsert({
        where: {
          workshopId_userId: {
            workshopId,
            userId: user.id,
          },
        },
        update: {
          status:
            validationStatus === WorkshopEvidenceValidationStatus.APPROVED
              ? WorkshopProgressStatus.APPROVED
              : WorkshopProgressStatus.REJECTED,
          watchedAt: now,
          completedAt: validationStatus === WorkshopEvidenceValidationStatus.APPROVED ? now : null,
        },
        create: {
          workshopId,
          userId: user.id,
          status:
            validationStatus === WorkshopEvidenceValidationStatus.APPROVED
              ? WorkshopProgressStatus.APPROVED
              : WorkshopProgressStatus.REJECTED,
          watchedAt: now,
          completedAt: validationStatus === WorkshopEvidenceValidationStatus.APPROVED ? now : null,
        },
      });

      const payload = await getTalleresSnapshot(user.id);
      return NextResponse.json({
        ok: true,
        evidence: {
          id: evidence.id,
          validationStatus: evidence.validationStatus,
          validationReason: evidence.validationReason,
          validationConfidence: evidence.validationConfidence,
        },
        payload,
      });
    } catch {
      const evidence = await prisma.developmentWorkshopEvidence.create({
        data: {
          workshopId,
          userId: user.id,
          validationStatus: WorkshopEvidenceValidationStatus.ERROR,
          validationReason: "La validacion automatica no estuvo disponible. Tu evidencia fue guardada para revision.",
          validationConfidence: null,
          validatedAt: now,
          fileName: stored.fileName,
          storedFileName: stored.storedFileName,
          filePath: stored.filePath,
          mimeType: stored.mimeType,
          sizeBytes: stored.sizeBytes,
          checksumSha256: stored.checksumSha256,
        },
      });

      await prisma.developmentWorkshopProgress.upsert({
        where: {
          workshopId_userId: {
            workshopId,
            userId: user.id,
          },
        },
        update: {
          status: WorkshopProgressStatus.EVIDENCE_SUBMITTED,
          watchedAt: now,
        },
        create: {
          workshopId,
          userId: user.id,
          status: WorkshopProgressStatus.EVIDENCE_SUBMITTED,
          watchedAt: now,
        },
      });

      const payload = await getTalleresSnapshot(user.id);
      return NextResponse.json({
        ok: true,
        warning: "Tu evidencia se guardo, pero la validacion automatica quedo pendiente.",
        evidence: {
          id: evidence.id,
          validationStatus: evidence.validationStatus,
          validationReason: evidence.validationReason,
          validationConfidence: evidence.validationConfidence,
        },
        payload,
      });
    }
  } catch (error) {
    if (isSchemaNotReadyError(error)) {
      return NextResponse.json(
        { error: "La base de datos aun no tiene las tablas de Talleres. Ejecuta prisma migrate para continuar." },
        { status: 503 },
      );
    }

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