package dev.lions.components;

import jakarta.annotation.PostConstruct;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
import jakarta.validation.constraints.NotNull;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import org.primefaces.model.charts.*;
import org.primefaces.model.charts.bar.*;
import org.primefaces.model.charts.line.*;
import org.primefaces.model.charts.pie.*;
import org.primefaces.model.charts.optionconfig.title.Title;
import org.primefaces.model.charts.optionconfig.legend.Legend;

import java.io.Serializable;
import java.util.*;

/**
 * Composant de gestion des graphiques.
 * Fournit des modèles pour les graphiques linéaires, en barres et circulaires.
 *
 * @author Lions Dev Team
 * @version 2.1
 */
@Slf4j
@Named
@ViewScoped
public class ChartComponent implements Serializable {

  private static final long serialVersionUID = 1L;

  private static final List<String> CHART_COLORS = Arrays.asList(
      "rgba(33, 150, 243, 0.8)",
      "rgba(255, 64, 129, 0.8)",
      "rgba(255, 193, 7, 0.8)",
      "rgba(76, 175, 80, 0.8)",
      "rgba(156, 39, 176, 0.8)"
  );

  @Getter @Setter
  private LineChartModel lineModel;

  @Getter @Setter
  private BarChartModel barModel;

  @Getter @Setter
  private PieChartModel pieModel;

  /**
   * Initialise les modèles de graphiques lors de la construction du composant.
   */
  @PostConstruct
  public void init() {
    log.info("Initialisation des modèles de graphiques.");
    createLineModel();
    createBarModel();
    createPieModel();
  }

  /**
   * Crée un modèle de graphique linéaire.
   */
  private void createLineModel() {
    lineModel = new LineChartModel();
    ChartData data = new ChartData();

    LineChartDataSet dataSet = new LineChartDataSet();
    dataSet.setLabel("Évolution des ventes");
    dataSet.setData(new ArrayList<>(generateRandomData(6)));
    dataSet.setBorderColor(CHART_COLORS.get(0));
    dataSet.setFill(false);
    dataSet.setTension(0.4);

    data.addChartDataSet(dataSet);
    data.setLabels(generateLabels(6, "Mois"));

    lineModel.setData(data);
    addChartOptions(lineModel, "Évolution temporelle");

    log.debug("Modèle de graphique linéaire créé.");
  }

  /**
   * Crée un modèle de graphique en barres.
   */
  private void createBarModel() {
    barModel = new BarChartModel();
    ChartData data = new ChartData();

    BarChartDataSet dataSet = new BarChartDataSet();
    dataSet.setLabel("Performance par trimestre");
    dataSet.setData(new ArrayList<>(generateRandomData(4)));
    dataSet.setBackgroundColor(CHART_COLORS.get(1));

    data.addChartDataSet(dataSet);
    data.setLabels(generateLabels(4, "T"));

    barModel.setData(data);
    addChartOptions(barModel, "Performance trimestrielle");

    log.debug("Modèle de graphique en barres créé.");
  }

  /**
   * Crée un modèle de graphique circulaire.
   */
  private void createPieModel() {
    pieModel = new PieChartModel();
    ChartData data = new ChartData();

    PieChartDataSet dataSet = new PieChartDataSet();
    dataSet.setData(Arrays.asList(25, 35, 40));
    dataSet.setBackgroundColor(CHART_COLORS);

    data.addChartDataSet(dataSet);
    data.setLabels(Arrays.asList("Développement", "Marketing", "Infrastructure"));

    pieModel.setData(data);
    addChartOptions(pieModel, "Répartition des activités");

    log.debug("Modèle de graphique circulaire créé.");
  }

  /**
   * Ajoute des options telles que le titre et la légende aux graphiques.
   *
   * @param model Le modèle de graphique.
   * @param title Titre du graphique.
   */
  private void addChartOptions(ChartModel model, String title) {
    Title chartTitle = new Title();
    chartTitle.setDisplay(true);
    chartTitle.setText(title);

    Legend legend = new Legend();
    legend.setDisplay(true);
    legend.setPosition("bottom");

    if (model instanceof LineChartModel) {
      LineChartModel lineChart = (LineChartModel) model;
      lineChart.setExtender((String) chartTitle.getText());
    } else if (model instanceof BarChartModel) {
      BarChartModel barChart = (BarChartModel) model;
      barChart.setExtender((String) chartTitle.getText());
    } else if (model instanceof PieChartModel) {
      PieChartModel pieChart = (PieChartModel) model;
      pieChart.setExtender((String) chartTitle.getText());
    }
  }

  private List<Number> generateRandomData(int size) {
    Random random = new Random();
    List<Number> data = new ArrayList<>();
    for (int i = 0; i < size; i++) {
      data.add(random.nextInt(100));
    }
    return data;
  }

  private List<String> generateLabels(int size, String prefix) {
    List<String> labels = new ArrayList<>();
    for (int i = 1; i <= size; i++) {
      labels.add(prefix + " " + i);
    }
    return labels;
  }
}
