package dev.lions.unionflow.server.resource;

import dev.lions.unionflow.server.api.dto.comptabilite.request.*;
import dev.lions.unionflow.server.api.dto.comptabilite.response.*;
import dev.lions.unionflow.server.common.ErrorResponse;
import dev.lions.unionflow.server.service.ComptabiliteService;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.util.List;
import java.util.UUID;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.jboss.logging.Logger;

/**
 * Resource REST pour la gestion comptable
 *
 * @author UnionFlow Team
 * @version 3.0
 * @since 2025-01-29
 */
@Path("/api/comptabilite")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@RolesAllowed({ "ADMIN", "ADMIN_ORGANISATION", "TRESORIER" })
@Tag(name = "Comptabilité", description = "Gestion comptable : comptes, journaux et écritures comptables")
public class ComptabiliteResource {

  private static final Logger LOG = Logger.getLogger(ComptabiliteResource.class);

  @Inject
  ComptabiliteService comptabiliteService;

  // ========================================
  // COMPTES COMPTABLES
  // ========================================

  /**
   * Crée un nouveau compte comptable
   *
   * @param compteDTO DTO du compte à créer
   * @return Compte créé
   */
  @POST
  @RolesAllowed({ "ADMIN", "ADMIN_ORGANISATION", "TRESORIER" })
  @Path("/comptes")
  public Response creerCompteComptable(@Valid CreateCompteComptableRequest request) {
    try {
      CompteComptableResponse result = comptabiliteService.creerCompteComptable(request);
      return Response.status(Response.Status.CREATED).entity(result).build();
    } catch (IllegalArgumentException e) {
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(ErrorResponse.ofError(e.getMessage()))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la création du compte comptable");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(ErrorResponse.ofError("Erreur lors de la création du compte comptable: " + e.getMessage()))
          .build();
    }
  }

  /**
   * Trouve un compte comptable par son ID
   *
   * @param id ID du compte
   * @return Compte comptable
   */
  @GET
  @Path("/comptes/{id}")
  public Response trouverCompteParId(@PathParam("id") UUID id) {
    try {
      CompteComptableResponse result = comptabiliteService.trouverCompteParId(id);
      return Response.ok(result).build();
    } catch (jakarta.ws.rs.NotFoundException e) {
      return Response.status(Response.Status.NOT_FOUND)
          .entity(ErrorResponse.ofError("Compte comptable non trouvé"))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la recherche du compte comptable");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(ErrorResponse.ofError("Erreur lors de la recherche du compte comptable: " + e.getMessage()))
          .build();
    }
  }

  /**
   * Liste tous les comptes comptables actifs
   *
   * @return Liste des comptes
   */
  @GET
  @Path("/comptes")
  public Response listerTousLesComptes() {
    try {
      List<CompteComptableResponse> result = comptabiliteService.listerTousLesComptes();
      return Response.ok(result).build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la liste des comptes comptables");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(ErrorResponse.ofError("Erreur lors de la liste des comptes comptables: " + e.getMessage()))
          .build();
    }
  }

  // ========================================
  // JOURNAUX COMPTABLES
  // ========================================

  /**
   * Crée un nouveau journal comptable
   *
   * @param journalDTO DTO du journal à créer
   * @return Journal créé
   */
  @POST
  @RolesAllowed({ "ADMIN", "ADMIN_ORGANISATION", "TRESORIER" })
  @Path("/journaux")
  public Response creerJournalComptable(@Valid CreateJournalComptableRequest request) {
    try {
      JournalComptableResponse result = comptabiliteService.creerJournalComptable(request);
      return Response.status(Response.Status.CREATED).entity(result).build();
    } catch (IllegalArgumentException e) {
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(ErrorResponse.ofError(e.getMessage()))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la création du journal comptable");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(ErrorResponse.ofError("Erreur lors de la création du journal comptable: " + e.getMessage()))
          .build();
    }
  }

