import { DOCUMENT } from "@angular/common";
import {
  Component,
  Inject,
  LOCALE_ID,
  OnInit,
  SimpleChanges,
  ViewChild,
} from "@angular/core";
import { trigger, state, style, transition, animate } from '@angular/animations';
import { AbstractControl, FormBuilder, FormGroup } from "@angular/forms";
import { MatDialog, MAT_DIALOG_DATA } from "@angular/material/dialog";
import { MatAccordion } from "@angular/material/expansion";
import { Subject } from "rxjs";
import { tap } from "rxjs/operators";

import { ModalGenerateDocumentComponent } from "src/app/components/modal-generate-document/modal-generate-document.component";
import { ProjectsComponent } from "src/app/components/projects/projects.component";
import { EventService } from 'src/app/core/services/event.service';
import { ProjectService } from "src/app/services/projects.service";
import { ReportingService } from "src/app/services/reporting.service";
import { StorageService } from 'src/app/core/services/storage.service';
import { ToastService } from "src/app/services/toast.service";
import { ProjectsStore } from "src/app/stores/projects.store";
import {
  detailData,
  getListViewElements,
  permissionCta,
} from "src/app/custom/common";
import { DataService } from "src/app/core/services/data.service";
import { DocumentService } from "src/app/services/document.service";

export interface ActionConfig {
  id: string;
  label: string;
  icon: string;
  inputLabel: string;
  inputPlaceholder: string;
  confirmText: string;
  requiredCta: string;
}

@Component({
  selector: "app-vue-detail",
  templateUrl: "./vue-detail.component.html",
  styleUrls: ["./vue-detail.component.scss"],
  animations: [
    trigger('slideToggle', [
      state('collapsed', style({
        height: '0px',
        opacity: 0,
        overflow: 'hidden'
      })),
      state('expanded', style({
        height: '*',
        opacity: 1,
        overflow: 'visible'
      })),
      transition('collapsed <=> expanded', [
        animate('300ms ease-in-out')
      ])
    ])
  ]
})
export class VueDetailComponent implements OnInit {
  public panelOpenState = false;
  public isClickEdit = false;
  public isClickAdd = false;
  public details!: any;
  public metadatas!: any;
  public tableau!: any;
  public current_tab = "";
  public selectedTabIndex = 0;
  public expandedTabs: Set<string> = new Set();
  public isModernDesign = true; // Toggle entre ancien/nouveau design

  // Gestion des accordéons
  public accordionStates: { [key: string]: boolean } = {
    'bloc-0-informations-générales': true,   // Premier bloc ouvert par défaut
    'donnees-contextuelles': true       // Dernier bloc ouvert par défaut
  };

  // Cache pour les colonnes des onglets (évite la boucle infinie)
  private tabColumnsCache: { [key: string]: string[] } = {};

  public form: FormGroup;
  public dataDepot!: [];
  public isLoadingDepot = false;
  public errorMsg = "";
  public keyword = "name";
  public autocomplete_selected = "Depot";
  public destroy$: Subject<boolean> = new Subject<boolean>();
  public listTabs!: string[];
  @ViewChild(MatAccordion)
  accordion!: MatAccordion;
  public submitted = false;
  public isLoading = false;
  public objectField!: Object;
  public objectName: string = "accounts";
  public domaine: string = "Utilisateurs";
  public level!: any;
  public recordId!: string;
  public allDetails!: any;
  public isLoadingDetails: boolean = true;
  public ctas: any = [];
  public headers: any = [];
  public blocs: any = [];
  public availableActions: string[] = [];

  constructor(
    public dialog: MatDialog,
    @Inject(MAT_DIALOG_DATA) public data: any,
    @Inject(DOCUMENT) private document: Document,
    public projectStore: ProjectsStore,
    @Inject(LOCALE_ID) private locale: string,
    private projectService: ProjectService,
    private reporting: ReportingService,
    private formBuilder: FormBuilder,
    private toast: ToastService,
    public storeService: StorageService,
    private contextuel: EventService,
    public dataService: DataService,
    public storage: StorageService,
    private documentService: DocumentService
  ) {
    this.recordId = this.data.id;
    this.objectField = {
      id: this.data.id,
      name: this.data.label,
      parent: this.data.contextParent,
    };
    this.form = this.formBuilder.group({
      depot: [this.data && this.data.projetsid ? this.data["Depot"] : ""],
    });
  }

