package dev.lions.unionflow.server.resource;

import dev.lions.unionflow.server.service.ComptabilitePdfService;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Inject;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.time.LocalDate;
import java.util.UUID;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;

/**
 * Endpoints de téléchargement des rapports comptables PDF SYSCOHADA révisé.
 */
@Path("/api/comptabilite/pdf")
@Produces(MediaType.APPLICATION_JSON)
@RolesAllowed({"ADMIN_ORGANISATION", "TRESORIER", "COMMISSAIRE_COMPTES", "SUPER_ADMIN"})
@Tag(name = "Comptabilité PDF", description = "Rapports comptables SYSCOHADA : balance, compte de résultat, grand livre")
public class ComptabilitePdfResource {

    @Inject
    ComptabilitePdfService comptabilitePdfService;

    @GET
    @Path("/organisations/{organisationId}/balance")
    @Produces("application/pdf")
    @Operation(summary = "Balance générale SYSCOHADA",
               description = "Génère la balance générale (cumul débit/crédit/solde) pour la période.")
    public Response balance(
            @PathParam("organisationId") UUID organisationId,
            @QueryParam("dateDebut") @DefaultValue("") String dateDebutStr,
            @QueryParam("dateFin") @DefaultValue("") String dateFinStr) {

        LocalDate dateDebut = parseDateOrStartOfYear(dateDebutStr);
        LocalDate dateFin = parseDateOrToday(dateFinStr);

        byte[] pdf = comptabilitePdfService.genererBalance(organisationId, dateDebut, dateFin);
        return buildPdfResponse(pdf, "balance_" + organisationId + ".pdf");
    }

    @GET
    @Path("/organisations/{organisationId}/compte-de-resultat")
    @Produces("application/pdf")
    @Operation(summary = "Compte de résultat SYSCOHADA",
               description = "Génère le compte de résultat (produits classes 7/8 − charges classes 6/8).")
    public Response compteDeResultat(
            @PathParam("organisationId") UUID organisationId,
            @QueryParam("dateDebut") @DefaultValue("") String dateDebutStr,
            @QueryParam("dateFin") @DefaultValue("") String dateFinStr) {

        LocalDate dateDebut = parseDateOrStartOfYear(dateDebutStr);
        LocalDate dateFin = parseDateOrToday(dateFinStr);

        byte[] pdf = comptabilitePdfService.genererCompteResultat(organisationId, dateDebut, dateFin);
        return buildPdfResponse(pdf, "compte_resultat_" + organisationId + ".pdf");
    }

    @GET
    @Path("/organisations/{organisationId}/grand-livre/{numeroCompte}")
    @Produces("application/pdf")
    @Operation(summary = "Grand livre d'un compte SYSCOHADA",
               description = "Génère le grand livre (détail chronologique) pour un compte comptable donné.")
    public Response grandLivre(
            @PathParam("organisationId") UUID organisationId,
            @PathParam("numeroCompte") String numeroCompte,
            @QueryParam("dateDebut") @DefaultValue("") String dateDebutStr,
            @QueryParam("dateFin") @DefaultValue("") String dateFinStr) {

        LocalDate dateDebut = parseDateOrStartOfYear(dateDebutStr);
        LocalDate dateFin = parseDateOrToday(dateFinStr);

        byte[] pdf = comptabilitePdfService.genererGrandLivre(organisationId, numeroCompte, dateDebut, dateFin);
        return buildPdfResponse(pdf, "grand_livre_" + numeroCompte + ".pdf");
    }

    private static Response buildPdfResponse(byte[] pdf, String filename) {
        return Response.ok(pdf)
                .header("Content-Disposition", "attachment; filename=\"" + filename + "\"")
                .header("Content-Length", pdf.length)
                .build();
    }

    private static LocalDate parseDateOrStartOfYear(String s) {
        if (s == null || s.isBlank()) return LocalDate.of(LocalDate.now().getYear(), 1, 1);
        try { return LocalDate.parse(s); } catch (Exception e) {
            throw new BadRequestException("Format de date invalide (attendu : YYYY-MM-DD) : " + s);
        }
    }

    private static LocalDate parseDateOrToday(String s) {
        if (s == null || s.isBlank()) return LocalDate.now();
        try { return LocalDate.parse(s); } catch (Exception e) {
            throw new BadRequestException("Format de date invalide (attendu : YYYY-MM-DD) : " + s);
        }
    }
}
