import { NextRequest } from "next/server";
import { Role } from "@prisma/client";
import { z } from "zod";
import { prisma } from "@/server/db";
import { AppError } from "@/server/errors";
import { fail, ok, parseJson } from "@/server/http";
import { kycUploadMimeType, readKycUpload } from "@/server/kyc/document-upload";
import { requireUser } from "@/server/security/auth";
import { requireRole } from "@/server/security/rbac";

const documentDecisionSchema = z.object({
  status: z.enum(["accepted", "rejected", "uploaded"]),
  reason: z.string().trim().max(500).optional()
});

export const dynamic = "force-dynamic";
export const runtime = "nodejs";

export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
  try {
    const auth = await requireUser(request);
    requireRole(auth.roles, [Role.KYC_ANALYST, Role.ADMIN, Role.SUPER_ADMIN]);
    const { id } = await params;
    const document = await prisma.kycDocument.findUniqueOrThrow({ where: { id } });
    const bytes = await readKycUpload(document.storageKey);
    const mimeType = metadataMimeType(document.metadata) ?? kycUploadMimeType(document.storageKey);

    return new Response(bytes, {
      headers: {
        "Content-Type": mimeType,
        "Content-Disposition": `inline; filename="${documentFilename(document.type, mimeType)}"`,
        "Cache-Control": "private, no-store"
      }
    });
  } catch (error) {
    return fail(error);
  }
}

export async function PATCH(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
  try {
    const auth = await requireUser(request);
    requireRole(auth.roles, [Role.KYC_ANALYST, Role.ADMIN, Role.SUPER_ADMIN]);
    const { id } = await params;
    const input = await parseJson(request, documentDecisionSchema);
    const existingDocument = await prisma.kycDocument.findUniqueOrThrow({ where: { id } });
    const existingMetadata =
      existingDocument.metadata && typeof existingDocument.metadata === "object" && !Array.isArray(existingDocument.metadata)
        ? existingDocument.metadata
        : {};
    const document = await prisma.kycDocument.update({
      where: { id },
      data: {
        status: input.status,
        metadata: {
          ...existingMetadata,
          decisionReason: input.reason ?? null,
          decidedAt: new Date().toISOString(),
          decidedBy: auth.user.id
        }
      }
    });

    return ok({
      document: {
        id: document.id,
        type: document.type,
        status: document.status,
        uploadedAt: document.uploadedAt,
        metadata: document.metadata
      }
    });
  } catch (error) {
    return fail(error);
  }
}

function metadataMimeType(metadata: unknown) {
  if (metadata && typeof metadata === "object" && "mimeType" in metadata && typeof metadata.mimeType === "string") {
    return metadata.mimeType;
  }
  return null;
}

function documentFilename(type: string, mimeType: string) {
  const extension = mimeType === "application/pdf" ? "pdf" : mimeType.split("/")[1] ?? "bin";
  if (!["pdf", "jpeg", "jpg", "png", "webp"].includes(extension)) {
    throw new AppError("Format de document invalide.", 422, "KYC_DOCUMENT_FORMAT_INVALID");
  }
  return `${type.toLowerCase()}.${extension === "jpeg" ? "jpg" : extension}`;
}