  async ngOnInit() {
    this.document.body.classList.add("pop-element");
    const dd = localStorage.getItem("__domaineDD");

    if (dd != null) {
      let __dd = dd ? JSON.parse(dd) : {};
      this.domaine = __dd.domaine;
      this.objectName =
        this.data && this.data && this.data.from
          ? this.data.from
          : __dd.modulename;
    }
    let lvs = this.storage.getItem("__lvs");
    let __lvs = lvs ? JSON.parse(lvs) : {};
    if (__lvs == null || __lvs[this.objectName] == undefined) {
      __lvs = await getListViewElements(this.objectName, this.dataService);
    }
    this.metadatas = __lvs[this.objectName]?.DetailView?.fields;
    this.metadatas?.forEach((element: any) => {
      let parts = this.getKeys(element);
      if (parts.length > 0) {
        this.blocs.push(parts[0]);
      }
    });

    // Initialiser l'état des accordéons pour tous les blocs (fermés par défaut)
    this.blocs.forEach((bloc: string, index: number) => {
      const blocKey = this.getBlocKey(bloc, index);
      if (!this.accordionStates.hasOwnProperty(blocKey)) {
        this.accordionStates[blocKey] = false; // Fermé par défaut
      }
    });
    // Utiliser UNIQUEMENT les CTAs de la DetailView pour la vue détails
    const detailViewCtas = __lvs[this.objectName]?.DetailView?.cta || [];

    // Ne prendre que les CTAs de la vue détails
    this.ctas = detailViewCtas;

    // Effacer le cache des actions disponibles car les CTAs ont changé
    this.clearActionsCache();

    this.headers = __lvs[this.objectName]?.DetailView?.headers
      ? __lvs[this.objectName]?.DetailView?.headers
      : [];
    this.isLoadingDetails = true;


    let dataApi = await detailData(
      this.domaine,
      this.objectName,
      this.data.uuid,
      this.dataService
    );
    if (dataApi && dataApi?.record?.tableau) {
      this.tableau = dataApi?.record?.tableau;

      // Récupérer les actions disponibles depuis l'API
      this.availableActions = dataApi?.record?.availableActions || [];
      console.log('✅ Actions disponibles depuis API:', this.availableActions);
      this.listTabs = Object.keys(dataApi?.record?.tableau);
      this.current_tab = this.listTabs[0];

      // Réinitialiser le cache des colonnes quand les données changent
      this.tabColumnsCache = {};
      
      // Debug: Analyser la structure des données tableau
      console.log('🔍 ANALYSE STRUCTURE TABLEAU:', this.tableau);
      console.log('📋 Onglets disponibles:', this.listTabs);
      
      // Pour chaque onglet, analyser fields vs data
      this.listTabs.forEach(tab => {
        if (this.tableau[tab]) {
          console.log(`\n📊 ONGLET: ${tab}`);
          console.log('  - Fields originaux:', this.tableau[tab].fields);
          console.log('  - Fields transformés:', this.transformField(this.tableau[tab].fields));
          
          if (this.tableau[tab].data && this.tableau[tab].data.length > 0) {
            console.log('  - Premier élément data:', this.tableau[tab].data[0]);
            console.log('  - Clés réelles des données:', Object.keys(this.tableau[tab].data[0]));
            
            // Comparaison directe
            const originalFields = this.tableau[tab].fields;
            const transformedFields = this.transformField(this.tableau[tab].fields);
            const dataKeys = Object.keys(this.tableau[tab].data[0]);
            
            console.log('  📈 ANALYSE MAPPING:');
            transformedFields?.forEach((transformedField: string, index: number) => {
              const originalField = originalFields[index];
              const hasTransformedKey = dataKeys.includes(transformedField);
              const hasOriginalKey = dataKeys.includes(originalField);
              
              console.log(`    "${originalField}" → "${transformedField}"`);
              console.log(`      ✅ Original existe: ${hasOriginalKey}`);
              console.log(`      🔄 Transformé existe: ${hasTransformedKey}`);
            });
          }
        }
      });
    }
    this.isLoadingDetails = false;
    this.checkLevel();

    // Log du niveau contextuel pour debug (n'incrémente PAS car le parent s'en charge)
    console.log('📊 Niveau contextuel dans vue détail:', this.contextuel.getCurrentLevel());

    // Charger la préférence de design depuis localStorage
    const savedDesign = localStorage.getItem('vue-detail-modern-design');
    if (savedDesign !== null) {
      this.isModernDesign = savedDesign === 'true';
    }
  }

  getKeys(obj: any) {
    return Object.keys(obj);
  }

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

  public hasIssueCta(): boolean {
    return this.ctas && this.ctas.some((cta: any) => cta.action === 'issue');
  }

  /**
   * DÉPRÉCIÉ: Matrice de décision déplacée côté serveur
   * Les actions disponibles sont maintenant retournées par l'API getOne()
   * La logique métier (module, status, date) est gérée dans CrudController.php
   */

  /**
   * Retourne les opérations SPC disponibles pour l'élément actuel
   * Les actions sont calculées côté serveur et retournées par l'API
   * Nécessite la permission CTA "execute" sur le module
   */
  public getAvailableSpcOperations(): string[] {
    // Vérifier la permission execute avant de retourner les actions
    if (!this.permissionCta('execute')) {
      return [];
    }
    return this.availableActions;
  }

  /**
   * Exécuter l'action SPC par défaut (première de la liste)
   */
  public executeDefaultAction(): void {
    const availableOps = this.getAvailableSpcOperations();

    if (availableOps.length === 0) {
      this.toast.showWaring('Aucune action disponible pour cet élément');
      return;
    }

    // Si une seule opération : l'exécuter directement
    if (availableOps.length === 1) {
      this.executeSpcOperation(availableOps[0]);
      return;
    }

    // Sinon, le group-button s'affichera automatiquement
    console.log('📋 Plusieurs opérations disponibles:', availableOps);
  }

  /**
   * Récupérer les actions SPC pour le group-button
   */
  public async getExecuteActions(): Promise<ActionConfig[]> {
    const availableOps = this.getAvailableSpcOperations();

    // Import de la config SPC
    const { SPC_OPERATIONS } = await import('src/app/components/modal-execute/spc-operations.config');

    return availableOps.map(opType => {
      const config = SPC_OPERATIONS[opType];
      if (!config) return null;

      return {
        id: opType,
        label: config.title,
        icon: config.icon.replace('fas fa-', ''),
        inputLabel: config.hasCommandInput ? config.helpText : '',
        inputPlaceholder: config.placeholder,
        confirmText: config.confirmButtonText,
        requiredCta: 'execute'
      };
    }).filter(action => action !== null) as ActionConfig[];
  }

  /**
   * Détermine si le bouton d'exécution doit être affiché
   */
  public shouldShowExecuteButton(): boolean {
    return this.getAvailableSpcOperations().length > 0;
  }

  /**
   * Récupère le label dynamique du bouton d'exécution
   */
  public getExecuteButtonLabel(): string {
    const availableOps = this.getAvailableSpcOperations();

    if (availableOps.length === 0) return '';
    if (availableOps.length > 1) return 'Actions';

    // Import synchrone pour opération unique
    return this.getSpcConfig(availableOps[0])?.confirmButtonText || 'Exécuter';
  }

  /**
   * Récupère l'icône dynamique du bouton d'exécution
   */
  public getExecuteButtonIcon(): string {
    const availableOps = this.getAvailableSpcOperations();

    if (availableOps.length === 0) return '';
    if (availableOps.length > 1) return 'list'; // Icône liste pour actions multiples

    // Import synchrone pour opération unique
    return this.getSpcConfig(availableOps[0])?.icon.replace('fas fa-', '') || 'play';
  }

