package dev.lions.unionflow.client.view;

import dev.lions.unionflow.client.api.dto.RapportTrimestrielDto;
import dev.lions.unionflow.client.service.RapportTrimestrielRestClient;
import jakarta.annotation.PostConstruct;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.ExternalContext;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.time.Year;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.logging.Logger;

/**
 * Bean liste/actions sur les rapports trimestriels Contrôleur Interne (Sprint 8 ⇄ P2-NEW-3).
 *
 * @since 2026-04-25 (Sprint 8)
 */
@Named
@ViewScoped
public class RapportsTrimestrielsBean implements Serializable {

  private static final long serialVersionUID = 1L;
  private static final Logger LOG = Logger.getLogger(RapportsTrimestrielsBean.class);

  @Inject @RestClient
  RapportTrimestrielRestClient client;

  private List<RapportTrimestrielDto> rapports = Collections.emptyList();
  private int annee = Year.now().getValue();
  private int trimestreCible = 1;
  private RapportTrimestrielDto selection;
  private String erreur;

  @PostConstruct
  public void init() {
    rafraichir();
  }

  public void rafraichir() {
    erreur = null;
    try {
      rapports = client.lister(null, annee);
      LOG.infof("Liste rapports trimestriels chargée pour année %d : %d entrée(s)",
          annee, rapports.size());
    } catch (Exception e) {
      handleError("Chargement des rapports échoué", e);
      rapports = Collections.emptyList();
    }
  }

  public void genererRapport() {
    erreur = null;
    try {
      var nouveau = client.generer(null, annee, trimestreCible);
      addMessage(FacesMessage.SEVERITY_INFO, "Rapport généré",
          "Trimestre " + nouveau.trimestre() + "/" + nouveau.annee()
              + " — score " + nouveau.scoreConformite());
      rafraichir();
    } catch (Exception e) {
      handleError("Génération du rapport échouée", e);
    }
  }

  public void signerSelection(UUID signataireId) {
    if (selection == null) {
      addMessage(FacesMessage.SEVERITY_WARN, "Aucune sélection",
          "Sélectionnez un rapport DRAFT à signer");
      return;
    }
    try {
      client.signer(selection.id(), signataireId);
      addMessage(FacesMessage.SEVERITY_INFO, "Signé",
          "Rapport " + selection.annee() + "/T" + selection.trimestre() + " signé");
      rafraichir();
    } catch (Exception e) {
      handleError("Signature échouée", e);
    }
  }

  public void archiverSelection() {
    if (selection == null) {
      addMessage(FacesMessage.SEVERITY_WARN, "Aucune sélection",
          "Sélectionnez un rapport SIGNE à archiver");
      return;
    }
    try {
      client.archiver(selection.id());
      addMessage(FacesMessage.SEVERITY_INFO, "Archivé",
          "Rapport " + selection.annee() + "/T" + selection.trimestre() + " archivé");
      rafraichir();
    } catch (Exception e) {
      handleError("Archivage échoué", e);
    }
  }

  public void telechargerPdf(RapportTrimestrielDto r) {
    if (r == null) return;
    try {
      byte[] pdf = client.telechargerPdf(r.id());
      String filename = String.format("rapport-trim-%d-T%d.pdf", r.annee(), r.trimestre());

      FacesContext fc = FacesContext.getCurrentInstance();
      ExternalContext ec = fc.getExternalContext();
      ec.responseReset();
      ec.setResponseContentType("application/pdf");
      ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
      ec.setResponseContentLength(pdf.length);
      try (OutputStream os = ec.getResponseOutputStream()) {
        os.write(pdf);
      }
      fc.responseComplete();
    } catch (IOException e) {
      handleError("Téléchargement PDF échoué", e);
    } catch (Exception e) {
      handleError("Téléchargement PDF échoué", e);
    }
  }

  private void handleError(String summary, Exception e) {
    LOG.warnf("%s : %s", summary, e.getMessage());
    erreur = summary + " — " + e.getMessage();
    addMessage(FacesMessage.SEVERITY_ERROR, "Erreur", erreur);
  }

  private void addMessage(FacesMessage.Severity sev, String summary, String detail) {
    FacesContext.getCurrentInstance().addMessage(null,
        new FacesMessage(sev, summary, detail));
  }

  public List<RapportTrimestrielDto> getRapports() { return rapports; }
  public int getAnnee() { return annee; }
  public void setAnnee(int annee) { this.annee = annee; }
  public int getTrimestreCible() { return trimestreCible; }
  public void setTrimestreCible(int trimestreCible) { this.trimestreCible = trimestreCible; }
  public RapportTrimestrielDto getSelection() { return selection; }
  public void setSelection(RapportTrimestrielDto selection) { this.selection = selection; }
  public String getErreur() { return erreur; }
}
