package dev.lions.unionflow.client.view;

import dev.lions.unionflow.client.service.AuditTrailRestClient;
import dev.lions.unionflow.server.api.dto.audit.response.AuditTrailOperationResponse;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import java.io.Serializable;
import java.time.LocalDateTime;
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 viewer audit trail (Sprint 11 ⇄ backend Sprint 10 CQRS read).
 * Pas d'écriture — la production des événements est dans le backend lifecycle.
 */
@Named
@ViewScoped
public class AuditTrailViewerBean implements Serializable {

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

  @Inject @RestClient AuditTrailRestClient client;

  /** Mode : USER, ENTITY, ORG, SOD_VIOLATIONS, FINANCIAL */
  private String mode = "ORG";

  private UUID userId;
  private UUID orgId;
  private String entityType;
  private UUID entityId;
  private LocalDateTime from = LocalDateTime.now().minusDays(30);
  private LocalDateTime to = LocalDateTime.now();

  private List<AuditTrailOperationResponse> operations = Collections.emptyList();
  private AuditTrailOperationResponse selection;
  private String erreur;

  public void rechercher() {
    erreur = null;
    try {
      operations = switch (mode) {
        case "USER" -> userId != null
            ? client.parUtilisateur(userId, from.toString(), to.toString())
            : Collections.emptyList();
        case "ENTITY" -> entityType != null && entityId != null
            ? client.historique(entityType, entityId)
            : Collections.emptyList();
        case "ORG" -> orgId != null
            ? client.parOrganisation(orgId)
            : Collections.emptyList();
        case "SOD_VIOLATIONS" -> client.violationsSod();
        case "FINANCIAL" -> orgId != null
            ? client.operationsFinancieres(orgId, from.toString(), to.toString())
            : Collections.emptyList();
        default -> Collections.emptyList();
      };
      LOG.infof("Audit trail (%s) chargé : %d entrées", mode, operations.size());
    } catch (Exception e) {
      handleError("Recherche audit trail échouée", e);
      operations = Collections.emptyList();
    }
  }

  public String getCouleurAction(String actionType) {
    if (actionType == null) return "secondary";
    return switch (actionType) {
      case "DELETE", "PAYMENT_FAILED" -> "danger";
      case "VALIDATE", "PAYMENT_CONFIRMED", "AID_REQUEST_APPROVED" -> "success";
      case "UPDATE", "PAYMENT_INITIATED", "BUDGET_APPROVED" -> "info";
      case "CREATE" -> "primary";
      case "EXPORT" -> "warning";
      default -> "secondary";
    };
  }

  public String getCouleurSod(Boolean sodCheckPassed) {
    if (sodCheckPassed == null) return "secondary";
    return sodCheckPassed ? "success" : "danger";
  }

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

  public String getMode() { return mode; }
  public void setMode(String mode) { this.mode = mode; }
  public UUID getUserId() { return userId; }
  public void setUserId(UUID userId) { this.userId = userId; }
  public UUID getOrgId() { return orgId; }
  public void setOrgId(UUID orgId) { this.orgId = orgId; }
  public String getEntityType() { return entityType; }
  public void setEntityType(String entityType) { this.entityType = entityType; }
  public UUID getEntityId() { return entityId; }
  public void setEntityId(UUID entityId) { this.entityId = entityId; }
  public LocalDateTime getFrom() { return from; }
  public void setFrom(LocalDateTime from) { this.from = from; }
  public LocalDateTime getTo() { return to; }
  public void setTo(LocalDateTime to) { this.to = to; }
  public List<AuditTrailOperationResponse> getOperations() { return operations; }
  public AuditTrailOperationResponse getSelection() { return selection; }
  public void setSelection(AuditTrailOperationResponse selection) { this.selection = selection; }
  public String getErreur() { return erreur; }
}