  /**
   * Récupère la config SPC de manière synchrone
   */
  public getSpcConfig(operationType: string): any {
    // Configuration statique intégrée pour éviter l'import async
    const SPC_CONFIGS: any = {
      office_id: { confirmButtonText: 'Vérifier', icon: 'fas fa-shield-alt' },
      load_pnr: { confirmButtonText: 'Charger', icon: 'fas fa-download' },
      issue_pnr: { confirmButtonText: 'Émettre', icon: 'fas fa-paper-plane' },
      void_ticket: { confirmButtonText: 'Annuler', icon: 'fas fa-ban' },
      refund_ticket: { confirmButtonText: 'Demander', icon: 'fas fa-undo' },
      link: { confirmButtonText: 'Associer', icon: 'fas fa-link' },
      pricing: { confirmButtonText: 'Tarifer', icon: 'fas fa-calculator' },
      confirm_pricing: { confirmButtonText: 'Confirmer', icon: 'fas fa-check-circle' }
    };

    return SPC_CONFIGS[operationType];
  }

  /**
   * Exécuter une opération SPC spécifique
   */
  public async executeSpcOperation(operationType: string): Promise<void> {
    const { createSpcModalConfig } = await import('src/app/components/modal-execute/spc-operations.config');
    const { ModalExecuteComponent } = await import('src/app/components/modal-execute/modal-execute.component');

    const modalConfig = createSpcModalConfig(
      operationType,
      [this.data],
      this.objectName,
      this.data.uuid
    );

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

    dialogRef.afterClosed().subscribe(async (result) => {
      if (result && result.confirmed && result.spcPayload) {
        try {
          console.log('🔄 Exécution opération SPC depuis DetailView:', result.spcPayload);

          // Appeler le service pour exécuter l'opération
          const response = await this.projectService
            .executeSpcOperation(result.spcPayload, this.objectName)
            .toPromise();

          if (response && response.success) {
            this.toast.showSuccess(`Opération ${operationType} exécutée avec succès`);

            // Recharger les détails
            await this.ngOnInit();
          } else {
            this.toast.showError(response?.message || 'Erreur lors de l\'exécution');
          }
        } catch (error) {
          console.error('❌ Erreur opération SPC:', error);
          this.toast.showError('Erreur lors de l\'exécution de l\'opération');
        }
      }
    });
  }

  private _cachedAvailableActions: ActionConfig[] | null = null;
  
  /**
   * Invalide le cache des actions disponibles
   */
  private clearActionsCache(): void {
    this._cachedAvailableActions = null;
  }
  
  /**
   * Configuration des actions disponibles dans le dropdown selon le module
   */
  public getAvailableActions(): ActionConfig[] {
    // Cache pour éviter les recalculs répétitifs
    if (this._cachedAvailableActions !== null) {
      return this._cachedAvailableActions;
    }
    
    const moduleName = this.objectName?.toLowerCase();
    let actions: ActionConfig[] = [];


    // Actions spécifiques par module
    switch (moduleName) {
      case 'pnr':
        actions = [
          {
            id: 'issue',
            label: 'Émettre un billet',
            icon: 'send',
            inputLabel: 'Référence d\'émission',
            inputPlaceholder: 'Entrez la référence',
            confirmText: 'Émettre',
            requiredCta: 'issue'
          },
          {
            id: 'attach',
            label: 'Rattacher un billet',
            icon: 'link',
            inputLabel: 'Numéro de billet',
            inputPlaceholder: 'Entrez le numéro de billet',
            confirmText: 'Rattacher',
            requiredCta: 'attach'
          }
        ];
        break;

      case 'presales':
        actions = [
          {
            id: 'issue',
            label: 'Émettre un billet',
            icon: 'send',
            inputLabel: 'Référence d\'émission',
            inputPlaceholder: 'Entrez la référence',
            confirmText: 'Émettre',
            requiredCta: 'issue'
          },
          {
            id: 'pricing',
            label: 'Tarifer un billet',
            icon: 'attach_money',
            inputLabel: 'Référence tarifaire',
            inputPlaceholder: 'Entrez la référence tarifaire',
            confirmText: 'Tarifer',
            requiredCta: 'pricing'
          }
        ];
        break;

      default:
        // Autres modules - configuration générique
        actions = [
          {
            id: 'issue',
            label: 'Émettre',
            icon: 'send',
            inputLabel: 'Référence',
            inputPlaceholder: 'Entrez la référence',
            confirmText: 'Émettre',
            requiredCta: 'issue'
          }
        ];
    }

    // Filtrer les actions selon les CTAs disponibles
    const filteredActions = actions.filter(action => {
      return this.ctas && this.ctas.some((cta: any) => cta.action === action.requiredCta);
    });

    // Mettre en cache le résultat
    this._cachedAvailableActions = filteredActions;
    return filteredActions;
  }

  /**
   * Vérifie s'il y a des actions disponibles
   */
  public hasAvailableActions(): boolean {
    return this.getAvailableActions().length > 0;
  }

