import { LiveAnnouncer } from "@angular/cdk/a11y";
import { SelectionModel } from "@angular/cdk/collections";
import { CurrencyPipe, DatePipe, DecimalPipe, DOCUMENT } from "@angular/common";
import { HttpClient } from "@angular/common/http";
import {
  AfterViewInit,
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  Inject,
  OnDestroy,
  OnInit,
  ViewChild,
  NgZone,
} from "@angular/core";
import { MatDialog } from "@angular/material/dialog";
import { MatPaginator } from "@angular/material/paginator";
import { MatSort, Sort } from "@angular/material/sort";
import { MatTableDataSource } from "@angular/material/table";
import { Title } from "@angular/platform-browser";
import { AgGridAngular } from "ag-grid-angular";
import { saveAs } from "file-saver";
import { tap } from "rxjs/operators";
import { ModalDeleteComponent } from "src/app/components/modal-delete/modal-delete.component";
import { ModalDataExportComponent } from "src/app/components/modal-data-export/modal-data-export.component";
import { ModalGenerateReportingComponent } from "src/app/components/modal-generate-reporting/modal-generate-reporting.component";
import { ModalExecuteComponent } from "src/app/components/modal-execute/modal-execute.component";
import { ProjectsComponent } from "src/app/components/projects/projects.component";
import { VueDetailComponent } from "src/app/components/vue-detail/projets/vue-detail.component";
import { EventService } from 'src/app/core/services/event.service';
import { DataService } from "src/app/core/services/data.service";
import { ProjectService } from "src/app/services/projects.service";
import { ToastService } from "src/app/services/toast.service";
import { ProjectsStore } from "src/app/stores/projects.store";
import { ActivatedRoute, NavigationEnd, Router } from "@angular/router";
import { filter, takeUntil } from "rxjs/operators";
import { Subject } from "rxjs";
import { StorageService } from 'src/app/core/services/storage.service';
import {
  getListViewElements,
  getAllDatas,
  permissionCta,
  ctaName,
} from "src/app/custom/common";
import { DIR_DOCUMENT } from "@angular/cdk/bidi";
import { PaginationService } from "src/app/core/services/pagination.service";
import { environment } from "src/environments/environment";
import { FilterService } from 'src/app/shared/services/filter.service';
import { FilterGroup, FieldDefinition, FieldType, FilterCondition } from 'src/app/shared/models/filter.models';
import { OPERATORS_BY_TYPE } from 'src/app/shared/config/filter-operators.config';
import { DocumentService } from "src/app/services/document.service";

enum ViewStatus {
  LOADING,
  LIST_VIEW_ONE_EMPTY,
  LIST_VIEW_ONE,
}