  /**
   * Trouve un journal comptable par son ID
   *
   * @param id ID du journal
   * @return Journal comptable
   */
  @GET
  @Path("/journaux/{id}")
  public Response trouverJournalParId(@PathParam("id") UUID id) {
    try {
      JournalComptableResponse result = comptabiliteService.trouverJournalParId(id);
      return Response.ok(result).build();
    } catch (jakarta.ws.rs.NotFoundException e) {
      return Response.status(Response.Status.NOT_FOUND)
          .entity(ErrorResponse.ofError("Journal comptable non trouvé"))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la recherche du journal comptable");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(ErrorResponse.ofError("Erreur lors de la recherche du journal comptable: " + e.getMessage()))
          .build();
    }
  }

  /**
   * Liste tous les journaux comptables actifs
   *
   * @return Liste des journaux
   */
  @GET
  @Path("/journaux")
  public Response listerTousLesJournaux() {
    try {
      List<JournalComptableResponse> result = comptabiliteService.listerTousLesJournaux();
      return Response.ok(result).build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la liste des journaux comptables");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(ErrorResponse.ofError("Erreur lors de la liste des journaux comptables: " + e.getMessage()))
          .build();
    }
  }

  // ========================================
  // ÉCRITURES COMPTABLES
  // ========================================

  /**
   * Crée une nouvelle écriture comptable
   *
   * @param ecritureDTO DTO de l'écriture à créer
   * @return Écriture créée
   */
  @POST
  @RolesAllowed({ "ADMIN", "ADMIN_ORGANISATION", "MEMBRE" })
  @Path("/ecritures")
  public Response creerEcritureComptable(@Valid CreateEcritureComptableRequest request) {
    try {
      EcritureComptableResponse result = comptabiliteService.creerEcritureComptable(request);
      return Response.status(Response.Status.CREATED).entity(result).build();
    } catch (IllegalArgumentException e) {
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(ErrorResponse.ofError(e.getMessage()))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la création de l'écriture comptable");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(ErrorResponse.ofError("Erreur lors de la création de l'écriture comptable: " + e.getMessage()))
          .build();
    }
  }

  /**
   * Trouve une écriture comptable par son ID
   *
   * @param id ID de l'écriture
   * @return Écriture comptable
   */
  @GET
  @Path("/ecritures/{id}")
  public Response trouverEcritureParId(@PathParam("id") UUID id) {
    try {
      EcritureComptableResponse result = comptabiliteService.trouverEcritureParId(id);
      return Response.ok(result).build();
    } catch (jakarta.ws.rs.NotFoundException e) {
      return Response.status(Response.Status.NOT_FOUND)
          .entity(ErrorResponse.ofError("Écriture comptable non trouvée"))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la recherche de l'écriture comptable");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(ErrorResponse.ofError("Erreur lors de la recherche de l'écriture comptable: " + e.getMessage()))
          .build();
    }
  }

  /**
   * Liste les écritures d'un journal
   *
   * @param journalId ID du journal
   * @return Liste des écritures
   */
  @GET
  @Path("/ecritures/journal/{journalId}")
  public Response listerEcrituresParJournal(@PathParam("journalId") UUID journalId) {
    try {
      List<EcritureComptableResponse> result = comptabiliteService.listerEcrituresParJournal(journalId);
      return Response.ok(result).build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la liste des écritures");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(ErrorResponse.ofError("Erreur lors de la liste des écritures: " + e.getMessage()))
          .build();
    }
  }

  /**
   * Liste les écritures d'une organisation
   *
   * @param organisationId ID de l'organisation
   * @return Liste des écritures
   */
  @GET
  @Path("/ecritures/organisation/{organisationId}")
  public Response listerEcrituresParOrganisation(@PathParam("organisationId") UUID organisationId) {
    try {
      List<EcritureComptableResponse> result = comptabiliteService.listerEcrituresParOrganisation(organisationId);
      return Response.ok(result).build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur lors de la liste des écritures");
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(ErrorResponse.ofError("Erreur lors de la liste des écritures: " + e.getMessage()))
          .build();
    }
  }

}