  /**
   * Exécute une action sélectionnée dans le dropdown
   */
  public async executeAction(action: ActionConfig): Promise<void> {
    
    // Importer dynamiquement ModalExecuteComponent
    const { ModalExecuteComponent } = await import('src/app/components/modal-execute/modal-execute.component');
    
    const dialogRef = this.dialog.open(ModalExecuteComponent, {
      width: '500px',
      data: {
        title: action.label,
        message: `Veuillez saisir les informations nécessaires pour ${action.label.toLowerCase()}.`,
        showInputField: true,
        inputFieldLabel: action.inputLabel,
        inputFieldPlaceholder: action.inputPlaceholder,
        inputFieldMaxLength: 50,
        inputFieldRequired: true,
        requiresConfirmation: true,
        confirmButtonText: action.confirmText,
        action: action.id,
        records: [{ id: this.recordId, name: this.data.name || this.recordId }],
        count: 1,
        moduleName: this.objectName
      }
    });

    dialogRef.afterClosed().subscribe(async (result) => {
      if (result && result.confirmed && result.inputValue) {
        try {
          const inputValue = result.inputValue;
          
          console.log(`📤 ${action.label} en cours avec valeur:`, inputValue);
          
          // Appeler le service approprié selon l'action
          console.log(`🔄 Exécution de l'action "${action.id}" sur module "${this.objectName}"`);
          
          switch (action.id) {
            case 'issue':
              await this.executeIssueAction(inputValue);
              break;
            case 'pricing':
              await this.executePricingAction(inputValue);
              break;
            case 'attach':
              await this.executeAttachAction(inputValue);
              break;
            default:
              console.warn('Action non gérée:', action.id);
              throw new Error(`Action "${action.id}" non implémentée`);
          }
          
          console.log(`✅ ${action.label} effectuée avec succès`);
          
          // Afficher un message de succès
          this.toast.showSuccess(`${action.label} effectuée avec succès (Valeur: ${inputValue})`);
          
        } catch (error) {
          console.error(`❌ Erreur lors de ${action.label}:`, error);
          this.toast.showError(`Erreur lors de ${action.label}`);
        }
      }
    });
  }

  // Gestion dynamique des CTAs
  public getVisibleCtasCount(): number {
    let count = 0;
    if (this.permissionCta('generate')) count++;
    if (this.permissionCta('update')) count++;
    if (this.hasAvailableActions()) count++; // Dropdown d'actions compte comme 1 bouton
    if (this.permissionCta('delete')) count++; // Bouton supprimer
    count += this.getExtraCtasToShow().length;
    return count;
  }

  public shouldShowCtaLabel(): boolean {
    const count = this.getVisibleCtasCount();
    return count <= 2; // Afficher les labels seulement si 2 CTAs ou moins
  }

  public getCtaButtonClass(ctaType: string): string {
    const count = this.getVisibleCtasCount();
    const baseClass = 'cta-btn';
    
    // Classes selon le nombre de CTAs
    let sizeClass = '';
    if (count === 1) {
      sizeClass = 'cta-single';
    } else if (count === 2) {
      sizeClass = 'cta-double';
    } else {
      sizeClass = 'cta-multiple';
    }
    
    // Classe selon le type
    const typeClass = `cta-${ctaType}`;
    
    return `${baseClass} ${sizeClass} ${typeClass}`;
  }

  public getExtraCtasToShow(): any[] {
    // Ici on peut ajouter d'autres CTAs dynamiques selon les besoins
    // Pour l'instant retourne un tableau vide, mais peut être étendu
    const extraCtas: any[] = [];
    
    // Note: Le bouton "Émettre" est maintenant géré directement dans le template HTML
    // avec la méthode hasIssueCta() pour éviter la duplication
    
    // Exemple de CTAs supplémentaires conditionnels
    if (this.permissionCta('delete')) {
      extraCtas.push({
        type: 'delete',
        icon: 'delete',
        label: 'Supprimer',
        tooltip: 'Supprimer cet élément',
        action: 'delete'
      });
    }
    
    if (this.permissionCta('duplicate')) {
      extraCtas.push({
        type: 'duplicate',
        icon: 'content_copy',
        label: 'Dupliquer',
        tooltip: 'Dupliquer cet élément',
        action: 'duplicate'
      });
    }
    
    if (this.permissionCta('export')) {
      extraCtas.push({
        type: 'export',
        icon: 'download',
        label: 'Exporter',
        tooltip: 'Exporter les données',
        action: 'export'
      });
    }
    
    return extraCtas;
  }

  public handleCtaClick(cta: any): void {
    switch (cta.action) {
      case 'issue':
        this.handleIssue();
        break;
      case 'delete':
        this.handleDelete();
        break;
      case 'duplicate':
        this.handleDuplicate();
        break;
      case 'export':
        this.handleExport();
        break;
      default:
        console.log('Action CTA non gérée:', cta.action);
    }
  }

  public handleDelete(): void {
    // Logique de suppression avec confirmation
    const confirmed = confirm('Êtes-vous sûr de vouloir supprimer cet élément ?');
    if (confirmed) {
      console.log('🗑️ Suppression confirmée pour:', this.recordId);
      // TODO: Implémenter l'appel API de suppression
      // this.dataService.delete(this.domaine, this.objectName, this.recordId)
      this.toast.showSuccess('Élément supprimé avec succès');
    }
  }

  private handleDuplicate(): void {
    // Logique de duplication
    console.log('Duplication demandée');
  }

  private handleExport(): void {
    // Logique d'export
    console.log('Export demandé');
  }

  public async handleIssue(): Promise<void> {
    // Rediriger vers la nouvelle méthode avec dropdown
    const actions = this.getAvailableActions();
    const issueAction = actions.find(a => a.id === 'issue');
    if (issueAction) {
      await this.executeAction(issueAction);
    } else {
      console.warn('Action "issue" non disponible');
    }
  }

  /**
   * Exécute l'action d'émission
   */
  private async executeIssueAction(reference: string): Promise<void> {
    // TODO: Migrer vers DataService ou HttpClientService
    // const response = await this.dataService.executeAction(
    //   this.objectName,
    //   this.recordId,
    //   'issue',
    //   { reference: reference }
    // );
    // return response;
    console.log('Action issue:', reference);
  }

  /**
   * Exécute l'action de tarification
   */
  private async executePricingAction(reference: string): Promise<void> {
    // TODO: Migrer vers DataService ou HttpClientService
    // const response = await this.dataService.executeAction(
    //   this.objectName,
    //   this.recordId,
    //   'pricing',
    //   { reference: reference }
    // );
    // return response;
    console.log('Action pricing:', reference);
  }

