package dev.lions.unionflow.server.resource;

import dev.lions.unionflow.server.api.dto.organisation.TypeOrganisationDTO;
import dev.lions.unionflow.server.service.TypeOrganisationService;
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.util.List;
import java.util.Map;
import java.util.UUID;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.media.Content;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.jboss.logging.Logger;

/**
 * Ressource REST pour la gestion du catalogue des types d'organisation.
 */
@Path("/api/types-organisations")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Types d'organisation", description = "Catalogue des types d'organisation")
@RolesAllowed({"ADMIN", "MEMBRE", "USER"})
public class TypeOrganisationResource {

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

  @Inject TypeOrganisationService service;

  /** Liste les types d'organisation. */
  @GET
  @Operation(
      summary = "Lister les types d'organisation",
      description = "Récupère la liste des types d'organisation, optionnellement seulement actifs")
  @APIResponses({
    @APIResponse(
        responseCode = "200",
        description = "Liste des types récupérée avec succès",
        content =
            @Content(
                mediaType = MediaType.APPLICATION_JSON,
                schema = @Schema(implementation = TypeOrganisationDTO.class))),
    @APIResponse(responseCode = "401", description = "Non authentifié"),
    @APIResponse(responseCode = "403", description = "Non autorisé")
  })
  public Response listTypes(
      @Parameter(description = "Limiter aux types actifs", example = "true")
          @QueryParam("onlyActifs")
          @DefaultValue("true")
          String onlyActifs) {
    // Parsing manuel pour éviter toute erreur de conversion JAX-RS (qui peut renvoyer une 400)
    boolean actifsSeulement = !"false".equalsIgnoreCase(onlyActifs);
    List<TypeOrganisationDTO> types = service.listAll(actifsSeulement);
    return Response.ok(types).build();
  }

  /** Crée un nouveau type d'organisation (réservé à l'administration). */
  @POST
  @RolesAllowed({"ADMIN", "MEMBRE"})
  @Operation(
      summary = "Créer un type d'organisation",
      description = "Crée un nouveau type dans le catalogue (code doit exister dans l'enum)")
  @APIResponses({
    @APIResponse(
        responseCode = "201",
        description = "Type créé avec succès",
        content =
            @Content(
                mediaType = MediaType.APPLICATION_JSON,
                schema = @Schema(implementation = TypeOrganisationDTO.class))),
    @APIResponse(responseCode = "400", description = "Données invalides"),
    @APIResponse(responseCode = "401", description = "Non authentifié"),
    @APIResponse(responseCode = "403", description = "Non autorisé")
  })
  public Response create(TypeOrganisationDTO dto) {
    try {
      TypeOrganisationDTO created = service.create(dto);
      return Response.status(Response.Status.CREATED).entity(created).build();
    } catch (IllegalArgumentException e) {
      LOG.warnf("Erreur lors de la création du type d'organisation: %s", e.getMessage());
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(Map.of("error", e.getMessage()))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur inattendue lors de la création du type d'organisation");
      return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
          .entity(Map.of("error", "Erreur interne du serveur"))
          .build();
    }
  }

  /** Met à jour un type. */
  @PUT
  @RolesAllowed({"ADMIN", "MEMBRE"})
  @Path("/{id}")
  @Operation(
      summary = "Mettre à jour un type d'organisation",
      description = "Met à jour un type existant (libellé, description, ordre, actif, code)")
  @APIResponses({
    @APIResponse(
        responseCode = "200",
        description = "Type mis à jour avec succès",
        content =
            @Content(
                mediaType = MediaType.APPLICATION_JSON,
                schema = @Schema(implementation = TypeOrganisationDTO.class))),
    @APIResponse(responseCode = "400", description = "Données invalides"),
    @APIResponse(responseCode = "404", description = "Type non trouvé"),
    @APIResponse(responseCode = "401", description = "Non authentifié"),
    @APIResponse(responseCode = "403", description = "Non autorisé")
  })
  public Response update(@PathParam("id") UUID id, TypeOrganisationDTO dto) {
    try {
      TypeOrganisationDTO updated = service.update(id, dto);
      return Response.ok(updated).build();
    } catch (IllegalArgumentException e) {
      LOG.warnf("Erreur lors de la mise à jour du type d'organisation: %s", e.getMessage());
      return Response.status(Response.Status.BAD_REQUEST)
          .entity(Map.of("error", e.getMessage()))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur inattendue lors de la mise à jour du type d'organisation");
      return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
          .entity(Map.of("error", "Erreur interne du serveur"))
          .build();
    }
  }

  /** Désactive un type (soft delete). */
  @DELETE
  @RolesAllowed({"ADMIN"})
  @Path("/{id}")
  @Operation(
      summary = "Désactiver un type d'organisation",
      description = "Désactive un type dans le catalogue (soft delete)")
  @APIResponses({
    @APIResponse(responseCode = "204", description = "Type désactivé avec succès"),
    @APIResponse(responseCode = "404", description = "Type non trouvé"),
    @APIResponse(responseCode = "401", description = "Non authentifié"),
    @APIResponse(responseCode = "403", description = "Non autorisé")
  })
  public Response disable(@PathParam("id") UUID id) {
    try {
      service.disable(id);
      return Response.noContent().build();
    } catch (IllegalArgumentException e) {
      return Response.status(Response.Status.NOT_FOUND)
          .entity(Map.of("error", e.getMessage()))
          .build();
    } catch (Exception e) {
      LOG.errorf(e, "Erreur inattendue lors de la désactivation du type d'organisation");
      return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
          .entity(Map.of("error", "Erreur interne du serveur"))
          .build();
    }
  }
}