@Component({
  selector: "app-list-view-one",
  templateUrl: "./list-view-one.page.html",
  styleUrls: ["./list-view-one.page.scss"],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ListViewOnePageComponent
  implements OnInit, AfterViewInit, OnDestroy
{
  // Propriétés principales
  public listViewOne: any[] = [];
  public listSelected: any[] = [];
  public generatedBadges: any[] = [];
  public qtd!: any;
  public isLoadingDetails: boolean = false;
  public selection = new SelectionModel<any>(true, []);
  public isLoading: boolean = true;
  public iconEnabled: boolean = false;
  private lastLoadDataCall: number = 0;
  public exportEnabled: boolean = false;
  public isFirst: boolean = false;
  public searchQuery: string = '';
  private gridApi: any = null;
  public metadata: any = {};
  
  // Enhanced UI state
  public viewMode: 'table' | 'cards' = 'table';
  public activeFiltersCount = 0;
  public gridColumnApi: any;
  
  // Modern List View Properties
  public listViewFields: any[] = [];
  public ctaList: any[] = [];
  
  // Pagination properties
  public totalRecords: number = 0;

  // Filtres AG-Grid
  public ishowFilter = true; // Toggle des filtres flottants - FORCÉ POUR TEST
  public filters: any = {}; // Filtres actifs
  private isRestoringFilters = false; // Flag anti-boucles infinies

  // Système de filtres avancés
  public showFilterPanel = false;
  public currentFilters: FilterGroup | null = null;
  public fieldDefinitions: FieldDefinition[] = [];

  // Propriété privée pour traquer viewStep
  private _viewStep: ViewStatus = ViewStatus.LOADING;

  // Getter/Setter pour traquer les changements de viewStep
  public get viewStep(): ViewStatus {
    return this._viewStep;
  }

  public set viewStep(value: ViewStatus) {
    const oldValue = this._viewStep;
    this._viewStep = value;

    // Log tous les changements de viewStep pour debugging
    if (oldValue !== value) {
      console.log(
        `🔄 viewStep changé: ${ViewStatus[oldValue]} → ${ViewStatus[value]}`,
        {
          stack: new Error().stack?.split("\n").slice(1, 4).join("\n"),
        }
      );
    }
  }
  public viewStatus: typeof ViewStatus = ViewStatus;
  public Math = Math; // Pour utiliser Math dans le template

  // Propriétés de vue
  private current_list_views!: any;
  public current_sections!: string;
  private isUpdatingPagination = false; // Flag pour éviter les boucles infinies
  private current_constraints!: any;
  public sum_volum!: number;
  public count_elem!: number;
  public montant_total!: number;
  public isDelete = false;
  public lastResult: any;
  public widthTable!: number;
  public heightTable!: number;
  public badges!: any;

  // Configuration ag-Grid
  public defaultColDef: any = {
    sortable: true,
    resizable: true,
    filter: true,
    floatingFilter: true, // ← Activé par défaut pour tester
    suppressMenu: true,
    enableCellChangeFlash: false,
    suppressMovable: false, // Permettre le déplacement des colonnes
    // suppressCellFocus: true, // REMOVED: Invalid property in colDef
    minWidth: 150,
    flex: 1,
    // Configuration globale pour ellipsis et tooltips
    wrapText: false,
    autoHeight: false,
    tooltipShowDelay: 500,
    // Tooltip automatique pour les textes longs
    tooltipValueGetter: (params: any) => {
      if (params.value === null || params.value === undefined) return null;

      const value = String(params.value);
      // Afficher le tooltip seulement si le texte dépasse 25 caractères
      if (value.length > 25) {
        return value;
      }

      // Gestion des objets complexes
      if (typeof params.value === 'object') {
        if (params.value.name) return params.value.name;
        if (params.value.displayName) return params.value.displayName;
        const jsonStr = JSON.stringify(params.value);
        return jsonStr.length > 25 ? jsonStr : null;
      }

      return null;
    },
    suppressKeyboardEvent: (params: any) => {
      return params.event.key === "Tab";
    },
    cellClass: "ag-cell-no-focus",
    headerClass: "ag-header-no-focus",
    unSortIcon: true,
    sortingOrder: ["asc", "desc", null],
    filterParams: {
      buttons: ["clear", "apply"],
      closeOnApply: true,
      suppressAndOrCondition: true,
      inRangeInclusive: true,
    },
  };

  public columnDefAgrid = [
    {
      headerName: "",
      field: "",
      maxWidth: 80,
      headerCheckboxSelection: true,
      headerCheckboxSelectionFilteredOnly: true,
      checkboxSelection: true,
      filter: false,
      pinned: "left",
      lockPinned: true,
      suppressMenu: true,
      suppressMovable: true,
      resizable: false, // Use resizable: false instead of suppressResize
    },
  ];

  public gridOptions: any = {
    // Configuration pour optimiser les performances et l'affichage
    enableRangeSelection: true,
    enableCellChangeFlash: false,
    animateRows: false,
    suppressRowTransform: false,
    suppressColumnVirtualisation: false,
    // suppressRowVirtualisation: false, // REMOVED: Invalid property in AG-Grid
    rowHeight: 40,
    headerHeight: 40,
    groupHeaderHeight: 40,
    floatingFiltersHeight: 35,
    pivotHeaderHeight: 40,
    pivotGroupHeaderHeight: 40,
    // Pagination
    pagination: false, // Désactivé car nous utilisons une pagination personnalisée
    suppressPaginationPanel: true,
    // Selection
    rowSelection: 'multiple',
    suppressRowClickSelection: false,
    suppressRowHoverHighlight: true,
    // enableColumnMoveByDrag: true, // REMOVED: Invalid property - columns are movable by default
    // Performance
    // suppressCellFocus: true, // REMOVED: Invalid property in gridOptions (use in defaultColDef instead)
    suppressColumnMoveAnimation: false,
    suppressAnimationFrame: false,
    suppressParentsInRowNodes: true,
    suppressScrollOnNewData: true,
    maxConcurrentDatasourceRequests: 2,
    cacheOverflowSize: 2,
    purgeClosedRowNodes: true,
    // Tooltips
    enableBrowserTooltips: true,
    tooltipShowDelay: 500,
    // tooltipHideDelay: 2000, // REMOVED: Invalid property in AG-Grid
    // Callbacks
    onGridReady: (params: any) => {
      this.gridOptions.api = params.api;
      this.gridOptions.columnApi = params.columnApi;
      console.log("✅ ag-Grid API prête");

      // Si des données ont déjà été chargées, les afficher maintenant
      if (this.rowData && this.rowData.length > 0) {
        console.log("🔄 Chargement des données en attente dans ag-Grid:", this.rowData.length, "éléments");
        params.api.setRowData(this.rowData);
        params.api.sizeColumnsToFit();
      }
    },
    onFirstDataRendered: (params: any) => {
      params.api.sizeColumnsToFit();
    },
    // Localization
    localeText: {
      page: "Page",
      more: "Plus",
      to: "à",
      of: "sur",
      next: "Suivant",
      last: "Dernier",
      first: "Premier",
      previous: "Précédent",
      loadingOoo: "Chargement...",
      selectAll: "Tout sélectionner",
      searchOoo: "Rechercher...",
      blanks: "Vides",
      noMatches: "Aucune correspondance",
      pinColumn: "Épingler la colonne",
      valueAggregation: "Agrégation de valeur",
      autosizeThiscolumn: "Ajuster cette colonne",
      autosizeAllColumns: "Ajuster toutes les colonnes",
      groupBy: "Grouper par",
      ungroupBy: "Dégrouper",
      resetColumns: "Réinitialiser les colonnes",
      expandAll: "Développer tout",
      collapseAll: "Réduire tout",
      toolPanel: "Panneau d'outils",
      export: "Exporter",
      csvExport: "Export CSV",
      excelExport: "Export Excel",
    },
  };

  public dataHeaderAgrdid = [
    {
      headerName: "",
      field: "",
      maxWidth: 80,
      headerCheckboxSelection: true,
      headerCheckboxSelectionFilteredOnly: true,
      checkboxSelection: true,
      filter: false,
      pinned: "left",
      editable: false,
      lockPinned: true,
      suppressMenu: true,
      suppressMovable: true,
      resizable: false, // Use resizable: false instead of suppressResize
    },
  ] as any;

  // Caches optimisés
  private cellRendererCache = new Map<string, any>();
  private valueFormatterCache = new Map<string, any>();
  private dataCache = new Map<string, any>();
  private lastModuleName: string = "";
  private lastDomaine: string = "";

  // Données et style
  public rowStyle = { cursor: "pointer" };
  public getRowStyle = (params: any) => {
    return params.node.rowIndex % 2 === 0
      ? { ...this.rowStyle, background: "#fff" }
      : { ...this.rowStyle, background: "#f6f8fa" };
  };

  private tempData: any;
  public numberProject: number = 0;
  public rowData!: any;

  // Filtres et colonnes
  filterKeys: any;
  reducer = (accumulator: boolean, currentValue: boolean) =>
    accumulator && currentValue;
  public displayedColumns: string[] = ["select"];
  public displayedColumnsCsv: string[] = [];

  // ViewChildren
  @ViewChild(MatPaginator) paginator!: MatPaginator;
  @ViewChild(MatSort) sort!: MatSort;
  @ViewChild("agGrid") agGrid!: AgGridAngular;

  // Propriétés de navigation et permissions
  public current_click = "";
  public current_condition!: any;
  private records: any;
  public moduleName = "";
  public domaine = "";
  public ctas: any = [];
  public permissions: any = [];
  public isPermExec: boolean = false;
  public isPermDel: boolean = false;
  public isPermCreate: boolean = false;
  public isPermUpdate: boolean = false;
  public isPermReporting: boolean = false;
  public isPermRefresh: boolean = false;
  public isFirstGetData: boolean = true;
  // Propriétés pour la gestion de la sélection ag-Grid
  public selectedRecords: any[] = [];
  public selectedCount: number = 0;

  // Destruction subject
  private destroy$ = new Subject<void>();

  // Source de données
  public dataSource = new MatTableDataSource<any>();

  // Templates ag-Grid
  public overlayLoadingTemplate =
    '<div class="loader" aria-label="loading"></div>';
  public overlayNoRowsTemplate =
    '<span style="padding: 10px; border: 2px solid #666; background: #55AA77;">Chargement en cours ... </span>';
  constructor(
    public projectStore: ProjectsStore,
    private _liveAnnouncer: LiveAnnouncer,
    public dataService: DataService,
    public projectService: ProjectService,
    public dialog: MatDialog,
    public event: EventService,
    private contextuel: EventService,
    @Inject(DOCUMENT) private document: Document,
    private toast: ToastService,
    private titleService: Title,
    private currencyPipe: CurrencyPipe,
    private decimalPipe: DecimalPipe,
    private datePipe: DatePipe,
    private routeur: Router,
    private route: ActivatedRoute,
    public storage: StorageService,
    public paginationService: PaginationService,
    private cdr: ChangeDetectorRef,
    private zone: NgZone,
    private http: HttpClient,
    private filterService: FilterService,
    private documentService: DocumentService
  ) {
    this.filters = {};
    this.dataSource.filterPredicate = this.setupFilter();

    // Initialisation par défaut des colonnes pour éviter les erreurs de template
    this.displayedColumns = ["select"];
    this.displayedColumnsCsv = [];

    // Écoute des changements de pagination pour refresh ag-Grid
    this.paginationService.getState().pipe(
      takeUntil(this.destroy$)
    ).subscribe(state => {
      console.log('📊 État pagination changé:', state);
      // Recharger les données seulement si ce n'est pas une mise à jour interne
      if (this.gridOptions?.api && this.moduleName && this.domaine && !this.isLoading && this.rowData?.length > 0 && !this.isUpdatingPagination) {
        console.log('🔄 Rechargement des données après changement de pagination (navigation utilisateur)');
        this.isUpdatingPagination = true;
        this.loadPagedData().finally(() => {
          this.isUpdatingPagination = false;
        });
      }
    });

    console.log("🏗️ Constructeur - Colonnes et pagination initialisées");
  }
  ngOnInit() {
    console.log("🚀 ngOnInit - Démarrage du composant");
    
    // Reset forcé des flags de chargement au démarrage
    console.log("🔧 Reset initial des flags de chargement");
    this.isLoading = false;
    this.isLoadingDetails = false;
    this.lastLoadDataCall = 0;
    
    // Initialisation de base de la pagination (sera mise à jour avec les vraies données)
    console.log("🔧 Initialisation de base de la pagination");
    this.paginationService.updatePaginationInfo({
      currentPage: 1,
      pageSize: 100,
      totalRecords: 0,
      totalFiltered: 0,
      totalPages: 0,
      hasNextPage: false,
      hasPreviousPage: false
    });
    this.resetLoadingStates();

    // Vérifier si on arrive juste après la connexion
    const autoLoadFlag = localStorage.getItem("autoLoadFirstData");
    if (autoLoadFlag === "true") {
      console.log(
        "🎯 Détection: arrivée après connexion avec données préchargées"
      );
    }

    // Écouter les événements de navigation pour les rechargements
    this.routeur.events
      .pipe(
        filter((event) => event instanceof NavigationEnd),
        takeUntil(this.destroy$)
      )
      .subscribe(async (event) => {
        const navigationEnd = event as NavigationEnd;
        console.log("🧭 Navigation détectée:", navigationEnd.url);
        // Petit délai pour éviter les appels simultanés
        setTimeout(() => {
          this.loadData();
        }, 100);
      });

    // Charger les données après un délai pour éviter les conflits avec NavigationEnd
    setTimeout(() => {
      this.loadData();
    }, 200);
  }

  ngAfterViewInit() {
    setTimeout(() => {
      if (this.paginator && this.dataSource && !this.dataSource.paginator) {
        this.dataSource.paginator = this.paginator;
      }
      if (this.sort && this.dataSource && !this.dataSource.sort) {
        this.dataSource.sort = this.sort;
      }

      this.dataSource.sortingDataAccessor = (item, property) => {
        switch (property) {
          case "project_name": {
            let newDate = new Date(item["Created At"]);
            return newDate;
          }
          case "Date engagement operation": {
            let newDate = new Date(item["Date engagement operation"]);
            return newDate;
          }
          default: {
            return item[property];
          }
        }
      };

      this.getDataObject();

      if (
        this.current_list_views &&
        this.current_list_views.length > 0 &&
        !this.current_sections
      ) {
        this.current_sections = this.current_list_views[0].name;
        this.buildAndSetColumns();
      }
      this.cdr.markForCheck();

      // Vérification finale de l'état après l'initialisation complète
      setTimeout(() => {
        console.log("🔍 ngAfterViewInit - Vérification finale de l'état");
        this.forceCorrectViewStep();
      }, 200);
    }, 100);
  }

  ngOnDestroy() {
    this.iconEnabled = false;
    this.destroy$.next();
    this.destroy$.complete();

    this.dataCache.clear();
    this.cellRendererCache.clear();
    this.valueFormatterCache.clear();

    if (this.agGrid && this.agGrid.api) {
      this.agGrid.api.destroy();
    }
  }
  /**
   * Sauvegarde les filtres ag-Grid actuels
   */

  /**
   * Nouvelle méthode avec pagination et filtres
   */
  async loadPagedData(): Promise<void> {
    console.log('🔄 loadPagedData() - Chargement avec pagination');

    if (!this.moduleName || !this.domaine) {
      console.warn('⚠️ Module ou domaine manquant pour la pagination');
      return;
    }

    // Sauvegarder les filtres avant rechargement
    const savedFilters = this.saveCurrentFilters();

    this.isLoadingDetails = true;
    this.cdr.markForCheck();

    try {
      const params = this.paginationService.getApiParams();

      // Récupérer les contraintes depuis les métadonnées du module
      const constraints = this.getConstraintsFromMetadata();

      const response = await this.dataService.getPagedData(
        this.domaine,
        this.moduleName,
        {
          page: params.page,
          size: params.limit,
          filters: constraints
        }
      ).toPromise();

      if (response) {
        console.log('✅ Données paginées reçues:', response);
        
        // Mettre à jour les informations de pagination avec les vraies données depuis PagedResult.pagination
        if (!this.isUpdatingPagination && response.pagination) {
          this.isUpdatingPagination = true;
          this.paginationService.updatePaginationInfo({
            currentPage: response.pagination.currentPage || 1,
            pageSize: response.pagination.pageSize || 100,
            totalRecords: response.pagination.totalRecords || 0,
            totalFiltered: response.pagination.totalFiltered || response.pagination.totalRecords || 0,
            totalPages: response.pagination.totalPages || 0,
            hasNextPage: response.pagination.hasNextPage || false,
            hasPreviousPage: response.pagination.hasPreviousPage || false
          });
          setTimeout(() => {
            this.isUpdatingPagination = false;
          }, 100);
        }
        
        console.log('📊 État pagination après mise à jour:', this.paginationService.getCurrentState());
        
        // Mettre à jour les données
        if (response.data || (response as any).records) {
          const data = response.data || (response as any).records;
          this.rowData = this.preprocessDataForAgGrid(data);
          this.records = data;
          this.listViewOne = data;
          this.numberProject = data.length || 0;

          console.log('📊 Données traitées:', {
            dataLength: data.length,
            rowDataLength: this.rowData.length,
            viewStep: this.viewStep
          });

          // Mettre à jour les indicateurs
          if (response.indicators) {
            this.updateIndicators(response.indicators);
          }

          // Définir le statut de la vue
          if (data.length > 0) {
            this.viewStep = ViewStatus.LIST_VIEW_ONE;
            this.exportEnabled = true;
          } else {
            this.viewStep = ViewStatus.LIST_VIEW_ONE_EMPTY;
            this.exportEnabled = false;
          }

          // Mettre à jour ag-Grid avec les données de la page courante uniquement
          if (this.gridOptions?.api) {
            console.log('🔄 Mise à jour ag-Grid avec', this.rowData.length, 'éléments');

            // Recharger les données
            this.gridOptions.api.setRowData(this.rowData);

            // Restaurer les filtres après le rechargement
            if (savedFilters && Object.keys(savedFilters.filters || {}).length > 0) {
              setTimeout(() => {
                this.restoreFilters(savedFilters);
              }, 50); // Petit délai pour s'assurer que les données sont chargées
            }

            this.gridOptions.api.sizeColumnsToFit();

            console.log('✅ ag-Grid mis à jour:', {
              currentPage: (response as any).pagination?.currentPage || 1,
              totalPages: (response as any).pagination?.totalPages || 1,
              totalRecords: (response as any).pagination?.totalRecords || 0,
              pageData: this.rowData.length
            });
          } else {
            console.warn('⚠️ ag-Grid API pas encore prête, les données seront affichées à l\'initialisation de la grille');
          }

          // Forcer la détection des changements
          this.cdr.detectChanges();
        }
      }
    } catch (error) {
      console.error('❌ Erreur lors du chargement des données paginées:', error);
      this.viewStep = ViewStatus.LIST_VIEW_ONE_EMPTY;
    } finally {
      this.isLoadingDetails = false;
      this.cdr.markForCheck();

      console.log('🏁 Fin loadPagedData:', {
        isLoadingDetails: this.isLoadingDetails,
        rowDataLength: this.rowData?.length || 0,
        columnDefsLength: this.columnDefAgrid?.length || 0,
        viewStep: this.viewStep,
        hasGridApi: !!this.gridOptions?.api
      });
    }
  }

  /**
   * Méthodes de navigation pour la pagination personnalisée
   */
  public goToFirstPage(): void {
    console.log('🔄 Navigation vers première page');
    this.paginationService.firstPage();
  }

  public goToPreviousPage(): void {
    console.log('🔄 Navigation vers page précédente');
    this.paginationService.previousPage();
  }

  public goToNextPage(): void {
    console.log('🔄 Navigation vers page suivante');
    this.paginationService.nextPage();
  }

  public goToLastPage(): void {
    console.log('🔄 Navigation vers dernière page');
    this.paginationService.lastPage();
  }

  /**
   * Supprime les éléments sélectionnés
   */
  public deleteSelected(): void {
    if (this.listSelected && this.listSelected.length > 0) {
      console.log('🗑️ Suppression des éléments sélectionnés:', this.listSelected);

      // Ouvrir le modal de confirmation de suppression
      const dialogRef = this.dialog.open(ModalDeleteComponent, {
        width: "500px",
        data: {
          records: this.listSelected,
          count: this.listSelected.length,
          data: {
            from: this.moduleName  // Le modal cherche this.data.data.from
          },
          message: `Êtes-vous sûr de vouloir supprimer ${this.listSelected.length} élément(s) sélectionné(s) ?`,
        },
      });

      // Le modal fait directement la suppression, on écoute juste la fermeture pour rafraîchir
      dialogRef.afterClosed().subscribe((result) => {
        console.log('🔍 Modal fermé, rafraîchissement de la liste...');
        // Rafraîchir la liste et réinitialiser la sélection
        this.refreshList();
        this.clearSelection();
      });
    } else {
      console.warn('⚠️ Aucun élément sélectionné pour la suppression');
    }
  }

  /**
   * Force le rechargement des CTA et permissions
   */
  public forceReloadCTA(): void {
    console.log('🔄 Force reload CTA - Clear cache and reload metadata');
    
    // Vider le cache des CTA
    const ctasCacheKey = `ctas_${this.moduleName}`;
    this.dataCache.delete(ctasCacheKey);
    
    // Réinitialiser les permissions
    this.ctas = [];
    this.isPermCreate = false;
    this.updatePermissions(); // Re-evaluate permissions after clearing cache
    
    // Recharger les métadonnées
    this.initializeMetadata().then(() => {
      console.log('✅ CTA rechargés:', {
        ctas: this.ctas?.length || 0,
        isPermCreate: this.isPermCreate,
        isPermReporting: this.isPermReporting
      });
      this.cdr.markForCheck();
    });
  }

  private async addPNR(): Promise<void> {
    // Dynamically import ModalExecuteComponent and SPC config
    const { ModalExecuteComponent } = await import('src/app/components/modal-execute/modal-execute.component');
    const { createSpcModalConfig } = await import('src/app/components/modal-execute/spc-operations.config');

    // Créer la configuration pour l'opération load_pnr
    const modalConfig = createSpcModalConfig(
      'load_pnr',
      [],
      this.moduleName
    );

    const dialogRef = this.dialog.open(ModalExecuteComponent, {
      width: '500px',
      data: modalConfig
    });

    dialogRef.afterClosed().subscribe(async (result) => {
      if (result && result.confirmed) {
        try {
          const pnrNumber = result.inputValue || result.spcPayload?.command_user;

          if (!pnrNumber) {
            this.showErrorNotification('Numéro de PNR manquant');
            return;
          }

          console.log('🔄 Chargement du PNR via SPC:', pnrNumber);
          console.log('📋 SPC Payload:', result.spcPayload);

          // Utiliser le payload SPC pour l'exécution
          await this.executeSpcOperation(result.spcPayload);

          // Recharger les données
          console.log('✅ PNR chargé avec succès');
          this.refreshList();
          this.loadData();
        } catch (error) {
          console.error('❌ Erreur lors du chargement du PNR:', error);
          this.showErrorNotification('Erreur lors du chargement du PNR: ' + error);
        }
      }
    });
  }


  /**
   * Exécute une opération SPC avec le payload fourni
   */
  private async executeSpcOperation(spcPayload: any): Promise<void> {
    try {
      console.log('🔄 Exécution opération SPC:', spcPayload);

      // Utiliser le service project pour exécuter l'opération SPC
      const result = await this.projectService
        .executeSpcOperation(spcPayload, this.moduleName)
        .toPromise();

      if (result && result.success) {
        this.toast.showSuccess(
          `Opération ${spcPayload.operation_type} exécutée avec succès`
        );
      } else {
        const errorMessage = result?.message || "Erreur lors de l'exécution SPC";
        this.toast.showError(errorMessage);
      }
    } catch (error) {
      console.error('❌ Erreur lors de l\'exécution SPC:', error);
      const errorMessage =
        error instanceof Error ? error.message : 'Erreur lors de l\'exécution SPC';
      this.toast.showError(errorMessage);
      throw error;
    }
  }

  /**
   * Afficher une notification d'erreur
   */
  private showErrorNotification(message: string): void {
    this.toast.showError(message);
  }

  /**
   * Met à jour les indicateurs/badges
   */
  private updateIndicators(indicators: any): void {
    console.log('📊 Mise à jour des indicateurs:', indicators);

    this.generatedBadges = [];

    // Utiliser totalFiltered au lieu de total quand des filtres sont actifs
    const paginationState = this.paginationService.getCurrentState();
    const hasActiveFilters = paginationState.filters && Object.keys(paginationState.filters).length > 0;
    const totalToDisplay = hasActiveFilters ? paginationState.totalFiltered : (indicators.total || paginationState.totalRecords);

    if (totalToDisplay !== undefined) {
      this.generatedBadges.push({
        title: hasActiveFilters ? 'Résultats filtrés' : 'Total',
        result: totalToDisplay,
        icon: 'assessment'
      });
    }

    if (indicators.actifs !== undefined) {
      this.generatedBadges.push({
        title: 'Actifs',
        result: indicators.actifs,
        icon: 'check_circle'
      });
    }

    if (indicators.inactifs !== undefined) {
      this.generatedBadges.push({
        title: 'Inactifs',
        result: indicators.inactifs,
        icon: 'cancel'
      });
    }

    // Indicateurs spécifiques selon le module
    Object.keys(indicators).forEach(key => {
      if (!['total', 'actifs', 'inactifs'].includes(key)) {
        this.generatedBadges.push({
          title: key.charAt(0).toUpperCase() + key.slice(1).replace('_', ' '),
          result: indicators[key],
          icon: 'info'
        });
      }
    });
  }

  /**
   * Charge les données principales (version avec pagination)
   */
  async loadData(): Promise<void> {
    const currentTime = Date.now();
    const timeSinceLastCall = currentTime - this.lastLoadDataCall;

    console.log("🔄 loadData() - Début du chargement avec pagination");
    console.log("🔄 État actuel - isLoading:", this.isLoading, "isLoadingDetails:", this.isLoadingDetails);
    console.log("🔄 Temps depuis le dernier appel:", timeSinceLastCall, "ms");

    // Éviter les appels multiples simultanés avec timeout de sécurité
    if (this.isLoading || this.isLoadingDetails) {
      console.log("⚠️ Chargement déjà en cours, ignorer l'appel");

      // Timeout de sécurité : si le loading est bloqué depuis plus de 5 secondes, forcer le reset
      setTimeout(() => {
        if (this.isLoading || this.isLoadingDetails) {
          console.log("🔧 Reset de sécurité des flags de chargement");
          this.isLoading = false;
          this.isLoadingDetails = false;
          this.lastLoadDataCall = 0;
          this.cdr.markForCheck();
        }
      }, 5000);

      return;
    }

    // Éviter les appels trop rapprochés (moins de 500ms) - debounce amélioré
    if (timeSinceLastCall < 500) {
      console.log("⚠️ Appel trop rapide, ignorer (délai:", timeSinceLastCall, "ms)");
      return;
    }
    this.lastLoadDataCall = currentTime;

    this.isLoading = true;
    this.isLoadingDetails = true;
    this.viewStep = ViewStatus.LOADING;
    this.cdr.markForCheck();

    try {
      this.resetLoadingStates();

      // Récupération des informations de domaine et module
      const dd = this.storage.getItem("__domaineDD");
      const __domainedd = dd ? JSON.parse(dd) : {};
      const previousModule = this.moduleName;
      this.moduleName = __domainedd?.modulename;
      this.domaine = __domainedd?.domaine;

      console.log("📝 Module et domaine:", {
        previousModule,
        moduleName: this.moduleName,
        domaine: this.domaine,
      });

      // Si le module a changé, vider le cache des colonnes pour forcer le rechargement
      if (previousModule && previousModule !== this.moduleName) {
        console.log("🔄 Changement de module détecté, nettoyage complet");

        // Réinitialiser les colonnes et CTAs
        this.columnDefAgrid = [];
        this.current_list_views = [];
        this.ctas = [];

        // Réinitialiser les sélections
        this.listSelected = [];
        this.selection.clear();
        console.log("✅ Sélections réinitialisées");

        // Réinitialiser les filtres (ils seront rechargés depuis les métadonnées)
        this.filters = {};
        this.activeFiltersCount = 0;
        this.currentFilters = null; // Système de filtres avancés
        this.paginationService.reset(); // Réinitialiser aussi le service de pagination
        console.log("✅ Filtres réinitialisés");

        // Nettoyer les paramètres d'URL (filtres, pagination, etc.)
        this.routeur.navigate([], {
          relativeTo: this.route,
          queryParams: {},
          replaceUrl: true
        }).then(() => {
          console.log("✅ Paramètres d'URL nettoyés");
        });

        // Vider le cache pour ce module spécifique
        const cacheKey = `listview_${previousModule}`;
        this.dataCache.delete(cacheKey);
      }

      if (!this.moduleName || !this.domaine) {
        console.error("❌ Module ou domaine manquant");
        this.viewStep = ViewStatus.LIST_VIEW_ONE_EMPTY;
        this.isLoading = false;
        this.isLoadingDetails = false;
        this.cdr.markForCheck();
        return;
      }

      // Titre de la page
      let title = this.moduleName + " | ESTAIR-CONNECT ";
      this.titleService.setTitle(title);

      // Charger d'abord les métadonnées (colonnes, CTA)
      await this.initializeMetadata();

      // Charger les données initiales avec pagination
      await this.loadPagedData();

      console.log("✅ Chargement des données terminé:", {
        rowDataLength: this.rowData?.length || 0,
        viewStep: this.viewStep
      });

    } catch (error) {
      console.error("❌ Erreur lors du chargement des données:", error);
      this.viewStep = ViewStatus.LIST_VIEW_ONE_EMPTY;
      this.isLoading = false;
      this.isLoadingDetails = false;
      this.cdr.markForCheck();
    } finally {
      this.isLoading = false;
      // isLoadingDetails est géré dans loadPagedData()
      this.cdr.markForCheck();
    }
  }

  /**
   * Initialise les métadonnées (colonnes, CTA, permissions)
   */
  private async initializeMetadata(): Promise<void> {
    console.log("🔧 Initialisation des métadonnées...");

    // Récupérer les éléments de liste de vue (colonnes)
    const cacheKey = `listview_${this.moduleName}`;
    let lvs = this.dataCache.get(cacheKey);
    if (!lvs) {
      console.log("📡 Récupération des éléments de liste de vue...");
      lvs = await getListViewElements(this.moduleName, this.dataService);
      if (lvs) {
        this.dataCache.set(cacheKey, lvs);
      }
    }

    // Support des deux formats: nouveau (lvs[module].ListeView) et ancien (lvs[module].data.ListeView)
    const moduleData = lvs && lvs[this.moduleName] ? lvs[this.moduleName] : null;
    const listeView = moduleData?.data?.ListeView || moduleData?.ListeView;

    this.current_list_views = listeView?.list || [];

    console.log("📋 Vues disponibles:", this.current_list_views?.length || 0);

    // Récupérer les CTA (permissions)
    const ctasCacheKey = `ctas_${this.moduleName}`;
    let ctas = this.dataCache.get(ctasCacheKey);
    if (!ctas) {
      console.log("🔐 Récupération des CTA...");
      if (listeView) {
        ctas = listeView.cta || listeView.ctas;
        if (ctas) {
          this.dataCache.set(ctasCacheKey, ctas);
          console.log("✅ CTA trouvés:", ctas?.length || 0);
        }
      }
    }

    this.ctas = ctas || [];
    console.log("🎯 CTA trouvés:", this.ctas?.length || 0);

    // Les contraintes seront chargées automatiquement lors de l'appel API
    // Elles seront aussi restaurées dans l'interface ag-Grid après le chargement des données
    console.log("ℹ️ Les contraintes du module seront appliquées lors du chargement des données");

    // Debug détaillé
    console.log("🔍 Debug métadonnées:", {
      moduleName: this.moduleName,
      hasModuleData: !!moduleData,
      hasListeView: !!listeView,
      listViewsCount: this.current_list_views?.length || 0,
      ctasCount: this.ctas?.length || 0,
      hasConstraints: !!listeView?.constraints
    });

    // Traitement des permissions
    if (this.ctas && this.ctas.length > 0) {
      console.log("🔐 Traitement des permissions CTA...");
      this.ctas.forEach((item: any) => {
        if (item?.action != "action") {
          this.permissionCta(item.action);
        }
      });
    }

    // Initialiser les colonnes si on a des vues
    if (this.current_list_views && this.current_list_views.length > 0) {
      this.current_sections = this.current_list_views[0].name;
      this.buildAndSetColumns();
      console.log('✅ Colonnes construites:', {
        columnDefsLength: this.columnDefAgrid?.length || 0,
        currentSection: this.current_sections
      });
    } else {
      console.warn('⚠️ Aucune vue disponible pour construire les colonnes');
    }
  }

  /**
   * Récupère les contraintes depuis les métadonnées du module dans localStorage
   */
  private getConstraintsFromMetadata(): any {
    try {
      const __lvs = localStorage.getItem('__lvs');
      if (!__lvs) {
        console.log('⚠️ Pas de métadonnées __lvs disponibles');
        return {};
      }

      const lvsData = JSON.parse(__lvs);
      const moduleMetadata = lvsData[this.moduleName];

      if (!moduleMetadata?.ListeView?.list || !moduleMetadata.ListeView.list[0]) {
        console.log('⚠️ Pas de ListeView.list[0] pour ce module');
        return {};
      }

      const constraints = moduleMetadata.ListeView.list[0].constraints;

      if (!constraints || typeof constraints !== 'object') {
        console.log('ℹ️ Pas de contraintes définies dans ListeView.list[0].constraints');
        return {};
      }

      // Extraire les filtres depuis constraints.and
      const andFilters = constraints.and || {};

      // Nettoyer les contraintes (retirer les valeurs nulles et vides)
      const cleanedConstraints: any = {};
      if (typeof andFilters === 'object' && !Array.isArray(andFilters)) {
        Object.keys(andFilters).forEach(key => {
          const value = andFilters[key];
          // Ne garder que les valeurs non-nulles et non-vides
          if (value != null && value !== '') {
            cleanedConstraints[key] = value;
          }
        });
      }

      console.log('🔍 Contraintes chargées depuis localStorage:', cleanedConstraints);
      return cleanedConstraints;

    } catch (error) {
      console.error('❌ Erreur lors de la récupération des contraintes:', error);
      return {};
    }
  }

  /**
   * Sauvegarde les filtres utilisateur dans les contraintes du localStorage
   */
  private saveFiltersToLocalStorage(filters: Record<string, any>): void {
    try {
      const __lvs = localStorage.getItem('__lvs');
      if (!__lvs) {
        console.warn('⚠️ Pas de métadonnées __lvs disponibles pour sauvegarder les filtres');
        return;
      }

      const lvsData = JSON.parse(__lvs);
      const moduleMetadata = lvsData[this.moduleName];

      if (!moduleMetadata?.ListeView?.list || !moduleMetadata.ListeView.list[0]) {
        console.warn('⚠️ Pas de ListeView.list[0] pour sauvegarder les filtres');
        return;
      }

      // Initialiser constraints si nécessaire
      if (!moduleMetadata.ListeView.list[0].constraints) {
        moduleMetadata.ListeView.list[0].constraints = { and: {} };
      }

      // Nettoyer les filtres : ne garder que ceux qui ont une valeur
      const cleanedFilters: any = {};

      Object.keys(filters).forEach(key => {
        const value = filters[key];
        // Ignorer _operator et autres métadonnées
        if (key === '_operator') {
          return;
        }
        // Ne sauvegarder que les filtres avec une valeur non-nulle et non-vide
        if (value != null && value !== '') {
          cleanedFilters[key] = value;
        }
      });

      // Structurer les contraintes avec and/or
      moduleMetadata.ListeView.list[0].constraints = {
        and: cleanedFilters
      };

      // Sauvegarder dans le localStorage
      localStorage.setItem('__lvs', JSON.stringify(lvsData));

      console.log('💾 Filtres sauvegardés dans localStorage:', {
        module: this.moduleName,
        constraints: moduleMetadata.ListeView.list[0].constraints
      });

    } catch (error) {
      console.error('❌ Erreur lors de la sauvegarde des filtres dans localStorage:', error);
    }
  }

  /**
   * Initialise les données récupérées (maintenu pour compatibilité avec ag-Grid)
   */
  public initializeData(data: any) {
    console.log("🔧 initializeData() - Début initialisation:", data);

    if (data == null) {
      console.log("⚠️ Aucune donnée reçue - affichage de la vue vide");
      this.viewStep = ViewStatus.LIST_VIEW_ONE_EMPTY;
      this.isLoading = false;
      this.isLoadingDetails = false;
      this.cdr.markForCheck();
      return;
    }
    const moduleData = data[this.moduleName];
    console.log("📋 Données du module:", {
      moduleName: this.moduleName,
      moduleData,
      dataKeys: Object.keys(data || {}),
      dataStructure: data,
    });

    // Si les données ne sont pas trouvées avec le nom exact du module, essayer d'autres clés
    let actualModuleData = moduleData;
    if (!actualModuleData && data) {
      console.log("🔍 Recherche de données avec une clé alternative...");

      // Essayer la première clé disponible si elle contient des données
      const keys = Object.keys(data);
      for (const key of keys) {
        if (Array.isArray(data[key]) && data[key].length > 0) {
          console.log(`✅ Données trouvées avec la clé: ${key}`);
          actualModuleData = data[key];
          break;
        }
      }
    }

    this.records = actualModuleData;
    this.listViewOne = actualModuleData;
    this.numberProject = actualModuleData?.length || 0;
    this.selection.clear();

    this.dataSource.data = actualModuleData || [];
    if (!actualModuleData || actualModuleData.length === 0) {
      console.log(
        "📭 Données vides - vérification des CTA et configuration..."
      );

      // Si on a des CTA ou des colonnes configurées, utiliser ag-Grid même sans données
      if (
        (this.ctas && this.ctas.length > 0) ||
        (this.columnDefAgrid && this.columnDefAgrid.length > 0)
      ) {
        console.log(
          "🎯 CTA ou colonnes disponibles - utilisation d'ag-Grid avec données vides"
        );
        this.rowData = []; // ag-Grid vide mais prêt
        this.exportEnabled = false; // Pas d'export si pas de données
        this.viewStep = ViewStatus.LIST_VIEW_ONE;
      } else {
        console.log("📋 Aucune configuration - vue Material Table vide");
        this.viewStep = ViewStatus.LIST_VIEW_ONE_EMPTY;
        this.exportEnabled = false;
      }
    } else {
      console.log(
        "📊 Données trouvées - traitement pour ag-Grid:",
        actualModuleData.length,
        "éléments"
      );
      this.rowData = this.preprocessDataForAgGrid(actualModuleData);

      if (this.paginator && !this.dataSource.paginator) {
        this.dataSource.paginator = this.paginator;
      }
      if (this.sort && !this.dataSource.sort) {
        this.dataSource.sort = this.sort;
      }

      this.exportEnabled = true;
      this.viewStep = ViewStatus.LIST_VIEW_ONE;

      if (!this.isFirst) {
        this.routeur.navigate([
          `admin/${this.domaine.toLowerCase()}/${this.moduleName.toLowerCase()}/list/all`,
        ]);
      }
    } 
    // IMPORTANT: Finaliser le chargement AVANT d'initialiser les colonnes
    this.isLoadingDetails = false;
    this.isLoading = false;
    this.heightTable = actualModuleData ? actualModuleData.length : 0;

    console.log("🎯 États finalisés:", {
      viewStep: this.viewStep,
      viewStepString: ViewStatus[this.viewStep],
      isLoading: this.isLoading,
      isLoadingDetails: this.isLoadingDetails,
      rowDataLength: this.rowData?.length,
      moduleDataLength: actualModuleData?.length,
      hasData: !!(actualModuleData && actualModuleData.length > 0),
    });

    // Initialiser les colonnes après que le chargement soit terminé
    this.initializeColumns();
    console.log(
      "✅ initializeData() - Initialisation terminée avec viewStep:",
      ViewStatus[this.viewStep]
    );

    // FORCER la détection de changement
    this.cdr.markForCheck();

    // ag-Grid server-side se charge automatiquement du chargement des données
    console.log('✅ Initialisation terminée - ag-Grid server-side actif');
  }

  /**
   * Initialise les colonnes pour ag-Grid
   */
  private initializeColumns(): void {
    console.log("🔧 initializeColumns() - Début initialisation colonnes");
    console.log("📋 État actuel:", {
      current_sections: this.current_sections,
      current_list_views_length: this.current_list_views?.length,
    });

    if (
      !this.current_sections &&
      this.current_list_views &&
      this.current_list_views.length > 0
    ) {
      this.current_sections = this.current_list_views[0].name;
      console.log("🎯 Section par défaut définie:", this.current_sections);
    }

    if (this.current_sections) {
      console.log(
        "🏗️ Construction des colonnes pour la section:",
        this.current_sections
      );
      this.buildAndSetColumns();
    } else {
      console.log("⚠️ Aucune section disponible pour construire les colonnes");
    }
  }
  /**
   * Construit et configure les colonnes ag-Grid
   */
  private buildAndSetColumns(): void {
    console.log("🏗️ buildAndSetColumns() - Construction des colonnes");

    const response = this.current_list_views?.filter((res: any) => {
      return res.name === this.current_sections;
    });

    console.log("🔍 Recherche de la section:", this.current_sections);
    console.log("📋 Résultat de la recherche:", response);

    if (response && response.length > 0) {
      console.log(
        "✅ Section trouvée, champs disponibles:",
        response[0].fields
      );

      this.transformField(response[0].fields);

      const fieldsHash = JSON.stringify(
        response[0].fields.map((f: any) => f.name)
      );
      const cacheKey = `columns_${this.current_sections}_${fieldsHash}_${this.ishowFilter}`;
      let columnDef = this.dataCache.get(cacheKey);

      if (!columnDef) {
        console.log("🔨 Construction des nouvelles colonnes");
        const builtColumns = this.buildColumns(response[0].fields);
        columnDef = this.dataHeaderAgrdid.concat(builtColumns);
        this.dataCache.set(cacheKey, columnDef);
      } else {
        console.log("⚡ Utilisation du cache pour les colonnes");
      }

      this.columnDefAgrid = columnDef;

      // Initialiser les définitions de champs pour le système de filtres
      this.initializeFieldDefinitions();

      this.defaultColDef = {
        ...this.defaultColDef,
        floatingFilter: this.ishowFilter,
        suppressLoadingOverlay: true,
        suppressNoRowsOverlay: true,
      };

      console.log("🔍 État des filtres:", {
        ishowFilter: this.ishowFilter,
        floatingFilter: this.defaultColDef.floatingFilter,
        filter: this.defaultColDef.filter
      });

      console.log("🎯 Colonnes configurées:", {
        columnsCount: this.columnDefAgrid.length,
        defaultColDef: this.defaultColDef,
      });

      this.cdr.markForCheck();
    } else {
      console.log("❌ Aucune section correspondante trouvée");
    }
  }
  /**
   * Pre-processing optimisé des données pour ag-Grid
   */
  private preprocessDataForAgGrid(data: any[]): any[] {
    return data.map((item, index) => {
      if (!item.id) {
        item.id = `row_${index}_${Date.now()}`;
      }

      const processedItem = { ...item };

      Object.keys(processedItem).forEach((key) => {
        const value = processedItem[key];

        // Traitement des dates
        if (value && typeof value === "string") {
          if (value.match(/^\d{4}-\d{2}-\d{2}/) && value.includes("T")) {
            processedItem[`${key}_formatted`] = this.convertDate(value);
          }
        }

        // Traitement des références (objets avec propriété name)
        if (value && typeof value === "object" && !Array.isArray(value)) {
          // Créer une version formatée pour l'affichage
          const referenceDisplayValue =
            this.extractReferenceDisplayValue(value);
          if (referenceDisplayValue !== null) {
            processedItem[`${key}_display`] = referenceDisplayValue;

            // Log pour debug
            // console.log(`🔗 Référence détectée pour ${key}:`, {
            //   original: value,
            //   display: referenceDisplayValue,
            // });
          }
        }
      });

      return processedItem;
    });
  }

  /**
   * Extrait la valeur d'affichage d'un objet de référence
   */
  private extractReferenceDisplayValue(referenceObject: any): string | null {
    if (!referenceObject || typeof referenceObject !== "object") {
      return null;
    }

    // Ordre de priorité pour les propriétés de nom
    const nameProperties = [
      "name",
      "Name",
      "libelle",
      "label",
      "displayName",
      "display_name",
      "title",
      "nom",
    ];

    for (const prop of nameProperties) {
      if (referenceObject[prop] && typeof referenceObject[prop] === "string") {
        return referenceObject[prop];
      }
    }

    // Si aucune propriété de nom n'est trouvée, prendre la première propriété string
    const stringKeys = Object.keys(referenceObject).filter(
      (key) =>
        typeof referenceObject[key] === "string" &&
        referenceObject[key].trim() !== ""
    );

    if (stringKeys.length > 0) {
      return referenceObject[stringKeys[0]];
    }

    return null;
  }

  /**
   * Renderer optimisé pour les champs de type référence
   * Chaque colonne reference a son propre renderer (pas de cache partagé)
   * pour conserver le module cible dans la closure
   */
  private getOptimizedReferenceRenderer(response: any): any {
    const refModule = response.reference || response.module || '';

    return (params: any) => {
      const rawValue = params?.value;
      if (!rawValue) return "";

      // Déterminer le texte à afficher
      let displayText = '';
      const displayField = `${params.colDef.field}_display`;

      if (params.data && params.data[displayField]) {
        displayText = params.data[displayField];
      } else if (rawValue && typeof rawValue === 'object') {
        displayText = this.extractReferenceDisplayValue(rawValue) || '';
      } else {
        displayText = String(rawValue);
      }

      if (!displayText) return "";

      // Si la valeur brute est un objet avec id/uuid, rendre cliquable
      if (rawValue && typeof rawValue === 'object' && (rawValue.id || rawValue.uuid)) {
        return `<span class="reference-cell-link"
                  data-ref-module="${refModule}"
                  title="Voir le détail de ${displayText}">
                  ${displayText}
                </span>`;
      }

      // Affichage simple (valeur non-navigable)
      return `<span>${displayText}</span>`;
    };
  }
  private resetLoadingStates(): void {
    this.ishowFilter = false;
    this.iconEnabled = false;

    // Ne pas réinitialiser les permissions si les CTA sont déjà chargés
    if (!this.ctas || this.ctas.length === 0) {
      this.isPermExec = false;
      this.isPermDel = false;
      this.isPermCreate = false;
      this.isPermUpdate = false;
      this.isPermReporting = false;
      this.isPermRefresh = false;
    }

    this.generatedBadges = [];
  }

  /**
   * Force le reset des états de chargement - méthode publique
   */
  public forceResetLoadingStates(): void {
    console.log("🔧 Force reset des loading states");
    this.isLoading = false;
    this.isLoadingDetails = false;
    this.lastLoadDataCall = 0;
    this.cdr.markForCheck();
  }

  public permissionCta(cta: any) {
    let perm = permissionCta(this.ctas, cta);
    switch (cta) {
      case "delete":
        this.isPermDel = perm;
        break;
      case "update":
        this.isPermUpdate = perm;
        break;
      case "report":
        this.isPermReporting = perm;
        break;
      case "create":
        this.isPermCreate = perm;
        break;
      case "refresh":
        this.isPermRefresh = perm;
        break;
      case "execute":
        this.isPermExec = perm;
        break;
    }
  }

  public ctaName(cta: any) {
    return ctaName(this.ctas, cta);
  }

  private checkParams() {
    if (!this.current_sections) {
      return;
    }

    this.event.current_section$
      .pipe(takeUntil(this.destroy$))
      .subscribe((section) => {
        if (this.current_sections === section) {
          return;
        }

        this.current_sections = section;
        this.dataSource.filter = "";

        this.buildAndSetColumns();

        this.current_constraints = this.checkConstraint();

        if (Object.keys(this.current_constraints)) {
          const response = Object.keys(this.current_constraints).map((res) => {
            return this.current_constraints[res];
          });

          let orederField = response.reduce(
            (orderedAcum, elem) => [
              ...orderedAcum,
              ...(Array.isArray(elem) ? elem : [elem]),
            ],
            []
          );

          let getConditionField = orederField.map((res: any) => {
            return {
              key: res.fieldname,
              operator: this.getOperator(res.operator),
              value: res.value,
            };
          });

          if (this.dataSource.data.length > 0) {
            // Logique de filtrage si nécessaire
          }
        }

        this.cdr.markForCheck();
      });
  }

  public getDataObject() {
    this.selection.changed.pipe(takeUntil(this.destroy$)).subscribe((res) => {
      this.listSelected = res.source.selected;
      res.source.selected.length > 0
        ? (this.iconEnabled = true)
        : (this.iconEnabled = false);
      this.cdr.markForCheck();
    });
  }

  public getOperator(data: string) {
    switch (data) {
      case "e":
        return "===";
      case "n":
        return "!==";
      case "s":
        return "!==";
      case "ew":
        return "!==";
      case "c":
        return "toLowerCase().indexOf(value.toLowerCase()) !== -1";
      case "y":
        return "=== ''";
      case "ny":
        return "!== ''";
      case "l":
        return "<";
      case "m":
        return "<=";
      case "g":
        return ">";
      case "G":
        return ">=";
      default:
        return "";
    }
  }

  private buildColumns(fields: any[]): any[] {
    return this.filterListViews(fields).map((response: any, i: any) => {
      const columnConfig: any = {
        field: response.name,
        headerName: response.displayName || response.name,
        width: response.minWidth || 150,
        pinned: i === 0 ? "left" : null,
        suppressMenu: true,
        suppressMovable: false, // Permettre le déplacement des colonnes
        enableCellChangeFlash: false,
        filter: this.getOptimizedFilter(response.type),
        floatingFilter: this.ishowFilter,
        editable: this.isColumnEditable(response.type),
        // Empêcher les retours à la ligne et ajouter ellipsis
        wrapText: false,
        autoHeight: false,
        // Ajouter tooltip pour toutes les cellules
        tooltipValueGetter: (params: any) => {
          if (params.value === null || params.value === undefined) return '';
          if (typeof params.value === 'object') {
            // Pour les objets référence, essayer d'extraire le nom
            if (params.value.name) return params.value.name;
            if (params.value.displayName) return params.value.displayName;
            return JSON.stringify(params.value);
          }
          return String(params.value);
        },
        // Forcer les styles ellipsis sur chaque colonne
        cellStyle: (params: any) => {
          return {
            'white-space': 'nowrap',
            'overflow': 'hidden', 
            'text-overflow': 'ellipsis',
            'max-width': '100%'
          };
        },
        suppressKeyboardEvent: (params: any) => {
          return params.event.key === "Tab";
        },
      };
      if (response.name === "Description") {
        columnConfig.minWidth = 400;
        columnConfig.maxWidth = 400;
        columnConfig.cellRenderer = this.getOptimizedDescriptionRenderer();
        columnConfig.editable = false;
        // Override le style pour Description pour permettre le wrap
        columnConfig.cellStyle = (params: any) => {
          return {
            'white-space': 'normal',
            'overflow': 'hidden', 
            'text-overflow': 'ellipsis',
            'max-height': '50px',
            'line-height': '1.2'
          };
        };
      } else if (response.type === "reference") {
        // Pour les champs de type reference, utiliser un renderer spécialisé
        columnConfig.cellRenderer = this.getOptimizedReferenceRenderer(response);
        columnConfig.editable = false;
        // Combiner les styles de base avec les styles spécifiques
        columnConfig.cellStyle = (params: any) => {
          return {
            'white-space': 'nowrap',
            'overflow': 'hidden', 
            'text-overflow': 'ellipsis',
            'max-width': '100%',
            "text-align": "left",
            "padding-left": "10px",
            color: "#2563eb"
          };
        };
      } else if (response.type === "picklist") {
        columnConfig.cellRenderer = this.getOptimizedPicklistRenderer(response);
        columnConfig.cellStyle = (params: any) => {
          return {
            'white-space': 'nowrap',
            'overflow': 'hidden', 
            'text-overflow': 'ellipsis',
            'max-width': '100%',
            display: "flex",
            "justify-content": "center",
            "align-items": "center"
          };
        };
      } else {
        columnConfig.valueFormatter = this.getOptimizedValueFormatter(response.type);
      }

      // Filename column: render as download link for document modules
      const fieldNameLower = (response.name || '').toLowerCase();
      if (fieldNameLower === 'filename' || fieldNameLower === 'nom du fichier') {
        console.log('📥 Filename field detected:', { fieldName: response.name, moduleName: this.moduleName });
      }
      if (
        (fieldNameLower === 'filename' || fieldNameLower === 'nom du fichier') &&
        this.moduleName?.toLowerCase() === 'documents'
      ) {
        columnConfig.cellRenderer = (params: any) => {
          if (!params.value) return '';
          const container = document.createElement('span');
          container.classList.add('download-file-link');
          container.setAttribute('data-uuid', params.data?.uuid || '');
          container.style.cssText = 'color:#2563eb;cursor:pointer;display:inline-flex;align-items:center;gap:4px;';
          container.innerHTML =
            '<span class="material-icons" style="font-size:16px;">download</span>' +
            '<span style="text-decoration:underline;">' + this.escapeHtml(params.value) + '</span>';
          return container;
        };
        columnConfig.editable = false;
      }

      return columnConfig;
    });
  }

  /**
   * Escape HTML characters to prevent XSS in cell renderers
   */
  private escapeHtml(text: string): string {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
  }

  private getOptimizedFilter(type: string): string {
    switch (type) {
      case "timestamp":
      case "datetime":
      case "date":
        return "agDateColumnFilter";
      case "currency":
      case "integer":
      case "double":
        return "agNumberColumnFilter";
      case "picklist":
      case "boolean":
        return "agSetColumnFilter";
      case "string":
      case "text":
      default:
        return "agTextColumnFilter";
    }
  }

  private isColumnEditable(type: string): boolean {
    return type !== "reference" && type !== "datetime" && type !== "date";
  }

  private getOptimizedCellStyle(response: any): any {
    const cacheKey = `cellStyle_${response.type}_${response.name}`;
    let style = this.cellRendererCache.get(cacheKey);

    if (!style) {
      if (
        response.type === "currency" ||
        response.type === "integer" ||
        response.type === "double" ||
        response.type === "date" ||
        response.type === "datetime" ||
        response.name === "Numero de statut"
      ) {
        style = {
          "text-align": "right",
          "padding-right": "15px",
          // "border-right": "1px solid #e2e8f0",
        };
      } else if (response.type === "picklist") {
        style = {
          display: "flex",
          "justify-content": "center",
          "align-items": "center",
        };
      } else {
        style = {
          "text-align": "left",
          "padding-left": "10px",
        };
      }
      this.cellRendererCache.set(cacheKey, style);
    }

    return style;
  }

  private getOptimizedValueFormatter(type: string): any {
    const cacheKey = `valueFormatter_${type}`;
    let formatter = this.valueFormatterCache.get(cacheKey);

    if (!formatter) {
      switch (type) {
        case "currency":
          formatter = (params: any) => {
            if (params.value != null) {
              return (
                this.currencyPipe.transform(
                  params.value,
                  "EUR",
                  "symbol",
                  "1.2-2"
                ) || ""
              );
            }
            return "";
          };
          break;
        case "date":
          formatter = (params: any) => {
            if (params.value) {
              return this.datePipe.transform(params.value, "dd/MM/yyyy") || "";
            }
            return "";
          };
          break;
        case "datetime":
          formatter = (params: any) => {
            if (params.value) {
              return (
                this.datePipe.transform(params.value, "dd/MM/yyyy HH:mm") || ""
              );
            }
            return "";
          };
          break;
        case "integer":
        case "double":
          formatter = (params: any) => {
            if (params.value != null) {
              return this.decimalPipe.transform(params.value, "1.0-2") || "";
            }
            return "";
          };
          break;
        default:
          formatter = (params: any) => params.value || "";
      }
      this.valueFormatterCache.set(cacheKey, formatter);
    }

    return formatter;
  }

  private getOptimizedDescriptionRenderer(): any {
    const cacheKey = "descriptionRenderer";
    let renderer = this.cellRendererCache.get(cacheKey);

    if (!renderer) {
      renderer = (params: any) => {
        const value = params.value || "";
        return value.length > 100
          ? `<span title="${value}">${value.substring(0, 100)}...</span>`
          : value;
      };
      this.cellRendererCache.set(cacheKey, renderer);
    }

    return renderer;
  }

  private getOptimizedPicklistRenderer(response: any): any {
    const cacheKey = `picklistRenderer_${response.name}`;
    let renderer = this.cellRendererCache.get(cacheKey);

    // if (!renderer) {
    //   renderer = (params: any) => {
    //     const value = params.value;
    //     if (!value) return "";

    //     return `<span class="picklist-value">${value}</span>`;
    //   };
    //   this.cellRendererCache.set(cacheKey, renderer);
    // }

    if (!renderer) {
      renderer = (params: any) => {
        const value = params?.value?.name ? params?.value?.name : params?.value;
        if (!value) return "";
        const backgroundColor = this.getPicklistBackgroundColor(
          response,
          value
        );
        const textColor = this.getPicklistTextColor(response, value);

        return `<span class="picklist-value" style="background-color: ${backgroundColor}; color: ${textColor}; padding: 5px 12px; border-radius: 15px;" title="${value}">${value}</span>`;
      };
      this.cellRendererCache.set(cacheKey, renderer);
    }
    return renderer;
  }

  /**
   * Formateur optimisé pour les champs de type référence
   */
  private getOptimizedReferenceValueFormatter(): any {
    const cacheKey = "referenceValueFormatter";
    let formatter = this.valueFormatterCache.get(cacheKey);

    if (!formatter) {
      formatter = (params: any) => {
        const value = params.value;

        // Si la valeur est null ou undefined
        if (!value) {
          return "";
        }

        // Si c'est un objet avec une propriété 'name'
        if (typeof value === "object" && value.name) {
          return value.name;
        }

        // Si c'est un objet avec une propriété 'Name' (majuscule)
        if (typeof value === "object" && value.Name) {
          return value.Name;
        }

        // Si c'est un objet avec une propriété 'libelle'
        if (typeof value === "object" && value.libelle) {
          return value.libelle;
        }

        // Si c'est un objet avec une propriété 'label'
        if (typeof value === "object" && value.label) {
          return value.label;
        }

        // Si c'est déjà une chaîne, la retourner directement
        if (typeof value === "string") {
          return value;
        }

        // Si c'est un objet mais sans propriété connue, essayer de trouver une propriété de nom
        if (typeof value === "object") {
          // Chercher une propriété qui pourrait contenir le nom d'affichage
          const possibleNameKeys = [
            "displayName",
            "display_name",
            "title",
            "nom",
          ];
          for (const key of possibleNameKeys) {
            if (value[key]) {
              return value[key];
            }
          }

          // En dernier recours, prendre la première propriété string non-null
          const stringKeys = Object.keys(value).filter(
            (key) => typeof value[key] === "string" && value[key].trim() !== ""
          );
          if (stringKeys.length > 0) {
            return value[stringKeys[0]];
          }
        }

        // Fallback: convertir en string
        return String(value);
      };

      this.valueFormatterCache.set(cacheKey, formatter);
    }

    return formatter;
  }

  private filterListViews(fields: any[]): any[] {
    return fields.filter((field) => field && field.name && field.displayName);
  }

  private convertDate(dateString: string): string {
    try {
      const date = new Date(dateString);
      return this.datePipe.transform(date, "dd/MM/yyyy") || dateString;
    } catch (error) {
      return dateString;
    }
  }
  public transformField(data: any) {
    console.log("🔧 transformField() - Transformation des champs:", data);

    const response =
      data &&
      data.length > 0 &&
      data.map((res: any) => {
        if (!res.columnname) return res.name;
        return res.name;
      });

    console.log("📋 Colonnes extraites:", response);

    if (response) {
      this.displayedColumnsCsv = this.checkUndefined(response);
      this.displayedColumns = this.checkUndefined(["select"].concat(response));
      this.widthTable = 200 * this.displayedColumns.length + 68;
      this.current_condition = response.reduce(
        (o: any, key: any) => Object.assign(o, { [key]: "" }),
        {}
      );

      console.log("✅ Colonnes configurées:", {
        displayedColumns: this.displayedColumns,
        displayedColumnsCsv: this.displayedColumnsCsv,
        widthTable: this.widthTable,
      });
    } else {
      console.log(
        "⚠️ Aucune colonne à traiter - utilisation des colonnes par défaut"
      );
      // Colonnes par défaut si aucune donnée
      this.displayedColumns = ["select"];
      this.displayedColumnsCsv = [];
      this.widthTable = 200;
    }
  }

  public checkUndefined(arr: any) {
    var filtered = arr?.filter((x: any) => {
      return x !== undefined;
    });
    return filtered;
  }

  public removeColumnProjectName(data: []) {
    let response = data.filter((res) => {
      return res !== "Numero de Projets";
    });
    return response;
  }

  public isAllSelected() {
    const numSelected = this.selection.selected.length;
    const numRows = this.dataSource.data.length;
    return numSelected === numRows;
  }

  public masterToggle() {
    this.isAllSelected()
      ? this.selection.clear()
      : this.dataSource.data.forEach((row) => {
          this.selection.select(row);
        });
  }

  public checkboxLabel(row?: any): string {
    return !row
      ? `${this.isAllSelected() ? "select" : "deselect"} all`
      : `${this.selection.isSelected(row) ? "deselect" : "select"} row ${
          row.position + 1
        }`;
  }

  public announceSortChange(sortState: Sort) {
    if (sortState.direction) {
      this._liveAnnouncer.announce(`Sorted ${sortState.direction}ending`);
    } else {
      this._liveAnnouncer.announce("Sorting cleared");
    }
  }


  /**
   * Méthode pour basculer l'affichage des filtres
   */
  public toggleFilters(): void {
    console.log('🔍 Basculement des filtres, état actuel:', this.ishowFilter);
    
    if (!this.iconEnabled) {
      const previousState = this.ishowFilter;
      this.ishowFilter = !this.ishowFilter;
      
      console.log('🔍 Nouvel état des filtres:', this.ishowFilter);
      
      if (previousState !== this.ishowFilter) {
        this.buildAndSetColumns();
        console.log('🔍 Colonnes reconstruites avec filtres:', this.ishowFilter);
      }
      
      // Mettre à jour le compteur de filtres actifs
      if (this.gridApi) {
        setTimeout(() => {
          this.updateActiveFiltersCount();
        }, 100);
      }
    }
  }

  /**
   * Méthode pour la recherche rapide
   */
  public onQuickSearch(event: any): void {
    const searchValue = event.target?.value || '';
    this.searchQuery = searchValue;
    
    if (this.gridApi) {
      this.gridApi.setQuickFilter(searchValue);
    }
  }

  // Les méthodes toggleFilters() et onQuickSearch() sont déjà définies plus haut

  public getBadges() {
    console.log("🏷️ getBadges() - Début génération des badges:", {
      badges: this.badges,
      listViewOne: this.listViewOne?.length,
      hasData: !!(this.badges && this.listViewOne),
    });

    if (this.badges && this.listViewOne) {
      this.generatedBadges = this.badges.map((badge: any, index: number) => {
        const calculatedValue = this.calculateBadgeValue(badge, this.listViewOne);
        console.log(`🏷️ Badge ${index + 1}:`, {
          title: badge.title,
          icon: badge.icon,
          type: badge.type,
          field: badge.field,
          value: badge.value,
          condition: badge.condition,
          calculatedValue: calculatedValue,
          rawBadge: badge,
        });
        return {
          title: badge.title,
          icon: badge.icon,
          result: calculatedValue,
        };
      });
      console.log("✅ Badges générés:", this.generatedBadges);
    } else {
      console.warn("⚠️ Impossible de générer les badges:", {
        hasBadges: !!this.badges,
        hasData: !!this.listViewOne,
        badgesLength: this.badges?.length,
        dataLength: this.listViewOne?.length,
      });
    }
    
    this.cdr.markForCheck();
  }

  private calculateBadgeValue(badge: any, data: any[]): number {
    if (!data || !Array.isArray(data) || data.length === 0) {
      return 0;
    }

    // Si le badge a une propriété 'field' ou 'column', filtrer selon ce champ
    if (badge.field) {
      return data.filter((item) => {
        const fieldValue = item[badge.field];

        // Si le badge a une valeur attendue, compter les éléments qui correspondent
        if (badge.value !== undefined) {
          return fieldValue === badge.value;
        }

        // Sinon, compter les éléments qui ont une valeur non vide pour ce champ
        return (
          fieldValue !== null && fieldValue !== undefined && fieldValue !== ""
        );
      }).length;
    }

    // Si le badge a une condition ou critère spécifique
    if (badge.condition) {
      return data.filter((item) => {
        try {
          // Évaluer la condition si c'est une fonction
          if (typeof badge.condition === "function") {
            return badge.condition(item);
          }

          // Si c'est un objet avec des critères
          if (typeof badge.condition === "object") {
            return Object.keys(badge.condition).every(
              (key) => item[key] === badge.condition[key]
            );
          }
        } catch (error) {
          console.warn(
            "Erreur lors de l'évaluation de la condition du badge:",
            error
          );
          return false;
        }
        return false;
      }).length;
    }

    // Si le badge a un type spécifique pour les calculs
    switch (badge.type) {
      case "count":
        return data.length;

      case "sum":
        if (badge.sumField) {
          return data.reduce((sum, item) => {
            const value = parseFloat(item[badge.sumField]) || 0;
            return sum + value;
          }, 0);
        }
        return data.length;

      case "average":
        if (badge.avgField) {
          const validItems = data.filter(
            (item) =>
              item[badge.avgField] !== null &&
              item[badge.avgField] !== undefined &&
              !isNaN(parseFloat(item[badge.avgField]))
          );
          if (validItems.length === 0) return 0;

          const sum = validItems.reduce(
            (sum, item) => sum + parseFloat(item[badge.avgField]),
            0
          );
          return Math.round((sum / validItems.length) * 100) / 100; // Arrondi à 2 décimales
        }
        return 0;

      case "percentage":
        if (badge.numeratorField && badge.denominatorField) {
          const numerator = data.filter(
            (item) => item[badge.numeratorField]
          ).length;
          const denominator = data.filter(
            (item) => item[badge.denominatorField]
          ).length;
          return denominator > 0
            ? Math.round((numerator / denominator) * 100)
            : 0;
        }
        return 0;

      default:
        // Par défaut, retourner le nombre total d'éléments
        return data.length;
    }
  }

  private checkConstraint() {
    // Retourner un objet vide par défaut
    return {};
  }

  private setupFilter() {
    return (data: any, filter: string) => {
      return true; // Logique de filtrage simplifiée
    };
  }

  /**
   * Toggle l'affichage des filtres flottants AG-Grid
   */
  public showFilter(): void {
    // Ouvrir le panneau de filtres avancés
    this.showFilterPanel = !this.showFilterPanel;
  }

  /**
   * Gestion des changements de filtres AG-Grid
   */
  onFilterChanged(params: any): void {
    // Ignorer les événements de filtres si on est en cours de restauration
    if (this.isRestoringFilters) {
      console.log('🔍 Filtres ag-Grid changés (ignoré - restauration en cours):', params);
      return;
    }

    console.log('🔍 Filtres ag-Grid changés:', params);

    // Mettre à jour le compteur de filtres actifs
    this.updateActiveFiltersCount();

    // Convertir les filtres ag-Grid en format API
    if (this.agGrid && this.agGrid.api) {
      const filterModel = this.agGrid.api.getFilterModel();
      const convertedFilters = this.convertAgGridFilters(filterModel);

      console.log('📊 Filtres convertis:', {
        original: filterModel,
        converted: convertedFilters
      });

      // Sauvegarder les filtres dans les contraintes du localStorage
      this.saveFiltersToLocalStorage(convertedFilters);

      // Recharger les données avec les nouveaux filtres
      this.loadPagedData();
    }
  }

  /**
   * Convertit les filtres ag-Grid au format attendu par l'API backend
   */
  private convertAgGridFilters(filterModel: any): Record<string, any> {
    const filters: Record<string, any> = {};

    if (!filterModel) return filters;

    Object.keys(filterModel).forEach(field => {
      const filter = filterModel[field];

      // Tous les types de filtres → valeur simple (backend fait LIKE %value%)
      if (filter.filterType === 'text') {
        // 'contains', 'equals', 'startsWith' → même traitement
        filters[field] = filter.filter;

      } else if (filter.filterType === 'number') {
        // 'equals', 'greaterThan', 'lessThan' → même traitement
        filters[field] = filter.filter;

      } else if (filter.filterType === 'date') {
        // Toujours la première date
        filters[field] = this.formatDateForApi(filter.dateFrom);

      } else if (filter.filterType === 'set') {
        // Multi-sélection → première valeur
        if (filter.values && filter.values.length > 0) {
          filters[field] = filter.values[0];
        }

      } else if (typeof filter === 'string') {
        filters[field] = filter;
      }
    });

    console.log('🔄 Filtres AG-Grid → API (format simple):', filters);
    return filters;
  }

  /**
   * Formate une date pour l'API
   */
  private formatDateForApi(date: Date | string): string {
    if (!date) return '';
    const d = new Date(date);
    return d.toISOString().split('T')[0]; // YYYY-MM-DD
  }

  /**
   * Met à jour le compteur de filtres actifs
   */
  private updateActiveFiltersCount(): void {
    if (this.agGrid && this.agGrid.api) {
      const filterModel = this.agGrid.api.getFilterModel();
      this.activeFiltersCount = Object.keys(filterModel || {}).length;
      console.log('🔢 Filtres actifs:', this.activeFiltersCount);
    } else {
      this.activeFiltersCount = 0;
    }
  }

  /**
   * Sauvegarde les filtres ag-Grid actuels
   */
  private saveCurrentFilters(): any {
    if (this.agGrid && this.agGrid.api) {
      try {
        const filterModel = this.agGrid.api.getFilterModel();
        // Use columnApi.getColumnState() for AG-Grid v26
        const columnState = this.agGrid.columnApi?.getColumnState() || [];
        const sortModel = columnState
          .filter((col: any) => col.sort != null)
          .map((col: any) => ({
            colId: col.colId,
            sort: col.sort,
            sortIndex: col.sortIndex
          }));
        return {
          filters: filterModel,
          sorting: sortModel,
          timestamp: Date.now(),
        };
      } catch (error) {
        console.warn("⚠️ Erreur lors de la sauvegarde des filtres:", error);
        return null;
      }
    }
    return null;
  }

  /**
   * Restaure les filtres ag-Grid sauvegardés
   */
  private restoreFilters(savedState: any): void {
    if (!savedState || !this.agGrid || !this.agGrid.api) {
      return;
    }

    try {
      this.isRestoringFilters = true;

      // Restaurer les filtres
      if (savedState.filters) {
        this.agGrid.api.setFilterModel(savedState.filters);
      }

      // Restaurer le tri en utilisant columnApi.applyColumnState() au lieu de setSortModel()
      if (savedState.sorting && savedState.sorting.length > 0 && this.agGrid.columnApi) {
        const columnState = savedState.sorting.map((sort: any) => ({
          colId: sort.colId,
          sort: sort.sort,
          sortIndex: sort.sortIndex
        }));
        this.agGrid.columnApi.applyColumnState({
          state: columnState,
          defaultState: { sort: null }
        });
      }

      // Forcer la mise à jour
      this.agGrid.api.onFilterChanged();

      console.log("✅ Filtres et tri restaurés:", {
        filters: savedState.filters,
        sorting: savedState.sorting,
      });

      // Délai pour éviter les boucles infinies
      setTimeout(() => {
        this.isRestoringFilters = false;
      }, 100);

    } catch (error) {
      console.warn("⚠️ Erreur lors de la restauration des filtres:", error);
      this.isRestoringFilters = false;
    }
  }

  // Méthodes ag-Grid events (mise à jour avec la nouvelle logique)

  onCellValueChanged(params: any) {
    // Logique de modification de cellule
  }
  onCellClicked(params: any) {
    // Éviter l'ouverture de la vue détail si c'est un clic sur une checkbox
    if (params.colDef && params.colDef.checkboxSelection) {
      return;
    }

    // Vérifier si le clic est sur un lien de téléchargement de fichier
    const target = params.event?.target as HTMLElement;
    const fileLink = target?.closest('.download-file-link') as HTMLElement;

    if (fileLink) {
      const uuid = fileLink.getAttribute('data-uuid');
      const filename = params.value;
      if (uuid && filename) {
        this.documentService.downloadByUuid(uuid, filename);
      }
      return; // Ne pas ouvrir le détail de la ligne
    }

    // Vérifier si le clic est sur un lien de référence (prioritaire sur le clic ligne)
    const refLink = target?.closest('.reference-cell-link') as HTMLElement;

    if (refLink) {
      const refModule = refLink.getAttribute('data-ref-module');
      const rawValue = params.value;

      if (refModule && rawValue && typeof rawValue === 'object' && (rawValue.id || rawValue.uuid)) {
        console.log("🔗 Clic sur référence:", { module: refModule, value: rawValue });
        this.openReferenceDetail(rawValue, refModule);
        return; // Ne pas ouvrir le détail de la ligne
      }
    }

    // Comportement par défaut : ouvrir le détail de la ligne
    const clickedData = params.data;
    if (clickedData) {
      this.vueDetails(clickedData);
    }
  }
  /**
   * Ouvre la vue détail pour l'enregistrement sélectionné (méthode compatible avec l'ancienne version)
   */
  public vueDetails(data: any, i?: any): void {
    if (!this.isLoadingDetails) {
      this.current_click = i || data.id || data.projetsid || "";

      if (this.dialog.openDialogs.length === 0) {
        // Incrémenter le niveau AVANT d'ouvrir le dialog
        this.contextuel.incrementLevel();
        const newLevel = this.contextuel.getCurrentLevel();
        console.log('📊 list-view-one incrémente niveau:', newLevel);

        // Calculer la config cascade
        const cascadeConfig = this.getCascadeDialogConfig(newLevel);

        // Ajouter le contexte parent comme dans l'ancienne version
        data["contextParent"] = this.moduleName;

        const dialogRef = this.dialog.open(VueDetailComponent, {
          data: data,
          ...cascadeConfig
        });

        dialogRef.afterClosed().subscribe((result) => {
          // Décrémenter le niveau après fermeture du dialog
          this.contextuel.decrementLevel();
          console.log('📊 list-view-one décrémente niveau:', this.contextuel.getCurrentLevel());

          this.current_click = "";
          this.document.body.classList.remove("pop-element");

          // Si des modifications ont été faites, recharger les données
          if (result && result.action === "updated") {
            console.log(
              "📝 Enregistrement mis à jour, rechargement des données..."
            );
            this.refreshList();
          }
        });
      }
    }
  }

  /**
   * Ouvre la vue détail d'un élément référencé (navigation depuis un champ reference)
   */
  private openReferenceDetail(refData: any, moduleName: string): void {
    if (this.isLoadingDetails || this.dialog.openDialogs.length > 0) return;

    this.contextuel.incrementLevel();
    const newLevel = this.contextuel.getCurrentLevel();
    const cascadeConfig = this.getCascadeDialogConfig(newLevel);

    const data = {
      ...refData,
      contextParent: moduleName,
      from: moduleName
    };

    const dialogRef = this.dialog.open(VueDetailComponent, {
      data: data,
      ...cascadeConfig
    });

    dialogRef.afterClosed().subscribe((result) => {
      this.contextuel.decrementLevel();
      this.current_click = "";
      this.document.body.classList.remove("pop-element");

      if (result && result.action === "updated") {
        this.refreshList();
      }
    });
  }

  /**
   * Calcule la configuration du dialog pour l'effet cascade
   */
  private getCascadeDialogConfig(currentLevel: number): any {
    const baseWidth = 69;
    const widthReduction = 3;

    const maxWidth = `${baseWidth - (widthReduction * currentLevel)}vw`;
    const position = { right: '0px' }; // Toujours fixé à droite

    console.log(`🎨 Cascade niveau ${currentLevel}: maxWidth=${maxWidth}`);

    return {
      maxWidth,
      position,
      panelClass: ["animate__animated", "animate__slideInRight", `cascade-level-${currentLevel}`]
    };
  }

  /**
   * Ouvre la vue détail pour l'enregistrement sélectionné
   */
  private openDetailView(data: any): void {
    try {
      // Ajouter la classe pour gérer l'overlay
      this.document.body.classList.add("pop-element");

      const dialogRef = this.dialog.open(ProjectsComponent, {
        data: {
          ...data, // Inclure toutes les données de l'élément sélectionné
          context: { from: this.moduleName }, // Utiliser 'context' au lieu de 'data'
        },
        position: { right: "0" },
        panelClass: ["animate__animated", "animate__slideInRight"],
        maxWidth: "69vw",
      });

      dialogRef.afterClosed().subscribe((result) => {
        // Retirer la classe d'overlay
        this.document.body.classList.remove("pop-element");

        if (result && result.action === "updated") {
          // Recharger les données si l'enregistrement a été modifié
          console.log(
            "📝 Enregistrement mis à jour, rechargement des données..."
          );
          this.refreshList();
        }

        // Réinitialiser la sélection visuelle
        this.current_click = "";
        this.cdr.markForCheck();
      });

      console.log("📋 Vue détail ouverte pour:", data);
    } catch (error) {
      console.error("❌ Erreur lors de l'ouverture de la vue détail:", error);
      this.toast.showError("Impossible d'ouvrir la vue détail");
    }
  }
  onSelectionChanged(params: any) {
    console.log('🔍 Debug onSelectionChanged() appelé:', { params, agGridApi: !!this.agGrid?.api });

    try {
      // Utiliser la même logique que l'ancienne version
      const selectedNodes = this.agGrid?.api?.getSelectedNodes() || params?.api?.getSelectedNodes() || [];
      console.log('📋 Selected nodes:', selectedNodes.length);

      // Récupérer les données des nœuds sélectionnés
      this.selectedRecords = selectedNodes.map((node: any) => node.data);
      this.listSelected = this.selectedRecords; // Synchroniser avec listSelected pour le template
      this.selectedCount = this.selectedRecords.length;

      // Mettre à jour l'état des boutons d'action
      this.iconEnabled = this.selectedCount > 0;

      console.log('✅ Sélection mise à jour:', {
        selectedCount: this.selectedCount,
        selectedRecords: this.selectedRecords.length,
        iconEnabled: this.iconEnabled,
        listSelected: this.listSelected.length
      });
    } catch (error) {
      console.error('❌ Erreur dans onSelectionChanged:', error);
    }

    console.log("🔘 Sélection changée:", {
      selectedCount: this.selectedCount,
      iconEnabled: this.iconEnabled
    });

    // Forcer la détection de changement pour mettre à jour l'interface
    this.cdr.markForCheck();
  }
  // Actions utilisateur
  public delete() {
    if (!this.isPermDel || this.selectedCount === 0) {
      console.warn("⚠️ Suppression non autorisée ou aucun élément sélectionné");
      return;
    }

    console.log(
      "🗑️ Suppression demandée pour:",
      this.selectedCount,
      "éléments"
    );

    const dialogRef = this.dialog.open(ModalDeleteComponent, {
      width: "500px",
      data: {
        records: this.selectedRecords,
        count: this.selectedCount,
        moduleName: this.moduleName,
        message: `Êtes-vous sûr de vouloir supprimer ${this.selectedCount} élément(s) sélectionné(s) ?`,
      },
    });

    dialogRef.afterClosed().subscribe((result) => {
      if (result && result.confirmed) {
        this.performDelete(this.selectedRecords);
      }
    });
  }

  public execute() {
    if (!this.isPermExec || this.selectedCount === 0) {
      console.warn("⚠️ Exécution non autorisée ou aucun élément sélectionné");
      return;
    }

    console.log(
      "🔄 Exécution demandée pour:",
      this.selectedCount,
      "éléments du module:",
      this.moduleName
    );

    const dialogRef = this.dialog.open(ModalExecuteComponent, {
      width: "500px",
      data: {
        records: this.selectedRecords,
        count: this.selectedCount,
        moduleName: this.moduleName,
        message: `Êtes-vous sûr de vouloir exécuter l'opération sur ${this.selectedCount} élément(s) sélectionné(s) ?`,
        requiresConfirmation: true,
      },
    });

    dialogRef.afterClosed().subscribe((result) => {
      console.log("🔄 Modal fermée avec résultat:", result);
      if (result && result.confirmed) {
        console.log("✅ Confirmation reçue, démarrage de l'exécution");
        this.performExecution(this.selectedRecords);
      } else {
        console.log("❌ Exécution annulée ou pas de confirmation");
      }
    });
  }

  public clickEdit() {
    console.log('🔍 Debug clickEdit():', {
      isPermUpdate: this.isPermUpdate,
      selectedCount: this.selectedCount,
      selectedRecords: this.selectedRecords,
      listSelected: this.listSelected,
      selectionModel: this.selection.selected.length,
      iconEnabled: this.iconEnabled
    });

    if (!this.isPermUpdate || this.selectedCount === 0) {
      console.warn(
        "⚠️ Modification non autorisée ou aucun élément sélectionné",
        { isPermUpdate: this.isPermUpdate, selectedCount: this.selectedCount }
      );
      return;
    }

    if (this.selectedCount === 1) {
      // Modification d'un seul élément
      this.openDetailView(this.selectedRecords[0]);
    } else {
      // Modification en masse
      console.log(
        "✏️ Modification en masse demandée pour:",
        this.selectedCount,
        "éléments"
      );

      const dialogRef = this.dialog.open(ProjectsComponent, {
        data: this.selectedRecords, // Passer directement les enregistrements sélectionnés
        position: { right: "0" },
        panelClass: ["animate__animated", "animate__slideInRight"],
        maxWidth: "69vw",
      });

      dialogRef.afterClosed().subscribe((result) => {
        if (result && result.action === "updated") {
          console.log("📝 Modifications en masse effectuées, rechargement...");
          this.refreshList();
        }
      });
    }
  }

  /**
   * Effectue la suppression des enregistrements sélectionnés
   */
  private async performDelete(records: any[]): Promise<void> {
    try {
      console.log("🗑️ Suppression en cours...", records);

      // Extraire les IDs des enregistrements
      const recordIds = records.map((record) => record.id || record.projetsid); // Utiliser la méthode removeProject du service
      const result = await this.projectService
        .removeProject(recordIds as [], this.moduleName)
        .toPromise();

      if (result && result.success) {
        this.toast.showSuccess(
          `${records.length} élément(s) supprimé(s) avec succès`
        );
      } else {
        this.toast.showError("Erreur lors de la suppression");
      }

      // Recharger les données
      this.refreshList();

      // Réinitialiser la sélection
      this.clearSelection();
    } catch (error) {
      console.error("❌ Erreur lors de la suppression:", error);
      this.toast.showError("Erreur lors de la suppression");
    }
  }

  /**
   * Effectue l'exécution des enregistrements sélectionnés
   */
  private async performExecution(records: any[]): Promise<void> {
    try {
      console.log("⚡ Exécution en cours...", records);

      // Construire le payload SPC avec operation_type
      const payload = {
        operation_type: `execute_${this.moduleName}`,
        type: `execute_${this.moduleName}`,
        from: this.moduleName,
        uuids: records.map((record) => record.uuid)
      };

      console.log("📦 Payload SPC:", payload);

      // Utiliser la méthode massExecute du service
      const result = await this.projectService
        .massExecute(payload, this.moduleName)
        .toPromise();

      if (result && result.success) {
        this.toast.showSuccess(
          `Exécution réussie sur ${records.length} élément(s)`
        );
      } else {
        const errorMessage = result?.message || "Erreur lors de l'exécution";
        this.toast.showError(errorMessage);
      }

      // Recharger les données pour refléter les changements (succès ou échec)
      this.refreshList();

      // Réinitialiser la sélection
      this.clearSelection();
    } catch (error) {
      console.error("❌ Erreur lors de l'exécution:", error);
      const errorMessage =
        error instanceof Error ? error.message : "Erreur lors de l'exécution";
      this.toast.showError(errorMessage);

      // Rafraîchir même en cas d'erreur pour synchroniser l'état
      this.refreshList();
      this.clearSelection();
    }
  }

  /**
   * Réinitialise la sélection
   */
  public clearSelection(): void {
    if (this.agGrid && this.agGrid.api) {
      this.agGrid.api.deselectAll();
    }
    this.selectedRecords = [];
    this.selectedCount = 0;
    this.iconEnabled = false;
    this.current_click = "";
    this.cdr.markForCheck();
  }
  public exportCsv() {
    if (this.exportEnabled) {
      this.dialog.open(ModalDataExportComponent, {
        data: {
          currentList: this.current_sections,
          listViews: this.current_list_views,
          records: this.records,
          fileName: this.moduleName,
        },
      });
    }
  }
  public refreshList() {
    console.log(
      "🔄 refreshList() - Début du rechargement avec métadonnées et filtres"
    );

    // Sauvegarder l'état actuel des filtres et du tri
    const savedFiltersState = this.saveCurrentFilters();
    console.log("💾 État ag-Grid sauvegardé:", savedFiltersState);

    // Forcer le rechargement des métadonnées en vidant le cache
    const cacheKey = `${this.moduleName}_listView`;
    this.dataCache.delete(cacheKey);

    // Vider également les caches de données du module pour forcer le rechargement
    const moduleDataKeys = Array.from(this.dataCache.keys()).filter(
      (key) => key.includes(this.moduleName) || key.includes("moduleData")
    );
    moduleDataKeys.forEach((key) => this.dataCache.delete(key));

    // IMPORTANT: Forcer l'appel au service côté serveur en réinitialisant les indicateurs de cache
    localStorage.setItem("__initMetadatas", "true"); // Force le rechargement des métadonnées
    localStorage.setItem("__initDatas", "true"); // Force le rechargement des données
    localStorage.setItem("isFirst", "true"); // Force l'appel API

    // Vider les caches localStorage pour forcer l'appel serveur
    localStorage.removeItem("__lvs"); // Cache des métadonnées de vue
    localStorage.removeItem("__datas"); // Cache des données
    const existingData = localStorage.getItem("__datas");
    if (existingData) {
      const parsedData = JSON.parse(existingData);
      delete parsedData[this.moduleName];
      localStorage.setItem("__datas", JSON.stringify(parsedData));
      // window.location.reload();
    }

    // Réinitialiser les états pour forcer le rechargement complet
    this.isFirstGetData = true;
    this.lastModuleName = "";
    this.lastDomaine = "";

    // Vider les caches de rendu pour forcer la reconstruction des colonnes
    this.cellRendererCache.clear();
    this.valueFormatterCache.clear();

    console.log(
      "🗑️ Tous les caches vidés et indicateurs réinitialisés, rechargement des métadonnées et données..."
    );

    // Recharger les données
    this.loadData()
      .then(() => {
        // Restaurer les filtres après le rechargement avec un délai
        if (savedFiltersState) {
          setTimeout(() => {
            console.log("🔄 Restauration de l'état ag-Grid...");
            this.restoreFilters(savedFiltersState);
          }, 800); // Délai plus long pour s'assurer que ag-Grid est complètement prêt
        }

        console.log("✅ Rechargement terminé avec succès");
      })
      .catch((error) => {
        console.error("❌ Erreur lors du rechargement:", error);
        this.toast.showError("Erreur lors du rechargement des données");
      });
  }
  public generateReporting() {
    if (this.dialog.openDialogs.length === 0) {
      this.dialog.open(ModalGenerateReportingComponent, {
        data: {
          currentList: this.current_sections,
          listViews: this.current_list_views,
          records: this.records,
          fileName: this.moduleName,
        },
      });
    }
  }
  public addProject() {
    // Logique spécifique pour le module PNR
    if (this.moduleName?.toLowerCase() === 'pnr') {
      this.addPNR();
      return;
    }
    
    // Logique générale pour les autres modules
    if (this.dialog.openDialogs.length === 0) {
      const dialogRef = this.dialog.open(ProjectsComponent, {
        data: { context: { from: this.moduleName } },
        position: { right: "0" },
        panelClass: ["animate__animated", "animate__slideInRight"],
        maxWidth: "69vw",
      });

      dialogRef.afterClosed().subscribe((result) => {
        this.document.body.classList.remove("pop-element");
        // Si un nouvel élément a été créé, recharger les données
        if (result && result.action === "created") {
          console.log("📝 Nouvel élément créé, rechargement des données...");
          this.refreshList();
        }
      });
    }
  }

  // TrackBy functions pour optimiser les *ngFor
  public trackByBadge(index: number, badge: any): any {
    return badge.title || index;
  }

  public trackByColumn(index: number, column: string): string {
    return column || index.toString();
  }

  public trackByDisplayedColumn(index: number, column: string): string {
    return column || index.toString();
  }

  /**
   * Debug helper pour vérifier l'état des données
   */
  public debugDataState(): void {
    console.log("=== DEBUG DATA STATE ===");
    console.log("viewStep:", this.viewStep);
    console.log("isLoading:", this.isLoading);
    console.log("isLoadingDetails:", this.isLoadingDetails);
    console.log("rowData length:", this.rowData?.length || 0);
    console.log("columnDefAgrid length:", this.columnDefAgrid?.length || 0);
    console.log("current_sections:", this.current_sections);
    console.log("listViewOne length:", this.listViewOne?.length || 0);
    console.log("===========================");
  }
  /**
   * Force la correction de l'état de vue si les données sont présentes mais viewStep incorrect
   */
  public forceCorrectViewStep(): void {
    // Si on a des données mais viewStep est encore LOADING
    if (
      this.viewStep === ViewStatus.LOADING &&
      !this.isLoading &&
      !this.isLoadingDetails &&
      this.rowData &&
      this.rowData.length > 0
    ) {
      console.log(
        "🔧 CORRECTION FORCÉE: Données présentes mais viewStep incorrect"
      );
      console.log("Avant correction:", {
        viewStep: this.viewStep,
        viewStepString: ViewStatus[this.viewStep],
        rowDataLength: this.rowData.length,
      });

      this.viewStep = ViewStatus.LIST_VIEW_ONE;
      this.exportEnabled = true;

      console.log("Après correction:", {
        viewStep: this.viewStep,
        viewStepString: ViewStatus[this.viewStep],
      });

      this.cdr.markForCheck();
      this.cdr.detectChanges(); // Force la détection immédiate
    }
  }

  /**
   * Retourne le nom de l'enum ViewStatus pour le debug
   */
  public getViewStatusName(status: ViewStatus): string {
    return ViewStatus[status];
  }
  /**
   * Charge les données depuis le cache préchargé lors de la connexion
   */
  private async loadDataFromCache(cachedData: any): Promise<void> {
    console.log("📦 loadDataFromCache() - Utilisation des données préchargées");

    try {
      // Titre
      let title = this.moduleName + " | ESTAIR-CONNECT ";
      this.titleService.setTitle(title);

      // Vérifier si les données de navigation contiennent les configurations de vue préchargées
      const autoLoadFlag = localStorage.getItem("autoLoadFirstData");
      const lastCacheKey = localStorage.getItem("lastCacheKey");
      let lvs = null;

      if (autoLoadFlag === "true" && lastCacheKey) {
        const navigationCache = localStorage.getItem(lastCacheKey);
        if (navigationCache) {
          try {
            const parsedNavigationCache = JSON.parse(navigationCache);
            if (parsedNavigationCache.listViewData) {
              console.log(
                "📋 Utilisation des configurations préchargées depuis le cache de navigation"
              );
              lvs = parsedNavigationCache.listViewData;
            }
          } catch (parseError) {
            console.warn(
              "Erreur lors du parsing du cache de navigation:",
              parseError
            );
          }
        }
      }

      // Si pas de cache de navigation, essayer le cache local ou charger
      if (!lvs) {
        const cacheKey = `${this.moduleName}_listView`;
        lvs = this.dataCache.get(cacheKey);

        if (!lvs) {
          console.log("📡 Récupération des éléments de liste de vue...");
          lvs = await getListViewElements(
            this.moduleName,
            this.dataService
          );
          if (lvs) {
            this.dataCache.set(cacheKey, lvs);
          }
        }
      }

      // Traitement des configurations selon le format
      if (lvs && lvs[this.moduleName]) {
        // Format standard avec clé moduleName
        // Support des deux formats: nouveau (lvs[module].ListeView) et ancien (lvs[module].data.ListeView)
        const moduleData = lvs[this.moduleName];
        const listeView = moduleData.data?.ListeView || moduleData.ListeView;

        this.current_list_views = listeView?.list || [];
        this.ctas = listeView?.cta || [];
        this.badges = listeView?.badges || [];
      } else if (lvs && typeof lvs === "object") {
        // Format direct depuis le cache de navigation
        const moduleKey = Object.keys(lvs).find(
          (key) => key.toLowerCase() === this.moduleName.toLowerCase()
        );

        if (moduleKey) {
          const moduleData = lvs[moduleKey];
          const listeView = moduleData?.data?.ListeView || moduleData?.ListeView;

          this.current_list_views = listeView?.list || [];
          this.ctas = listeView?.cta || [];
          this.badges = listeView?.badges || [];
        } else {
          console.warn("Format de cache de navigation non reconnu:", lvs);
          this.current_list_views = [];
          this.ctas = [];
          this.badges = [];
        }
      } else {
        this.current_list_views = [];
        this.ctas = [];
        this.badges = [];
      }
      console.log("🏗️ Configurations récupérées:", {
        listViews: this.current_list_views?.length,
        ctas: this.ctas?.length,
        badges: this.badges?.length,
      });

      // Traitement des permissions CTA
      if (this.ctas && this.ctas.length != 0) {
        console.log("🔐 [Cache] Traitement des permissions CTA...");
        this.ctas.forEach((item: any) => {
          if (item?.action != "action") {
            this.permissionCta(item.action);
            console.log(`✅ [Cache] Permission ${item.action} traité`);
          }
        });

        console.log("🎯 [Cache] Permissions calculées:", {
          isPermCreate: this.isPermCreate,
          isPermReporting: this.isPermReporting,
          isPermUpdate: this.isPermUpdate,
          isPermDel: this.isPermDel,
          isPermRefresh: this.isPermRefresh,
          isPermExec: this.isPermExec,
        });
      }

      console.log("🏗️ Configurations récupérées:", {
        listViews: this.current_list_views?.length,
        ctas: this.ctas?.length,
        badges: this.badges?.length,
      });

      // Traitement des permissions CTA
      if (this.ctas && this.ctas.length != 0) {
        console.log("🔐 [Cache] Traitement des permissions CTA...");
        this.ctas.forEach((item: any) => {
          if (item?.action != "action") {
            this.permissionCta(item.action);
            console.log(`✅ [Cache] Permission ${item.action} traité`);
          }
        });

        console.log("🎯 [Cache] Permissions calculées:", {
          isPermCreate: this.isPermCreate,
          isPermReporting: this.isPermReporting,
          isPermUpdate: this.isPermUpdate,
          isPermDel: this.isPermDel,
          isPermRefresh: this.isPermRefresh,
          isPermExec: this.isPermExec,
        });
      } else {
        console.log(
          "⚠️ [Cache] Aucun CTA trouvé pour calculer les permissions"
        );
      }

      console.log("✅ Utilisation des données du cache:", cachedData); // Utiliser les données préchargées du module
      let moduleDataToUse = null;

      // Si cachedData est le cache de navigation enrichi
      if (cachedData && cachedData.moduleData) {
        console.log("📋 Cache de navigation enrichi détecté");
        moduleDataToUse = cachedData.moduleData;
      }
      // Si cachedData est directement les données du module
      else if (cachedData && cachedData[this.moduleName]) {
        console.log("📋 Données directes du module détectées");
        moduleDataToUse = cachedData;
      }
      // Si cachedData est un objet avec une clé unique
      else if (
        cachedData &&
        typeof cachedData === "object" &&
        Object.keys(cachedData).length === 1
      ) {
        console.log("📋 Objet avec clé unique détecté");
        const singleKey = Object.keys(cachedData)[0];
        moduleDataToUse = { [this.moduleName]: cachedData[singleKey] };
      } else {
        console.warn("📋 Format de cache non reconnu, utilisation directe");
        moduleDataToUse = cachedData;
      }

      console.log("📦 Données du module à utiliser:", {
        cacheType: cachedData && cachedData.moduleData ? "enriched" : "direct",
        hasModuleKey: !!(moduleDataToUse && moduleDataToUse[this.moduleName]),
        moduleDataKeys: moduleDataToUse ? Object.keys(moduleDataToUse) : [],
        dataCount:
          moduleDataToUse && moduleDataToUse[this.moduleName]
            ? moduleDataToUse[this.moduleName].length
            : 0,
      });

      // Utiliser les données préchargées
      this.initializeData(moduleDataToUse);
      this.getBadges();
      this.isFirstGetData = false;

      // Marquer les derniers paramètres pour éviter le rechargement
      this.lastModuleName = this.moduleName;
      this.lastDomaine = this.domaine;
    } catch (err) {
      // S'assurer que les flags de chargement sont toujours réinitialisés
      this.isLoading = false;
      this.isLoadingDetails = false;
      this.cdr.markForCheck();
      console.error("❌ Erreur lors du chargement depuis le cache:", err);
      // En cas d'erreur, passer au chargement normal
      throw err;
    }
  }

  /**
   * Méthode de débogage pour vérifier l'état des données après connexion
   */
  public debugAfterLogin(): void {
    console.log("🐛 DEBUG APRÈS CONNEXION - État complet:", {
      moduleName: this.moduleName,
      domaine: this.domaine,
      viewStep: this.viewStep,
      viewStepName: ViewStatus[this.viewStep],
      isLoading: this.isLoading,
      isLoadingDetails: this.isLoadingDetails,
      rowDataLength: this.rowData?.length || 0,
      dataSourceLength: this.dataSource?.data?.length || 0,
      columnDefAgridLength: this.columnDefAgrid?.length || 0,
      displayedColumnsLength: this.displayedColumns?.length || 0,
      records: this.records?.length || 0,
      listViewOne: this.listViewOne?.length || 0,
    });

    // Vérifier le localStorage
    const autoLoadFlag = localStorage.getItem("autoLoadFirstData");
    const lastCacheKey = localStorage.getItem("lastCacheKey");
    const moduleDataKey = `__moduleData_${this.moduleName}`;
    const moduleData = localStorage.getItem(moduleDataKey);

    console.log("🗄️ État du localStorage:", {
      autoLoadFlag,
      lastCacheKey,
      moduleDataKey,
      hasModuleData: !!moduleData,
      moduleDataLength: moduleData ? JSON.parse(moduleData) : null,
    });

    // Forcer l'affichage si les données sont présentes mais l'interface n'est pas correcte
    if (
      this.rowData &&
      this.rowData.length > 0 &&
      this.viewStep === ViewStatus.LOADING
    ) {
      console.log(
        "🔧 Correction forcée - données présentes mais vue en loading"
      );
      this.viewStep = ViewStatus.LIST_VIEW_ONE;
      this.isLoading = false;
      this.isLoadingDetails = false;
      this.cdr.markForCheck();
    }
  }

  /**
   * Méthode de débogage pour vérifier les références dans les données
   */
  public debugReferences(): void {
    console.log("🔗 DEBUG RÉFÉRENCES - Analyse des données:");

    if (this.rowData && this.rowData.length > 0) {
      const sampleItem = this.rowData[0];
      console.log("📋 Premier élément de données:", sampleItem);

      // Analyser chaque propriété pour détecter les références
      Object.keys(sampleItem).forEach((key) => {
        const value = sampleItem[key];
        if (value && typeof value === "object" && !Array.isArray(value)) {
          console.log(`🔗 Référence détectée dans "${key}":`, {
            original: value,
            hasName: !!value.name,
            hasLibelle: !!value.libelle,
            keys: Object.keys(value),
            extractedValue: this.extractReferenceDisplayValue(value),
          });
        }
      });
    }

    // Analyser les métadonnées des colonnes
    if (this.current_list_views && this.current_list_views.length > 0) {
      const currentSection = this.current_list_views.find(
        (lv: any) => lv.name === this.current_sections
      );
      if (currentSection && currentSection.fields) {
        const referenceFields = currentSection.fields.filter(
          (field: any) => field.type === "reference"
        );
        console.log(
          "🏗️ Champs de type référence dans les métadonnées:",
          referenceFields
        );
      }
    }
  }

  public getPicklistBackgroundColor(response: any, cellValue: string) {
    if (!response || !response.options || !Array.isArray(response.options)) {
      return "#f1f1f1";
    }
    const option = response.options.find((opt: any) => opt.value === cellValue);
    return option ? option.color_back : "#f1f1f1";
  }

  public getPicklistTextColor(response: any, cellValue: string) {
    if (!response || !response.options || !Array.isArray(response.options)) {
      return "#6c757d";
    }
    const option = response.options.find((opt: any) => opt.value === cellValue);
    return option ? option.color_font : "#6c757d";
  }

  /**
   * Debug de la sélection ag-Grid pour identifier les problèmes
   */
  public debugAgGridSelection(): void {
    console.log("🔍 === DEBUG SÉLECTION AG-GRID ===");

    if (this.agGrid?.api) {
      console.log("✅ ag-Grid API disponible");

      // Tester les configurations
      console.log("📋 Configuration gridOptions:", {
        rowSelection: this.gridOptions.rowSelection,
        suppressRowClickSelection: this.gridOptions.suppressRowClickSelection,
      });

      // Tester la colonne de sélection
      const columnDefs = this.agGrid.api.getColumnDefs();
      const firstColumn = columnDefs?.[0] as any;
      console.log("📋 Colonne de sélection:", {
        checkboxSelection: firstColumn?.checkboxSelection,
        headerCheckboxSelection: firstColumn?.headerCheckboxSelection,
        headerCheckboxSelectionFilteredOnly:
          firstColumn?.headerCheckboxSelectionFilteredOnly,
      });

      // État actuel de la sélection
      const selectedNodes = this.agGrid.api.getSelectedNodes();
      const selectedRows = this.agGrid.api.getSelectedRows();
      console.log("📋 État sélection:", {
        selectedNodesCount: selectedNodes.length,
        selectedRowsCount: selectedRows.length,
        internalSelectedCount: this.selectedCount,
        iconEnabled: this.iconEnabled,
      });

      // Test de sélection
      console.log("🧪 Test de sélection automatique...");

      // Vérifier qu'il y a des données
      if (this.rowData && this.rowData.length > 0) {
        console.log("📊 Données disponibles:", this.rowData.length, "lignes");

        // Test: sélectionner tout
        this.agGrid.api.selectAll();
        const afterSelectAll = this.agGrid.api.getSelectedNodes();
        console.log(
          "Après selectAll():",
          afterSelectAll.length,
          "nodes sélectionnés"
        );

        // Test: désélectionner tout
        setTimeout(() => {
          this.agGrid.api.deselectAll();
          const afterDeselectAll = this.agGrid.api.getSelectedNodes();
          console.log(
            "Après deselectAll():",
            afterDeselectAll.length,
            "nodes sélectionnés"
          );
        }, 1000);
      } else {
        console.log("❌ Aucune donnée disponible pour le test");
      }
    } else {
      console.log("❌ ag-Grid API non disponible");
      console.log("agGrid object:", this.agGrid);
    }

    console.log("=== FIN DEBUG ===");
  }
  /**
   * Debug spécifique pour vérifier le chargement post-connexion
   */
  public debugPostLoginDataLoad(): void {
    console.log("🔍 === DEBUG CHARGEMENT POST-CONNEXION ===");

    // Vérifier les flags et caches
    const autoLoadFlag = localStorage.getItem("autoLoadFirstData");
    const lastCacheKey = localStorage.getItem("lastCacheKey");
    const moduleDataKey = `__moduleData_${this.moduleName}`;

    console.log("📋 État des caches:", {
      autoLoadFlag,
      lastCacheKey,
      moduleDataKey,
      moduleName: this.moduleName,
    });

    // Vérifier l'état actuel
    console.log("📊 État composant:", {
      viewStep: ViewStatus[this.viewStep],
      rowDataLength: this.rowData?.length || 0,
      agGridReady: !!this.agGrid?.api,
    });

    console.log("=== FIN DEBUG ===");
  }

  /**
   * Debug des CTA et permissions
   */
  public debugCTAState(): void {
    console.group("🎯 DEBUG CTA STATE");
    console.log("📊 État des CTA:", {
      ctas: this.ctas,
      ctasLength: this.ctas?.length || 0,
      ctasStructure: this.ctas?.map((cta: any) => ({
        action: cta.action,
        name: cta.name,
        type: cta.type,
      })),
    });

    console.log("🔐 État des permissions:", {
      isPermCreate: this.isPermCreate,
      isPermReporting: this.isPermReporting,
      isPermUpdate: this.isPermUpdate,
      isPermDel: this.isPermDel,
      iconEnabled: this.iconEnabled,
      exportEnabled: this.exportEnabled,
      isPermExec: this.isPermExec,
      isPermRefresh: this.isPermRefresh,
    });

    console.log("📋 État de l'interface:", {
      viewStep: this.viewStep,
      viewStepName: this.getViewStatusName(this.viewStep),
      isLoading: this.isLoading,
      isLoadingDetails: this.isLoadingDetails,
      hasRowData: !!(this.rowData && this.rowData.length > 0),
      hasColumnDefs: !!(this.columnDefAgrid && this.columnDefAgrid.length > 0),
    });
    console.log("🧪 Test des méthodes CTA:", {
      ctaNameAction: this.ctaName("action"),
      ctaNameCreate: this.ctaName("create"),
      ctaNameReport: this.ctaName("report"),
      ctaNameUpdate: this.ctaName("update"),
      ctaNameDelete: this.ctaName("delete"),
      addProjectMethod: typeof this.addProject,
      generateReportingMethod: typeof this.generateReporting,
    });

    // Test détaillé des CTA disponibles
    if (this.ctas && this.ctas.length > 0) {
      console.log("📋 Détail des CTA disponibles:");
      this.ctas.forEach((cta: any, index: number) => {
        console.log(`  CTA ${index + 1}:`, {
          action: cta.action,
          label: cta.label,
          name: cta.name,
          type: cta.type,
          raw: cta,
        });
      });
    } else {
      console.warn("⚠️ Aucun CTA disponible");
    }
    console.groupEnd();
  }

  /**
   * Test du chargement automatique des données
   */
  public testAutoLoadData(): void {
    console.group("🧪 TEST CHARGEMENT AUTOMATIQUE");

    // Simuler l'état après connexion
    localStorage.setItem("autoLoadFirstData", "true");
    const testCacheKey = `cache_${this.domaine}_${this.moduleName}`;
    localStorage.setItem("lastCacheKey", testCacheKey);

    // Créer des données de test
    const testData = {
      moduleData: {
        [this.moduleName]: [
          { id: 1, name: "Test Item 1", description: "Description test 1" },
          { id: 2, name: "Test Item 2", description: "Description test 2" },
          { id: 3, name: "Test Item 3", description: "Description test 3" },
        ],
      },
      listViewData: {
        [this.moduleName]: {
          data: {
            ListeView: {
              list: [{ name: "default", displayName: "Vue par défaut" }],
              cta: [
                { action: "create", label: "Créer", type: "button" },
                { action: "report", label: "Exporter", type: "button" },
                { action: "update", label: "Modifier", type: "button" },
                { action: "delete", label: "Supprimer", type: "button" },
              ],
              badges: [{ title: "Total", icon: "list" }],
            },
          },
        },
      },
      selectedElementInfo: {
        moduleName: this.moduleName,
        domainName: this.domaine,
      },
      timestamp: Date.now(),
    };

    localStorage.setItem(testCacheKey, JSON.stringify(testData));

    console.log("🎯 Données de test créées:", testData);
    console.log("📋 Rechargement du composant...");

    // Recharger les données
    this.loadData();

    console.groupEnd();
  }

  /**
   * Méthode de diagnostic pour le chargement automatique des données du premier menu
   */
  public diagnosisAutoLoad(): void {
    console.group("🩺 DIAGNOSTIC - Chargement automatique du premier menu");

    // Vérification des flags de chargement automatique
    const autoLoadFlag = localStorage.getItem("autoLoadFirstData");
    const lastCacheKey = localStorage.getItem("lastCacheKey");

    console.log("🚦 Flags de chargement automatique:", {
      autoLoadFlag,
      lastCacheKey,
      shouldAutoLoad: autoLoadFlag === "true" && !!lastCacheKey,
    });

    // Vérification du cache de navigation
    if (lastCacheKey) {
      const navigationCache = localStorage.getItem(lastCacheKey);
      if (navigationCache) {
        try {
          const parsedCache = JSON.parse(navigationCache);
          console.log("📦 Cache de navigation analysé:", {
            hasSelectedElementInfo: !!parsedCache.selectedElementInfo,
            hasModuleData: !!parsedCache.moduleData,
            hasListViewData: !!parsedCache.listViewData,
            moduleDataKeys: parsedCache.moduleData
              ? Object.keys(parsedCache.moduleData)
              : [],
            timestamp: parsedCache.timestamp,
            cacheAge: Date.now() - (parsedCache.timestamp || 0),
          });
        } catch (error) {
          console.error(
            "❌ Erreur lors du parsing du cache de navigation:",
            error
          );
        }
      } else {
        console.warn("⚠️ Clé de cache trouvée mais pas de données associées");
      }
    }

    // Vérification des données du module
    const moduleDataKey = `__moduleData_${this.moduleName}`;
    const moduleData = localStorage.getItem(moduleDataKey);
    console.log("📊 Données du module:", {
      moduleDataKey,
      hasModuleData: !!moduleData,
      moduleName: this.moduleName,
    });

    if (moduleData) {
      try {
        const parsedModuleData = JSON.parse(moduleData);
        console.log("📊 Analyse des données du module:", {
          keys: Object.keys(parsedModuleData),
          hasDataForModule: !!parsedModuleData[this.moduleName],
          dataCount: parsedModuleData[this.moduleName]?.length || 0,
        });
      } catch (error) {
        console.error(
          "❌ Erreur lors du parsing des données du module:",
          error
        );
      }
    }

    // Vérification de l'état actuel du composant
    console.log("🔍 État actuel du composant:", {
      moduleName: this.moduleName,
      domaine: this.domaine,
      viewStep: this.viewStep,
      viewStepName: ViewStatus[this.viewStep],
      isLoading: this.isLoading,
      isLoadingDetails: this.isLoadingDetails,
      rowDataLength: this.rowData?.length || 0,
      dataSourceLength: this.dataSource?.data?.length || 0,
      hasGridAPI: !!this.gridOptions?.api,
    });

    // Vérification des CTA et permissions
    console.log("🎯 CTA et permissions:", {
      ctasLength: this.ctas?.length || 0,
      ctas:
        this.ctas?.map((cta: any) => ({
          action: cta.action,
          name: cta.name,
        })) || [],
      isPermCreate: this.isPermCreate,
      isPermUpdate: this.isPermUpdate,
      isPermDel: this.isPermDel,
      isPermReporting: this.isPermReporting,
      isPermExec: this.isPermExec,
      isPermRefresh: this.isPermRefresh,
    });

    console.groupEnd();
  }

  /**
   * Force le rechargement des données depuis le cache
   */
  public forceReloadFromCache(): void {
    console.log("🔄 Force le rechargement depuis le cache...");

    const autoLoadFlag = localStorage.getItem("autoLoadFirstData");
    const lastCacheKey = localStorage.getItem("lastCacheKey");

    if (autoLoadFlag === "true" && lastCacheKey) {
      const cachedData = localStorage.getItem(lastCacheKey);
      if (cachedData) {
        try {
          const parsedCache = JSON.parse(cachedData);
          console.log("🔄 Rechargement forcé avec cache:", parsedCache);
          this.loadDataFromCache(parsedCache);
        } catch (error) {
          console.error("❌ Erreur lors du rechargement forcé:", error);
        }
      }
    } else {
      console.warn("⚠️ Pas de cache disponible pour le rechargement forcé");
      this.loadData(); // Fallback sur le chargement normal
    }
  }

  /**
   * Nettoie les flags et cache obsolètes qui pourraient interférer
   */
  public cleanupObsoleteFlags(): void {
    console.log("🧹 Nettoyage des flags et cache obsolètes...");

    // Liste des clés à nettoyer
    const keysToClean = [
      "autoLoadFirstData",
      "lastCacheKey",
      "__isAutoSelected",
      "isFirst",
    ];

    // Nettoyer les flags
    keysToClean.forEach((key) => {
      const value = localStorage.getItem(key);
      if (value) {
        console.log(`🗑️ Suppression de ${key}: ${value}`);
        localStorage.removeItem(key);
      }
    });

    // Nettoyer les anciens caches de navigation
    const keys = Object.keys(localStorage);
    keys.forEach((key) => {
      if (key.startsWith("navigationCache_")) {
        const timestamp = parseInt(key.split("_")[1]);
        const age = Date.now() - timestamp;

        // Supprimer les caches de plus de 1 heure
        if (age > 3600000) {
          console.log(`🗑️ Suppression du cache obsolète: ${key}`);
          localStorage.removeItem(key);
        }
      }
    });

    console.log("✅ Nettoyage terminé");
  }

  /**
   * Met à jour les permissions et les CTAs basés sur les métadonnées
   */
  private updatePermissions(): void {
    try {
      // Réinitialiser les permissions
      this.isPermCreate = false;
      this.isPermUpdate = false;
      this.isPermDel = false;
      this.isPermExec = false;
      this.isPermReporting = false;
      this.ctas = [];

      if (!this.metadata || !this.metadata.ctas) {
        console.log("⚠️ updatePermissions() - Pas de métadonnées CTA disponibles");
        return;
      }

      // Évaluer chaque permission basée sur les CTAs des métadonnées
      this.metadata.ctas.forEach((cta: any) => {
        const permissionResult = permissionCta(cta, this.moduleName);
        
        switch (cta.type) {
          case 'create':
            this.isPermCreate = permissionResult;
            break;
          case 'update':
          case 'edit':
            this.isPermUpdate = permissionResult;
            break;
          case 'delete':
            this.isPermDel = permissionResult;
            break;
          case 'execute':
            this.isPermExec = permissionResult;
            break;
          case 'reporting':
          case 'export':
            this.isPermReporting = permissionResult;
            break;
        }

        if (permissionResult) {
          this.ctas.push(cta);
        }
      });

      console.log("✅ updatePermissions() terminé", {
        create: this.isPermCreate,
        update: this.isPermUpdate,
        delete: this.isPermDel,
        execute: this.isPermExec,
        reporting: this.isPermReporting,
        ctas: this.ctas.length
      });
    } catch (error) {
      console.error("❌ Erreur dans updatePermissions()", error);
    }
  }

  /**
   * Calcule et génère les badges/indicateurs basés sur les données
   */
  private calculateBadges(): void {
    try {
      this.generatedBadges = [];

      if (!this.rowData || this.rowData.length === 0) {
        console.log("⚠️ calculateBadges() - Pas de données pour calculer les badges");
        return;
      }

      // Badge du total des éléments
      this.generatedBadges.push({
        title: `Total ${this.moduleName}`,
        result: this.rowData.length,
        type: 'count'
      });

      // Si des métadonnées contiennent des définitions de badges
      if (this.metadata && this.metadata.badges) {
        this.metadata.badges.forEach((badgeDef: any) => {
          try {
            let count = 0;
            
            // Calcul simple basé sur une propriété
            if (badgeDef.field && badgeDef.value) {
              count = this.rowData.filter((row: any) => 
                row[badgeDef.field] === badgeDef.value
              ).length;
            }
            // Calcul basé sur une condition
            else if (badgeDef.condition) {
              count = this.rowData.filter((row: any) => 
                this.evaluateBadgeCondition(row, badgeDef.condition)
              ).length;
            }

            if (badgeDef.title) {
              this.generatedBadges.push({
                title: badgeDef.title,
                result: count,
                type: badgeDef.type || 'count'
              });
            }
          } catch (badgeError) {
            console.warn("⚠️ Erreur calcul badge", badgeDef, badgeError);
          }
        });
      }

      // Badges automatiques basés sur les colonnes communes
      if (this.columnDefAgrid && this.columnDefAgrid.length > 0) {
        // Badge pour les éléments actifs si une colonne status existe
        const statusColumn = this.columnDefAgrid.find((col: any) => 
          col.field === 'status' || col.field === 'state' || col.field === 'etat'
        );
        
        if (statusColumn) {
          const activeCount = this.rowData.filter((row: any) => 
            row[statusColumn.field] === 'actif' || 
            row[statusColumn.field] === 'active' || 
            row[statusColumn.field] === 'enabled'
          ).length;
          
          if (activeCount > 0) {
            this.generatedBadges.push({
              title: 'Éléments Actifs',
              result: activeCount,
              type: 'success'
            });
          }
        }
      }

      console.log("✅ calculateBadges() terminé", this.generatedBadges);
    } catch (error) {
      console.error("❌ Erreur dans calculateBadges()", error);
      this.generatedBadges = [];
    }
  }

  /**
   * Évalue une condition de badge sur une ligne de données
   */
  private evaluateBadgeCondition(row: any, condition: any): boolean {
    try {
      if (typeof condition === 'function') {
        return condition(row);
      }
      
      if (typeof condition === 'object') {
        for (const [key, value] of Object.entries(condition)) {
          if (row[key] !== value) {
            return false;
          }
        }
        return true;
      }
      
      return false;
    } catch (error) {
      console.warn("⚠️ Erreur évaluation condition badge", error);
      return false;
    }
  }

  /**
   * Force la récupération des données depuis l'API (ignore le cache)
   */
  public forceApiReload(): void {
    console.log("🔄 Force le rechargement depuis l'API...");

    // Nettoyer tous les flags de cache
    this.cleanupObsoleteFlags();

    // Réinitialiser les états
    this.isFirstGetData = true;
    this.lastModuleName = "";
    this.lastDomaine = "";

    // Relancer le chargement
    this.loadData();
  }

  // =================== PAGINATION METHODS ===================
  

  // ============================================
  // NOUVELLES MÉTHODES POUR L'UI MODERNE
  // ============================================

  /**
   * Gestion des KPI cards modernes
   */
  getKpiAvatarClass(index: number): string {
    const classes = [
      'bg-primary',
      'bg-success', 
      'bg-warning',
      'bg-info',
      'bg-purple'
    ];
    return classes[index % classes.length];
  }

  getProgressBarClass(index: number): string {
    const classes = [
      'bg-primary',
      'bg-success',
      'bg-warning', 
      'bg-info',
      'bg-purple'
    ];
    return classes[index % classes.length];
  }

  /**
   * Gestion du mode d'affichage
   */
  setViewMode(mode: 'table' | 'cards'): void {
    this.viewMode = mode;
    if (mode === 'cards') {
      // TODO: Implémenter la vue cartes si nécessaire
      console.log('Vue cartes non encore implémentée');
    }
  }

  /**
   * Gestion de la recherche améliorée
   */
  clearSearch(): void {
    this.searchQuery = '';
    if (this.gridApi) {
      this.gridApi.setQuickFilter('');
    }
  }



  /**
   * Gestion des tooltips Bootstrap
   */
  private initializeTooltips(): void {
    setTimeout(() => {
      try {
        const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
        tooltipTriggerList.map(function (tooltipTriggerEl) {
          return new (window as any).bootstrap?.Tooltip(tooltipTriggerEl);
        });
      } catch (error) {
        console.warn('Bootstrap tooltips not available:', error);
      }
    }, 100);
  }

  /**
   * Export de données amélioré
   */
  exportToExcel(): void {
    if (this.gridApi) {
      const timestamp = new Date().toISOString().split('T')[0];
      this.gridApi.exportDataAsExcel({
        fileName: `${this.moduleName}-${timestamp}.xlsx`,
        sheetName: this.moduleName
      });
    }
  }

  exportToCsv(): void {
    if (this.gridApi) {
      const timestamp = new Date().toISOString().split('T')[0];
      this.gridApi.exportDataAsCsv({
        fileName: `${this.moduleName}-${timestamp}.csv`
      });
    }
  }

  // Modern List View Event Handlers
  onModernActionTriggered(action: string): void {
    console.log('🎬 Modern action triggered:', action);
    switch (action) {
      case 'create':
        this.addProject();
        break;
      case 'refresh':
        this.refreshList();
        break;
      case 'export':
        this.exportCsv();
        break;
      default:
        console.log('⚠️ Unknown action:', action);
        break;
    }
  }

  onModernRowSelected(selectedRows: any[]): void {
    console.log('📋 Modern row selection changed:', selectedRows);
    this.listSelected = selectedRows;
    this.iconEnabled = selectedRows.length > 0;
    this.selectedCount = selectedRows.length;
  }

  onModernFilterChanged(filterEvent: any): void {
    console.log('🔍 Modern filter changed:', filterEvent);
  }

  // Temporary methods for template compatibility
  getKpiColor(index: number): string {
    return this.getKpiAvatarClass(index);
  }

  getDefaultKpiIcon(index: number): string {
    const icons = ['analytics', 'trending_up', 'bar_chart', 'pie_chart', 'show_chart'];
    return icons[index % icons.length];
  }

  editProjects(): void {
    console.log('Edit function not implemented');
  }

  deleteProjects(): void {
    this.delete();
  }

  get columnDefs() {
    return this.columnDefAgrid;
  }

  onGridReady(event: any): void {
    console.log('🔧 onGridReady appelé', {
      event,
      agGrid: !!this.agGrid,
      rowDataLength: this.rowData?.length || 0,
      listViewOneLength: this.listViewOne?.length || 0
    });

    // Stocker l'API pour un accès ultérieur
    this.gridApi = event.api;
    const columnApi = event.columnApi;

    // S'assurer que this.agGrid.api est accessible
    if (this.agGrid) {
      this.agGrid.api = event.api;
      this.agGrid.columnApi = columnApi;
    }

    console.log('✅ AG-Grid API stockée:', {
      hasGridApi: !!this.gridApi,
      hasAgGridApi: !!this.agGrid?.api
    });

    // Charger les données disponibles (prioriser rowData qui est la source de vérité)
    if (this.agGrid && this.agGrid.api) {
      const dataToLoad = this.rowData && this.rowData.length > 0 ? this.rowData : this.listViewOne;
      if (dataToLoad && dataToLoad.length > 0) {
        console.log('🔄 Chargement initial des données dans ag-Grid:', dataToLoad.length, 'éléments');
        this.agGrid.api.setRowData(dataToLoad);
      } else {
        console.log('⚠️ Aucune donnée disponible pour ag-Grid au moment de onGridReady');
      }
    }

    // Sizer les colonnes
    setTimeout(() => {
      if (this.gridApi) {
        this.gridApi.sizeColumnsToFit();
      }
    }, 100);
  }

  /**
   * Initialise les définitions de champs pour le système de filtres
   */
  private initializeFieldDefinitions(): void {
    // Récupérer les fields depuis les métadonnées
    let metadataFields: any[] = [];
    if (this.current_list_views && this.current_list_views.length > 0) {
      const currentSection = this.current_list_views.find(
        (lv: any) => lv.name === this.current_sections
      );
      if (currentSection && currentSection.fields) {
        metadataFields = currentSection.fields;
      }
    }

    this.fieldDefinitions = this.columnDefAgrid
      .filter((col: any) => col.field && col.field !== '') // Ignorer les colonnes sans field
      .map((col: any) => {
        let type: FieldType = FieldType.TEXT;
        let options: any[] | undefined;

        // Trouver le champ dans les métadonnées
        const metadataField = metadataFields.find((f: any) => f.name === col.field);

        // Déterminer le type selon le champ
        const fieldName = col.field.toLowerCase();
        if (fieldName.includes('date') || fieldName.includes('echeance')) {
          type = FieldType.DATE;
        } else if (metadataField && metadataField.type === 'enum' && metadataField.options) {
          type = FieldType.SELECT;
          // Récupérer les options depuis les métadonnées
          options = metadataField.options.map((opt: any) => ({
            label: opt.label || opt.value || opt,
            value: opt.value || opt
          }));
        } else if (fieldName === 'status' || fieldName === 'action' || fieldName === 'state' || fieldName === 'etat') {
          type = FieldType.SELECT;
          // Récupérer les options depuis les métadonnées si disponibles
          if (metadataField && metadataField.options) {
            options = metadataField.options.map((opt: any) => ({
              label: opt.label || opt.value || opt,
              value: opt.value || opt
            }));
          } else {
            options = [];
          }
        } else if (fieldName.includes('amount') || fieldName.includes('price') || fieldName.includes('count') ||
                   fieldName === 'passenger' || fieldName === 'ticketed' || fieldName === 'unticketed') {
          type = FieldType.NUMBER;
        }

        return {
          name: col.field,
          label: col.headerName || col.field,
          type: type,
          operators: OPERATORS_BY_TYPE[type],
          options: options
        };
      });

    console.log('🎯 Field definitions initialisées:', this.fieldDefinitions);
  }

  /**
   * Récupère les contraintes pour le panneau de filtres
   */
  public getConstraintsForFilterPanel(): any {
    return this.getConstraintsFromMetadata();
  }

  /**
   * Applique les filtres
   */
  public onFiltersApplied(filters: FilterGroup): void {
    this.currentFilters = filters;
    this.activeFiltersCount = this.filterService.getActiveFiltersCount(filters);
    this.showFilterPanel = false;

    // Rafraîchir les données avec les filtres
    this.loadDataWithFilters();
  }

  /**
   * Réinitialise les filtres
   */
  public onFiltersCleared(): void {
    this.currentFilters = null;
    this.activeFiltersCount = 0;
    this.showFilterPanel = false;

    // Nettoyer les contraintes dans le localStorage
    this.saveFiltersToLocalStorage({});

    // Recharger sans filtres
    this.loadPagedData();
  }

  /**
   * Charge les données avec les filtres appliqués
   */
  private async loadDataWithFilters(): Promise<void> {
    console.log('🔍 Chargement avec filtres:', this.currentFilters);

    if (!this.currentFilters) {
      this.loadData();
      return;
    }

    // Convertir le FilterGroup en format attendu par l'API
    const apiFilters = this.convertFiltersToApiFormat(this.currentFilters);
    console.log('🔍 Filtres convertis pour l\'API:', apiFilters);

    // Sauvegarder les filtres dans les contraintes du localStorage
    this.saveFiltersToLocalStorage(apiFilters);

    // Recharger les données avec les nouveaux filtres
    await this.loadPagedData();

    // Forcer la mise à jour des badges avec les nouvelles valeurs filtrées
    this.cdr.markForCheck();
  }

  /**
   * Convertit le FilterGroup en format API
   */
  private convertFiltersToApiFormat(filterGroup: FilterGroup): any {
    const apiFilters: any = {
      _operator: filterGroup.logicalOperator.toLowerCase() // 'and' ou 'or'
    };

    filterGroup.conditions.forEach((condition: any) => {
      if (this.isGroup(condition)) {
        // Pour l'instant, on ne gère pas les groupes imbriqués
        return;
      }

      const filterCondition = condition as FilterCondition;

      if (!filterCondition.field || !filterCondition.operator) {
        return;
      }

      // Construire le filtre selon l'opérateur
      const fieldName = filterCondition.field;
      const operator = filterCondition.operator;
      const value = filterCondition.value;

      // Format pour l'API backend: filter.field=operator:value ou filter.field=operator:value:value2
      let filterValue = `${operator}:${value}`;

      // Pour les opérateurs qui nécessitent 2 valeurs (between, notBetween)
      if (filterCondition.value2 !== undefined && filterCondition.value2 !== null) {
        filterValue = `${operator}:${value}:${filterCondition.value2}`;
      }

      apiFilters[fieldName] = filterValue;
    });

    return apiFilters;
  }

  /**
   * Vérifie si une condition est un groupe
   */
  private isGroup(item: FilterCondition | FilterGroup): item is FilterGroup {
    return 'conditions' in item && Array.isArray((item as FilterGroup).conditions);
  }

}