  /**
   * Exécute l'action de rattachement
   */
  private async executeAttachAction(ticketNumber: string): Promise<void> {
    // TODO: Migrer vers DataService ou HttpClientService
    // const response = await this.dataService.executeAction(
    //   this.objectName,
    //   this.recordId,
    //   'attach',
    //   { ticketNumber: ticketNumber }
    // );
    // return response;
    console.log('Action attach:', ticketNumber);
  }

  private checkLevel() {
    // Initialiser le niveau actuel de manière synchrone
    this.level = this.contextuel.getCurrentLevel();

    // Souscrire aux changements de niveau (avec cleanup automatique)
    this.contextuel.level$
      .pipe(tap(() => console.log('📊 Mise à jour niveau via Observable')))
      .subscribe((level) => {
        this.level = level;
        this.updatePermissions();
      });

    // Appliquer les permissions initiales
    this.updatePermissions();
  }

  private updatePermissions() {
    if (this.level < 2) {
      this.isClickAdd = true;
    }
    if (this.level < 5) {
      this.isClickEdit = true;
    }
  }

  /**
   * Calcule la configuration du dialog pour l'effet cascade
   * Réduit la largeur de 20px par niveau et décale vers la gauche
   */
  private getCascadeDialogConfig(currentLevel: number): any {
    const baseWidth = 69; // 69vw par défaut
    const widthReduction = 3; // Réduction de 3vw par niveau (environ 20-40px selon l'écran)

    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}`]
    };
  }

  public closeDialog() {
    this.dialog.closeAll();
  }

  get f(): { [key: string]: AbstractControl } {
    return this.form.controls;
  }

  public clickEdit() {
    this.isClickEdit = true;

    // Vérifier directement avec le service pour éviter les problèmes de synchronisation
    const currentLevel = this.contextuel.getCurrentLevel();
    console.log('📊 Vérification niveau pour modification:', currentLevel);

    if (currentLevel <= 4) {
      // Incrémenter le niveau AVANT d'ouvrir le dialog
      this.contextuel.incrementLevel();
      const newLevel = this.contextuel.getCurrentLevel();
      console.log('📊 Niveau incrémenté pour modification:', newLevel);

      // Obtenir la config cascade pour l'effet visuel
      const cascadeConfig = this.getCascadeDialogConfig(newLevel);

      this.data["from"] = this.objectName;
      const dialogRef = this.dialog.open(ProjectsComponent, {
        data: this.data,
        ...cascadeConfig
      });

      // Écouter la fermeture du dialog pour rafraîchir les données
      dialogRef.afterClosed().subscribe(async (result) => {
        // Décrémenter le niveau après fermeture du dialog
        this.contextuel.decrementLevel();
        console.log('📊 Niveau décrémenté après modification:', this.contextuel.getCurrentLevel());

        if (result && result.action === "updated") {
          console.log('✅ Modification réussie, rechargement des données...');
          this.toast.showSuccess('Modification effectuée avec succès');

          // Recharger les données de la vue detail
          await this.reloadDetailData();
        } else if (result && result.error) {
          console.error('❌ Erreur lors de la modification:', result.error);
          this.toast.showError(result.error || 'Erreur lors de la modification');
        }
      });
    } else {
      console.error('❌ Niveau trop élevé pour modification:', currentLevel);
      this.toast.showWaring(
        "Modification non disponible : veuillez réduire le nombre de fenêtres ouvertes"
      );
    }
  }

  /**
   * Recharge les données de la vue detail après modification
   */
  private async reloadDetailData(): Promise<void> {
    try {
      this.isLoadingDetails = true;

      // Recharger les données principales via l'API
      let dataApi = await detailData(
        this.domaine,
        this.objectName,
        this.data.uuid,
        this.dataService
      );

      if (dataApi && dataApi?.record) {
        // Mettre à jour les données principales
        this.data = dataApi.record.data;

        // Mettre à jour le tableau contextuel
        if (dataApi.record.tableau) {
          this.tableau = dataApi.record.tableau;
          this.listTabs = Object.keys(dataApi.record.tableau);

          // Réinitialiser le cache des colonnes
          this.tabColumnsCache = {};
        }

        // Mettre à jour les actions disponibles (si retournées par l'API)
        if (dataApi.record.availableActions) {
          this.availableActions = dataApi.record.availableActions;
          console.log('🔄 Actions disponibles mises à jour:', this.availableActions);
        }

        console.log('✅ Données de la vue detail rechargées avec succès');
      }
    } catch (error) {
      console.error('❌ Erreur lors du rechargement des données:', error);
      this.toast.showError('Erreur lors du rechargement des données');
    } finally {
      this.isLoadingDetails = false;
    }
  }

  public generateProject() {
    this.data["objectName"] = this.objectName;
    this.dialog.open(ModalGenerateDocumentComponent, {
      data: this.data,
      panelClass: ["animate__animated", "animate__slideInRight"],
    });
  }

  public clickAdd() {
    //   this.isClickEdit = true;
    let data = this.data;
    // data['from'] = this.objectName;
    data["from"] = this.current_tab;
    data["contextParent"] = (this.objectField as any).parent;
    data[`${this.objectName}`] = this.objectField;
    this.dialog.open(ProjectsComponent, {
      data: { data },
      position: { right: "0" },
      panelClass: ["animate__animated", "animate__slideInRight"],
    });
  }

  public transformField(data: any) {
    const response =
      data &&
      data.length > 0 &&
      data.map((res: any) => {
        return res.trim().toLowerCase().replace(/\s+/g, "_");
      });

    //console.log('transformField', response);
    return response;
  }

  public getDisplayColumnsForTab(tabName: string): string[] {
    // Vérifier le cache en premier
    if (this.tabColumnsCache[tabName]) {
      return this.tabColumnsCache[tabName];
    }

    if (!this.tableau || !this.tableau[tabName]) {
      console.warn(`⚠️ Pas de tableau pour l'onglet: ${tabName}`);
      return [];
    }

    const sampleData = this.tableau[tabName].data && this.tableau[tabName].data.length > 0
      ? this.tableau[tabName].data[0]
      : null;

    if (!sampleData) {
      console.warn(`⚠️ Pas de données pour l'onglet: ${tabName}`);
      return [];
    }

    const dataKeys = Object.keys(sampleData);
    console.log(`📋 Traitement de l'onglet ${tabName}:`, {
      nombreDonnees: this.tableau[tabName].data.length,
      clesDonnees: dataKeys
    });

    // Essayer d'utiliser les métadonnées ListeView depuis le localStorage
    let metadataColumns = this.getColumnsFromListViewMetadata(tabName);

    if (metadataColumns.length > 0) {
      console.log(`📄 Utilisation métadonnées ListeView pour ${tabName}:`, metadataColumns);
      const columns = this.mapMetadataColumnsToData(metadataColumns, dataKeys, tabName);
      this.tabColumnsCache[tabName] = columns; // Mettre en cache
      return columns;
    }

    // Fallback: génération automatique depuis les données
    console.log(`🔧 Génération automatique des colonnes pour ${tabName} depuis les données`);

    // Colonnes prioritaires à afficher en premier
    const priorityColumns = ['name', 'firstname', 'lastname', 'email', 'phone', 'mobile', 'description', 'montant', 'statut', 'reference'];
    const excludedKeys = ['id', 'uuid', 'created_at', 'updated_at', 'modified_at', 'modified_by', 'is_deleted', 'account_id'];

    // D'abord les colonnes prioritaires qui existent
    const finalColumns = priorityColumns.filter(col => dataKeys.includes(col));

    // Puis les autres colonnes non exclues
    const otherColumns = dataKeys.filter(key =>
      !excludedKeys.includes(key) &&
      !priorityColumns.includes(key)
    );

    finalColumns.push(...otherColumns);

    console.log(`✅ Colonnes auto-générées pour ${tabName}:`, finalColumns);

    // Mettre en cache avant de retourner
    this.tabColumnsCache[tabName] = finalColumns;
    return finalColumns;
  }

  private getColumnsFromListViewMetadata(tabName: string): string[] {
    try {
      const lvs = localStorage.getItem('__lvs');
      if (!lvs) return [];
      
      const metadata = lvs ? JSON.parse(lvs) : {};
      const moduleMetadata = metadata[tabName];

      if (moduleMetadata?.ListeView?.fields) {
        return moduleMetadata.ListeView.fields.map((field: any) => field.name || field);
      }

      return [];
    } catch (error) {
      console.warn(`⚠️ Erreur lors de la récupération des métadonnées pour ${tabName}:`, error);
      return [];
    }
  }

  private mapMetadataColumnsToData(metadataColumns: string[], dataKeys: string[], tabName: string): string[] {
    const validColumns: string[] = [];

    metadataColumns.forEach((field: string) => {
      const transformedField = field.trim().toLowerCase().replace(/\s+/g, "_");
      
      // Priorité 1: Le field original existe dans les données
      if (dataKeys.includes(field)) {
        validColumns.push(field);
      }
      // Priorité 2: Le field transformé existe dans les données  
      else if (dataKeys.includes(transformedField)) {
        validColumns.push(transformedField);
      }
      // Priorité 3: Vérifier des variations communes
      else {
        const variations = [
          field.toLowerCase(),
          field.toUpperCase(),
          field.replace(/\s+/g, ''),
          field.replace(/\s+/g, '_').toLowerCase()
        ];
        
        const foundVariation = variations.find(variation => dataKeys.includes(variation));
        if (foundVariation) {
          validColumns.push(foundVariation);
        } else {
          console.warn(`⚠️ Colonne "${field}" (métadonnées) non mappée dans les données pour ${tabName}`);
        }
      }
    });

    // S'assurer qu'on a au moins quelques colonnes importantes
    if (validColumns.length === 0) {
      const fallbackColumns = ['name', 'description', 'created_at'].filter(col => dataKeys.includes(col));
      validColumns.push(...fallbackColumns);
    }

    console.log(`✅ Mapping métadonnées → données pour ${tabName}:`, validColumns);
    return validColumns; // Toutes les colonnes métadonnées avec scroll
  }

  public tabChange(data: any) {
    this.current_tab = data.tab.textLabel;
  }

  public getTabDisplayName(tabName: string): string {
    const tabDisplayNames: { [key: string]: string } = {
      'accounts': 'Comptes',
      'contacts': 'Contacts', 
      'banques': 'Banques',
      'transaction': 'Transactions',
      'factures': 'Factures',
      'beneficiaires': 'Bénéficiaires',
      'approvisionnements': 'Approvisionnements',
      'bmps': 'BMPs',
      'creditlimit': 'Limites de crédit',
      'etatsdeventes': 'États de vente',
      'helpdesk': 'Support',
      'presale': 'Prévente',
      'setups': 'Configuration',
      'soldes': 'Soldes',
      'soldesbmp': 'Soldes BMP'
    };
    
    return tabDisplayNames[tabName] || this.capitalizeFirst(tabName);
  }

  private capitalizeFirst(str: string): string {
    return str.charAt(0).toUpperCase() + str.slice(1);
  }

  /**
   * Méthodes pour la gestion des onglets contextuels
   */
  getTabsWithData(): string[] {
    if (!this.tableau || !this.listTabs) return [];
    
    return this.listTabs.filter(tab => 
      this.tableau[tab]?.data && 
      this.tableau[tab].data.length > 0
    );
  }

  getTabsWithoutData(): string[] {
    if (!this.tableau || !this.listTabs) return [];
    
    return this.listTabs.filter(tab => 
      !this.tableau[tab]?.data || 
      this.tableau[tab].data.length === 0
    );
  }

  jumpToTab(tabName: string): void {
    const tabsWithData = this.getTabsWithData();
    const index = tabsWithData.indexOf(tabName);
    
    if (index !== -1) {
      this.selectedTabIndex = index;
      this.current_tab = tabName;
    }
  }

  toggleExpandTab(tabName: string): void {
    if (this.expandedTabs.has(tabName)) {
      this.expandedTabs.delete(tabName);
    } else {
      this.expandedTabs.add(tabName);
    }
  }

  isTabExpanded(tabName: string): boolean {
    return this.expandedTabs.has(tabName);
  }

  /**
   * Création d'objets contextuels
   */
  createContextualObject(contextualType: string): void {
    console.log(`🚀 Création d'objet contextuel de type: ${contextualType}`);

    // Préparer les données contextuelles
    const contextualData = {
      ...this.data, // Données de l'objet parent
      from: contextualType, // Type d'objet à créer
      contextParent: this.objectField, // Référence parent
      [this.objectName]: this.objectField, // Relation avec l'objet courant
      contextualType: contextualType, // Type contextuel
      parentId: this.data.id, // ID du parent pour la relation
      parentUuid: this.data.uuid // UUID du parent
    };

    console.log('💾 Données contextuelles préparées:', contextualData);

    // Vérifier directement avec le service pour éviter les problèmes de synchronisation
    const currentLevel = this.contextuel.getCurrentLevel();
    console.log('📊 Vérification niveau pour création contextuelle:', currentLevel);

    // Utiliser le système de création existant avec contexte
    if (currentLevel <= 4) {
      // Incrémenter le niveau contextuel AVANT d'ouvrir le dialog
      this.contextuel.incrementLevel();
      const newLevel = this.contextuel.getCurrentLevel();
      console.log('📊 Niveau incrémenté pour création contextuelle:', newLevel);

      // Obtenir la config cascade pour l'effet visuel
      const cascadeConfig = this.getCascadeDialogConfig(newLevel);

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

      // Écouter la fermeture pour décrémenter le niveau
      dialogRef.afterClosed().subscribe((result) => {
        this.contextuel.decrementLevel();
        console.log('📊 Niveau décrémenté après création contextuelle:', this.contextuel.getCurrentLevel());

        // Si création réussie, rafraîchir les données
        if (result && result.action === "created") {
          this.refreshContextualData(contextualType);
        }
      });

      // Afficher notification
      this.toast.showSuccess(`Création de ${this.getTabDisplayName(contextualType).toLowerCase()}...`);
    } else {
      console.error('❌ Niveau trop élevé pour création contextuelle:', currentLevel);
      this.toast.showWaring(
        "Création non disponible : veuillez réduire le nombre de fenêtres ouvertes"
      );
    }
  }

  /**
   * Méthode pour rafraîchir les données après création
   */
  refreshContextualData(contextualType?: string): void {
    console.log(`🔄 Rafraîchissement des données ${contextualType || 'générales'}`);
    this.isLoadingDetails = true;

    // Ici on pourrait implémenter une logique de rafraîchissement
    // pour mettre à jour le tableau après création d'un nouvel objet
    // Par exemple, recharger les données depuis l'API
    setTimeout(() => {
      this.isLoadingDetails = false;
    }, 1000);
  }

  /**
   * Basculer entre ancien et nouveau design
   */
  toggleDesign(): void {
    this.isModernDesign = !this.isModernDesign;
    console.log(`🎨 Design basculé vers: ${this.isModernDesign ? 'Moderne' : 'Classique'}`);
    
    // Sauvegarder la préférence dans localStorage
    localStorage.setItem('vue-detail-modern-design', this.isModernDesign.toString());
    
    // Notification
    this.toast.showSuccess(`Design ${this.isModernDesign ? 'moderne' : 'classique'} activé`);
  }

  /**
   * Vérifie si un champ est une référence navigable (objet avec id/uuid et name)
   */
  isReferenceField(fieldMeta: any, value: any): boolean {
    if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
    if (!(value.id || value.uuid)) return false;
    if (fieldMeta?.type === 'reference') return true;
    // Fallback : si l'objet a un id et un name, on le considère comme une référence
    return !!(value.id && value.name);
  }

  /**
   * Checks if a field represents a downloadable file (Filename column in documents module)
   */
  isFileField(fieldMeta: any): boolean {
    const name = fieldMeta?.name?.toLowerCase();
    return (
      this.objectName?.toLowerCase() === 'documents' &&
      (name === 'filename' || name === 'nom du fichier')
    );
  }

  /**
   * Download the file associated with the current document
   */
  downloadDocument(): void {
    const uuid = this.data?.uuid;
    const filename = this.data?.['Filename'] || this.data?.['Nom du fichier'] || this.data?.filename || 'document';
    if (uuid) {
      this.documentService.downloadByUuid(uuid, filename);
    }
  }

  /**
   * Ouvre la vue détail d'un élément référencé
   */
  openReferenceDetail(value: any, fieldMeta: any): void {
    if (!value || typeof value !== 'object') return;

    const refModule = fieldMeta?.reference || fieldMeta?.module || fieldMeta?.name || '';
    const currentLevel = this.contextuel.getCurrentLevel();

    if (currentLevel <= 4) {
      this.contextuel.incrementLevel();
      const newLevel = this.contextuel.getCurrentLevel();
      const cascadeConfig = this.getCascadeDialogConfig(newLevel);

      const refData = {
        ...value,
        contextParent: refModule,
        from: refModule
      };

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

      dialogRef.afterClosed().subscribe(() => {
        this.contextuel.decrementLevel();
      });
    } else {
      this.toast.showWaring("Trop de panneaux ouverts, veuillez en fermer avant de continuer.");
    }
  }

  ngOnDestroy() {
    if (this.dialog.openDialogs.length === 0) {
      this.document.body.classList.remove("pop-element");
    }
    // delete this.allDetails[this.recordId];
    // this.projectStore.setDetails(this.allDetails)

    // Note: La gestion du niveau est faite par le composant parent qui ouvre le dialog
    // (table-vue-details, list-view-one, etc.)
    console.log('📊 Vue détail fermée, niveau actuel:', this.contextuel.getCurrentLevel());

    // this.projectStore.setDetails([]);
    this.projectService.editData$.next("");
    this.destroy$.next(true);
    this.destroy$.unsubscribe();
  }

  public getServerResponseDepot(event: string) {
    this.isLoadingDepot = true;
    if (event) {
      this.reporting.getByDepot(this.form.value.depot).subscribe(
        (data) => {
          data.length > 0 ? (this.dataDepot = data) : (this.dataDepot = []);
          this.isLoadingDepot = false;
        },
        (err) => {
          (this.errorMsg = "erreur depuis nos serveur , desole"),
            (this.isLoadingDepot = false);
        }
      );
    } else {
      this.isLoadingDepot = false;
    }
  }

  public selectEvent(item: any) {
    this.isLoading = true;
    let payload = {
      project_name: this.data["Nom du projet"],
      depot: item.id,
      projetsid: this.data ? this.data.projetsid : "",
      assign: this.data["Assigné à"],
    };

    // this.projectService
    //   .updateProject(payload)
    //   .pipe(
    //     tap((res: any) => {
    //       if (res && res.success) {
    //         this.toast.showSuccess('Modifications avec succès');
    //         this.isLoading = false;
    //       } else {
    //         this.toast.showError(
    //           "L'autorisation d'effectuer l'opération est refusée pour l'identifiant"
    //         );
    //         this.isLoading = false;
    //       }
    //     })
    //   )
    //   .subscribe();
  }

  public selectEventGroup(item: any) {
    //  this.form.value.account_name = item.name;
  }

  public onChangeSearch(val: string) {
    // fetch remote data from here
    // And reassign the 'data' which is binded to 'data' property.
  }

  public onFocused(e: any, autocomplete: string) {
    this.autocomplete_selected = autocomplete;
  }
  public clearInput() {
    this.autocomplete_selected = "";
  }

  ngOnChanges(changes: SimpleChanges): void {
    //console.log('detais;', this.details);
  }

  // public searchCleared() {
  //   this.isLoading = true;
  //   let payload = {
  //     project_name: this.data['Nom du projet'],
  //     depot: '',
  //     projetsid: this.data ? this.data.projetsid : '',
  //     assign: this.data['Assigné à'],
  //   };
  //   this.projectService
  //     .updateProject(payload)
  //     .pipe(
  //       tap((res: any) => {
  //         if (res && res.success) {
  //           this.toast.showSuccess('Modifications avec succès');
  //           this.isLoading = false;
  //         } else {
  //           this.toast.showError(
  //             "L'autorisation d'effectuer l'opération est refusée pour l'identifiant"
  //           );
  //           this.isLoading = false;
  //         }
  //       })
  //     )
  //     .subscribe();
  // }

  /**
   * Méthodes helper pour le design moderne
   */
  generateAvatar(name: string): string {
    if (!name) return 'D';
    return name
      .split(' ')
      .map(word => word.charAt(0))
      .join('')
      .toUpperCase()
      .substring(0, 2);
  }

  isEmailField(fieldName: string): boolean {
    const emailFields = ['email', 'mail', 'courriel'];
    return emailFields.some(field =>
      fieldName?.toLowerCase().includes(field)
    );
  }

  isMoneyField(fieldName: string): boolean {
    const moneyFields = ['amount', 'prix', 'price', 'cost', 'solde', 'balance', 'montant'];
    return moneyFields.some(field =>
      fieldName?.toLowerCase().includes(field)
    );
  }

  isImportantField(fieldName: string): boolean {
    const importantFields = ['total', 'sum', 'principale', 'important', 'critical'];
    return importantFields.some(field =>
      fieldName?.toLowerCase().includes(field)
    );
  }

  formatFieldValue(value: any, fieldName: string): string {
    // if (!value && value !== 0) return 'Non renseigné';
    if (!value && value !== 0) return '';

    // Si c'est un objet avec un id et un name, on affiche le name
    if (value?.id && value?.name) {
      return value.name;
    }

    // Formatage des montants monétaires
    if (this.isMoneyField(fieldName) && typeof value === 'number') {
      return new Intl.NumberFormat('fr-FR', {
        style: 'currency',
        currency: 'EUR'
      }).format(value);
    }

    // Formatage des dates
    if (fieldName?.toLowerCase().includes('date') || fieldName?.toLowerCase().includes('created') || fieldName?.toLowerCase().includes('updated')) {
      try {
        const date = new Date(value);
        if (!isNaN(date.getTime())) {
          return date.toLocaleDateString('fr-FR');
        }
      } catch (e) {
        // Continue with default formatting
      }
    }

    return value.toString();
  }

  /**
   * Méthodes pour la gestion moderne des onglets contextuels
   */
  jumpToOthers(): void {
    this.selectedTabIndex = this.getTabsWithData().length;
  }


  addContextualData(): void {
    console.log('➕ Ajout de données contextuelles');
    // TODO: Implémenter l'ajout de données
  }

  getLastUpdateTime(): string {
    // Simulation du temps de dernière mise à jour
    return '5 min';
  }

  /**
   * Toggle l'état d'un accordéon
   */
  toggleAccordion(accordionKey: string): void {
    this.accordionStates[accordionKey] = !this.accordionStates[accordionKey];
  }

  /**
   * Vérifie si un accordéon est ouvert
   */
  isAccordionOpen(accordionKey: string): boolean {
    return this.accordionStates[accordionKey] || false;
  }

  /**
   * Vérifie si un bloc est ouvert par son index (optimisé pour le template)
   */
  isBlocOpen(bloc: string, index: number): boolean {
    const key = this.getBlocKey(bloc, index);
    return this.accordionStates[key] || false;
  }

  /**
   * Toggle un bloc par son index (optimisé pour le template)
   */
  toggleBloc(bloc: string, index: number): void {
    const key = this.getBlocKey(bloc, index);
    this.toggleAccordion(key);
  }

  /**
   * Génère une clé unique pour un bloc d'accordéon
   */
  getBlocKey(bloc: string, index: number): string {
    return `bloc-${index}-${bloc.toLowerCase().replace(/\s+/g, '-')}`;
  }
}
