import { Request, Response, NextFunction } from "express";
import { ZodError } from "zod";
import { Prisma } from "@prisma/client";
import { AppError } from "./AppError";
import { ValidationError } from "./ValidationError";

function isZodValidationError(err: unknown): err is ZodError {
    return err instanceof ZodError
        || (
            typeof err === "object"
            && err !== null
            && (err as { name?: unknown }).name === "ZodError"
            && Array.isArray((err as { issues?: unknown }).issues)
        );
}

export const errorHandler = (
    err: any,
    _req: Request,
    res: Response,
    _next: NextFunction
) => {
    // 1️⃣ Validation métier custom
    if (err instanceof ValidationError) {
        console.error(
            "ValidationError:",
            JSON.stringify(err.errors, null, 2)
        );

        return res.status(400).json({
            status: "fail",
            message: err.message,
            errors: err.errors
        });
    }

    console.error(err);

    // 2️⃣ AppError métier
    if (err instanceof AppError) {
        return res.status(err.statusCode).json({
            status: "fail",
            message: err.message
        });
    }

    // 3️⃣ Zod validation
    if (isZodValidationError(err)) {
        return res.status(400).json({
            status: "fail",
            message: "Validation error",
            errors: err.flatten()
        });
    }

    // 4️⃣ JSON invalide / body-parser
    if (
        err instanceof SyntaxError
        && typeof err === "object"
        && err !== null
        && (err as { status?: unknown }).status === 400
        && "body" in err
    ) {
        return res.status(400).json({
            status: "fail",
            message: "Invalid JSON body"
        });
    }

    // 5️⃣ Prisma validation errors
    if (err instanceof Prisma.PrismaClientValidationError) {
        return res.status(400).json({
            status: "fail",
            message: "Database validation error"
        });
    }

    // 6️⃣ Prisma known errors (ex: unique constraint)
    if (err instanceof Prisma.PrismaClientKnownRequestError) {
        return res.status(400).json({
            status: "fail",
            message: "Database error",
            code: err.code
        });
    }

    // 7️⃣ 🔥 Seulement ici on log vraiment
    console.error("UNEXPECTED ERROR:", err);

    return res.status(500).json({
        status: "error",
        message: "Internal server error"
    });
};