package dev.lions.unionflow.client.service;

import dev.lions.unionflow.server.api.dto.common.PagedResponse;
import dev.lions.unionflow.server.api.dto.membre.request.CreateMembreRequest;
import dev.lions.unionflow.server.api.dto.membre.response.MembreResponse;
import dev.lions.unionflow.server.api.dto.membre.response.MembreSummaryResponse;
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.List;
import java.util.UUID;

@RegisterRestClient(configKey = "unionflow-api")
@RegisterClientHeaders(dev.lions.unionflow.client.security.AuthHeaderFactory.class)
@Path("/api/membres")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface MembreService {

    @GET
    PagedResponse<MembreSummaryResponse> listerTous(
            @QueryParam("page") @DefaultValue("0") int page,
            @QueryParam("size") @DefaultValue("20") int size);

    /** Surcharge sans pagination — retourne jusqu'à 1000 membres (usage hors DataTable). */
    default PagedResponse<MembreSummaryResponse> listerTous() {
        return listerTous(0, 1000);
    }

    @GET
    @Path("/{id}")
    MembreResponse obtenirParId(@PathParam("id") UUID id);

    @GET
    @Path("/numero/{numeroMembre}")
    MembreResponse obtenirParNumero(@PathParam("numeroMembre") String numeroMembre);

    @GET
    @Path("/me")
    MembreResponse obtenirMembreConnecte();

    @GET
    @Path("/search")
    List<MembreResponse> rechercher(
            @QueryParam("nom") String nom,
            @QueryParam("prenom") String prenom,
            @QueryParam("email") String email,
            @QueryParam("telephone") String telephone,
            @QueryParam("statut") String statut,
            @QueryParam("associationId") UUID associationId,
            @QueryParam("page") @DefaultValue("0") int page,
            @QueryParam("size") @DefaultValue("20") int size);

    @POST
    @Path("/search/advanced")
    dev.lions.unionflow.server.api.dto.membre.MembreSearchResultDTO rechercherAvance(
            dev.lions.unionflow.server.api.dto.membre.MembreSearchCriteria criteria,
            @QueryParam("page") @DefaultValue("0") int page,
            @QueryParam("size") @DefaultValue("20") int size,
            @QueryParam("sort") @DefaultValue("nom") String sortField,
            @QueryParam("direction") @DefaultValue("asc") String sortDirection);

    @GET
    @Path("/organisation/{organisationId}")
    List<MembreResponse> listerParOrganisation(@PathParam("organisationId") UUID organisationId);

    @GET
    @Path("/actifs")
    List<MembreResponse> listerActifs();

    @GET
    @Path("/inactifs")
    List<MembreResponse> listerInactifs();

    @POST
    MembreResponse creer(CreateMembreRequest membre);

    @PUT
    @Path("/{id}")
    MembreResponse modifier(@PathParam("id") UUID id, MembreResponse membre);

    @DELETE
    @Path("/{id}")
    void supprimer(@PathParam("id") UUID id);

    @PUT
    @Path("/{id}/activer")
    MembreResponse activer(@PathParam("id") UUID id);

    @PUT
    @Path("/{id}/desactiver")
    MembreResponse desactiver(@PathParam("id") UUID id);

    @PUT
    @Path("/{id}/suspendre")
    MembreResponse suspendre(@PathParam("id") UUID id);

    @PUT
    @Path("/{id}/radier")
    MembreResponse radier(@PathParam("id") UUID id);

    @GET
    @Path("/stats")
    StatistiquesMembreDTO obtenirStatistiques();

    @GET
    @Path("/export")
    @Produces({ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "text/csv", "application/pdf",
            "application/json" })
    byte[] exporterExcel(
            @QueryParam("format") @DefaultValue("EXCEL") String format,
            @QueryParam("associationId") UUID associationId,
            @QueryParam("statut") String statut,
            @QueryParam("type") String type,
            @QueryParam("dateAdhesionDebut") String dateAdhesionDebut,
            @QueryParam("dateAdhesionFin") String dateAdhesionFin,
            @QueryParam("colonnes") List<String> colonnesExport,
            @QueryParam("inclureHeaders") @DefaultValue("true") boolean inclureHeaders,
            @QueryParam("formaterDates") @DefaultValue("true") boolean formaterDates,
            @QueryParam("inclureStatistiques") @DefaultValue("false") boolean inclureStatistiques,
            @QueryParam("motDePasse") String motDePasse);

    @GET
    @Path("/export/count")
    @Produces(MediaType.APPLICATION_JSON)
    Long compterMembresPourExport(
            @QueryParam("associationId") UUID associationId,
            @QueryParam("statut") String statut,
            @QueryParam("type") String type,
            @QueryParam("dateAdhesionDebut") String dateAdhesionDebut,
            @QueryParam("dateAdhesionFin") String dateAdhesionFin);

    @POST
    @Path("/import")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Produces(MediaType.APPLICATION_JSON)
    ResultatImportDTO importerDonnees(MembreImportMultipartForm form);

    @GET
    @Path("/import/modele")
    @Produces("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
    byte[] telechargerModeleImport();

    @GET
    @Path("/autocomplete/villes")
    List<String> obtenirVilles(@QueryParam("query") String query);

    @GET
    @Path("/mes-organisations")
    List<OrganisationSwitcherDTO> mesOrganisations();

    // ── Cycle de vie des adhésions ─────────────────────────────────────────

    @GET
    @Path("/{membreId}/adhesion")
    @SuppressWarnings("unchecked")
    java.util.Map<String, Object> getAdhesionStatut(@PathParam("membreId") UUID membreId,
                                                     @QueryParam("organisationId") UUID organisationId);

    @PUT
    @Path("/{membreId}/inviter-organisation")
    java.util.Map<String, Object> inviterMembreOrg(@PathParam("membreId") UUID membreId,
                                                    @QueryParam("organisationId") UUID organisationId,
                                                    @QueryParam("roleOrg") String roleOrg);

    @POST
    @Path("/accepter-invitation/{token}")
    java.util.Map<String, Object> accepterInvitation(@PathParam("token") String token);

    @PUT
    @Path("/{membreId}/adhesion/activer")
    java.util.Map<String, Object> activerAdhesion(@PathParam("membreId") UUID membreId,
                                                   @QueryParam("organisationId") UUID organisationId,
                                                   java.util.Map<String, String> body);

    @PUT
    @Path("/{membreId}/adhesion/suspendre")
    java.util.Map<String, Object> suspendrAdhesion(@PathParam("membreId") UUID membreId,
                                                    @QueryParam("organisationId") UUID organisationId,
                                                    java.util.Map<String, String> body);

    @PUT
    @Path("/{membreId}/adhesion/radier")
    java.util.Map<String, Object> radierAdhesion(@PathParam("membreId") UUID membreId,
                                                  @QueryParam("organisationId") UUID organisationId,
                                                  java.util.Map<String, String> body);

    @GET
    @Path("/autocomplete/professions")
    List<String> obtenirProfessions(@QueryParam("query") String query);

    @POST
    @Path("/export/selection")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
    byte[] exporterSelection(
            List<UUID> membreIds,
            @QueryParam("format") @DefaultValue("EXCEL") String format);

    // Classes DTO internes pour les réponses spécialisées

    /**
     * DTO pour le sélecteur d'organisation (multi-org switcher).
     * Mappé depuis GET /api/membres/mes-organisations.
     */
    class OrganisationSwitcherDTO implements java.io.Serializable {
        public String organisationId;
        public String nom;
        public String nomCourt;
        public String typeOrganisation;
        public String categorieType;
        public String modulesActifs;
        public String statut;
        public String statutMembre;
        public String roleOrg;
        public String dateAdhesion;

        public String getOrganisationId() { return organisationId; }
        public void setOrganisationId(String v) { this.organisationId = v; }
        public String getNom() { return nom; }
        public void setNom(String v) { this.nom = v; }
        public String getNomCourt() { return nomCourt; }
        public void setNomCourt(String v) { this.nomCourt = v; }
        public String getTypeOrganisation() { return typeOrganisation; }
        public void setTypeOrganisation(String v) { this.typeOrganisation = v; }
        public String getCategorieType() { return categorieType; }
        public void setCategorieType(String v) { this.categorieType = v; }
        public String getModulesActifs() { return modulesActifs; }
        public void setModulesActifs(String v) { this.modulesActifs = v; }
        public String getStatut() { return statut; }
        public void setStatut(String v) { this.statut = v; }
        public String getStatutMembre() { return statutMembre; }
        public void setStatutMembre(String v) { this.statutMembre = v; }
        public String getRoleOrg() { return roleOrg; }
        public void setRoleOrg(String v) { this.roleOrg = v; }
        public String getDateAdhesion() { return dateAdhesion; }
        public void setDateAdhesion(String v) { this.dateAdhesion = v; }

        /** Retourne le libellé court à afficher dans le switcher. */
        public String getLibelleCourt() {
            if (nomCourt != null && !nomCourt.isBlank()) return nomCourt;
            if (nom != null && nom.length() > 25) return nom.substring(0, 22) + "…";
            return nom;
        }
    }

    class StatistiquesMembreDTO {
        public Long totalMembres;
        public Long membresActifs;
        public Long membresInactifs;
        public Long membresSuspendus;
        public Long membresRadies;
        public Long nouveauxMembres30Jours;
        public Double tauxActivite;
        public Double tauxCroissance;

        // Constructeurs
        public StatistiquesMembreDTO() {
        }

        // Getters et setters
        public Long getTotalMembres() {
            return totalMembres;
        }

        public void setTotalMembres(Long totalMembres) {
            this.totalMembres = totalMembres;
        }

        public Long getMembresActifs() {
            return membresActifs;
        }

        public void setMembresActifs(Long membresActifs) {
            this.membresActifs = membresActifs;
        }

        public Long getMembresInactifs() {
            return membresInactifs;
        }

        public void setMembresInactifs(Long membresInactifs) {
            this.membresInactifs = membresInactifs;
        }

        public Long getMembresSuspendus() {
            return membresSuspendus;
        }

        public void setMembresSuspendus(Long membresSuspendus) {
            this.membresSuspendus = membresSuspendus;
        }

        public Long getMembresRadies() {
            return membresRadies;
        }

        public void setMembresRadies(Long membresRadies) {
            this.membresRadies = membresRadies;
        }

        public Long getNouveauxMembres30Jours() {
            return nouveauxMembres30Jours;
        }

        public void setNouveauxMembres30Jours(Long nouveauxMembres30Jours) {
            this.nouveauxMembres30Jours = nouveauxMembres30Jours;
        }

        public Double getTauxActivite() {
            return tauxActivite;
        }

        public void setTauxActivite(Double tauxActivite) {
            this.tauxActivite = tauxActivite;
        }

        public Double getTauxCroissance() {
            return tauxCroissance;
        }

        public void setTauxCroissance(Double tauxCroissance) {
            this.tauxCroissance = tauxCroissance;
        }
    }

    class ResultatImportDTO {
        public Integer totalLignes;
        public Integer lignesTraitees;
        public Integer lignesErreur;
        public List<String> erreurs;
        public List<MembreResponse> membresImportes;

        // Constructeurs
        public ResultatImportDTO() {
        }

        // Getters et setters
        public Integer getTotalLignes() {
            return totalLignes;
        }

        public void setTotalLignes(Integer totalLignes) {
            this.totalLignes = totalLignes;
        }

        public Integer getLignesTraitees() {
            return lignesTraitees;
        }

        public void setLignesTraitees(Integer lignesTraitees) {
            this.lignesTraitees = lignesTraitees;
        }

        public Integer getLignesErreur() {
            return lignesErreur;
        }

        public void setLignesErreur(Integer lignesErreur) {
            this.lignesErreur = lignesErreur;
        }

        public List<String> getErreurs() {
            return erreurs;
        }

        public void setErreurs(List<String> erreurs) {
            this.erreurs = erreurs;
        }

        public List<MembreResponse> getMembresImportes() {
            return membresImportes;
        }

        public void setMembresImportes(List<MembreResponse> membresImportes) {
            this.membresImportes = membresImportes;
        }
    }
}
