import { NextRequest } from "next/server";
import { getServerSession } from "next-auth";
import { authOptions } from "../auth/authOptions";
import { prisma } from "@/lib/prisma";
import { promises as fs } from 'fs';
import path from 'path';
import { FactureSchema } from "@/lib/validations/schemas";
import { successResponse, errorResponse, unauthorizedResponse, validationErrorResponse } from "@/lib/api-response";
import { z } from "zod";

export async function GET(req: NextRequest) {
  try {
    const session = await getServerSession(authOptions);
    if (!session) {
      return unauthorizedResponse();
    }
    
    const { searchParams } = new URL(req.url);
    const type = searchParams.get('type');
    
    if (session.user.role === "ADMIN") {
      const factures = await prisma.facture.findMany({
        where: type ? { type } : {},
        include: { partner: true, client: true },
        orderBy: { dateReception: 'desc' },
      });
      return successResponse(factures);
    }
    
    const managerData = await prisma.managerData.findUnique({
      where: { userId: Number(session.user.id) }
    });
    
    if (!managerData) {
      return successResponse([]);
    }
    
    const factures = await prisma.facture.findMany({
      where: {
        ...(type ? { type } : {}),
        managerDataId: managerData.id
      },
      include: { partner: true, client: true },
      orderBy: { dateReception: 'desc' },
    });
    return successResponse(factures);
  } catch (error: any) {
    return errorResponse("Erreur lors de la récupération des factures", error.message);
  }
}

export async function POST(req: NextRequest) {
  try {
    const session = await getServerSession(authOptions);
    
    if (!session || (session.user.role !== "MANAGER" && session.user.role !== "ADMIN")) {
      return unauthorizedResponse();
    }
    
    let managerDataId: number | null = null;
    if (session.user.role === "ADMIN") {
      const defaultManager = await prisma.managerData.findFirst();
      if (!defaultManager) {
        return errorResponse("Aucun manager disponible", undefined, 400);
      }
      managerDataId = defaultManager.id;
    } else {
      const managerData = await prisma.managerData.findUnique({
        where: { userId: Number(session.user.id) }
      });
      if (!managerData) {
        return errorResponse("Espace manager introuvable", undefined, 400);
      }
      managerDataId = managerData.id;
    }
    
    const formData = await req.formData();
    const data = Object.fromEntries(formData.entries());
    
    const payload: any = {
      type: data.type as string,
      titre: data.titre as string,
      montant: data.montant ? parseFloat(data.montant as string) : undefined,
      partenaireId: data.partenaireId ? parseInt(data.partenaireId as string, 10) : undefined,
      clientId: data.clientId ? parseInt(data.clientId as string, 10) : undefined,
      dateReception: data.dateReception ? new Date(data.dateReception as string) : new Date(),
      echeance: data.echeance ? new Date(data.echeance as string) : new Date(),
      statut: data.statut as string,
      remarque: data.remarque as string,
    };
    
    try {
      FactureSchema.parse(payload);
    } catch (validationError: any) {
      if (validationError instanceof z.ZodError) {
        return validationErrorResponse(validationError);
      }
    }

    let pdfPath: string | null = null;
    const file = formData.get('pdfFile');
    if (file && typeof file === 'object' && 'arrayBuffer' in file) {
      const buffer = Buffer.from(await file.arrayBuffer());
      const fileName = `${Date.now()}-${(file as any).name}`;
      const uploadPath = path.join(process.cwd(), 'public', 'invoices', fileName);
      await fs.mkdir(path.dirname(uploadPath), { recursive: true });
      await fs.writeFile(uploadPath, buffer);
      pdfPath = `/invoices/${fileName}`;
    }
    
    const facture = await prisma.facture.create({
      data: {
        ...payload,
        pdfPath,
        managerDataId: managerDataId
      },
      include: { client: true, partner: true },
    });
    return successResponse(facture, 201);
  } catch (error: any) {
    return errorResponse("Erreur serveur lors de la création de la facture", error.message, 500);
  }
}

// Keeping PUT/DELETE in the base route as they were originally there too
export async function PUT(req: NextRequest) {
  try {
    const session = await getServerSession(authOptions);
    if (!session || (session.user.role !== "MANAGER" && session.user.role !== "ADMIN")) {
      return unauthorizedResponse();
    }

    const formData = await req.formData();
    const id = formData.get('id') as string;
    if (!id) return errorResponse("Missing ID", undefined, 400);

    const data = Object.fromEntries(formData.entries());
    
    let pdfPath: string | null = null;
    const file = formData.get('pdfFile');
    if (file && typeof file === 'object' && 'arrayBuffer' in file) {
      const buffer = Buffer.from(await file.arrayBuffer());
      const fileName = `${Date.now()}-${(file as any).name}`;
      const uploadPath = path.join(process.cwd(), 'public', 'invoices', fileName);
      await fs.mkdir(path.dirname(uploadPath), { recursive: true });
      await fs.writeFile(uploadPath, buffer);
      pdfPath = `/invoices/${fileName}`;
    }
    
    const facture = await prisma.facture.update({
      where: { id: id as string },
      data: {
        type: data.type ? (data.type as string) : undefined,
        titre: data.titre ? (data.titre as string) : undefined,
        montant: data.montant ? parseFloat(data.montant as string) : undefined,
        partenaireId: data.partenaireId ? parseInt(data.partenaireId as string, 10) : undefined,
        clientId: data.clientId ? parseInt(data.clientId as string, 10) : undefined,
        dateReception: data.dateReception ? new Date(data.dateReception as string) : undefined,
        echeance: data.echeance ? new Date(data.echeance as string) : undefined,
        statut: data.statut ? (data.statut as string) : undefined,
        remarque: data.remarque as string,
        pdfPath: pdfPath || undefined,
      },
      include: { client: true, partner: true },
    });
    return successResponse(facture);
  } catch (error: any) {
    return errorResponse("Erreur lors de la modification de la facture", error.message);
  }
}

export async function DELETE(req: NextRequest) {
  try {
    const session = await getServerSession(authOptions);
    if (!session || (session.user.role !== "MANAGER" && session.user.role !== "ADMIN")) {
      return unauthorizedResponse();
    }
    const { searchParams } = new URL(req.url);
    const id = searchParams.get('id');
    if (!id) return errorResponse('Missing id', undefined, 400);
    
    await prisma.facture.delete({ where: { id } });
    return successResponse({ success: true });
  } catch (error: any) {
    return errorResponse("Erreur lors de la suppression de la facture", error.message);
  }
}