import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

/** Type d'entité déplaçable (réordonnancement par glisser-déposer dans l'arbre). */
export type ReorderKind = 'arc' | 'chapter' | 'scene' | 'npc' | 'enemy' | 'table' | 'folder' | 'page';

/** Contexte servant à recharger la bonne sidebar après un réordonnancement. */
export interface SidebarReorderContext {
  scope: 'campaign' | 'lore';
  id: string;
}

export interface TreeItem {
  id: string;
  label: string;
  children?: TreeItem[];
  route?: string;      // si défini, cliquer navigue au lieu de toggler
  isAction?: boolean;  // style "action" (ex: "+ Nouveau chapitre")
  /** Clé d'icône optionnelle (ex: "users"). Résolue par le composant via `resolveIcon`. */
  iconKey?: string;
  /** Type d'entité déplaçable (active le drag sur ce nœud). Absent = non déplaçable. */
  dragKind?: ReorderKind;
  /** Id BRUT de l'entité (sans préfixe) — utilisé pour l'ordre persisté. */
  dragId?: string;
  /** Types acceptés en dépôt dans la liste des enfants de ce nœud (drop list). */
  dropKinds?: ReorderKind[];
  /** Parent transmis au réordonnancement (arcId, chapterId, nodeId, dossier…). */
  dropParentId?: string | null;
  /** Petit badge affiché à droite (ex: "3" pour compter les pages d'un dossier). */
  meta?: string;
  /**
   * Libellé de section affiché AU-DESSUS du nœud, avec un filet de séparation.
   * Utilisé pour grouper visuellement des nœuds racines (ex: "Personnages" vs "Narration").
   */
  sectionHeaderBefore?: string;
  /**
   * Actions de creation contextuelles (ex: "+ Nouveau chapitre" sur un arc).
   * Affichees comme boutons icone au survol du noeud (repli visuel), et en
   * pleine largeur si le noeud est expanded sans aucun enfant reel
   * (empty-state inline, meilleur des deux mondes).
   */
  createActions?: TreeCreateAction[];
}

export interface TreeCreateAction {
  id: string;
  label: string;      // tooltip au hover, texte complet en empty-state
  route: string;
  /** Cle d'icone cote sidebar (plus | folder-plus | file-plus). */
  actionIcon?: 'plus' | 'folder-plus' | 'file-plus';
}

export interface GlobalItem {
  id: string;
  name: string;
  route: string;
}

export interface SidebarAction {
  id: string;
  label: string;
  variant: 'primary' | 'secondary' | 'success';
  route?: string;
}

/**
 * Item affiché dans un panneau secondaire (ex: liste des Templates).
 * Plus simple qu'un TreeItem : pas de récursion, juste label + meta + route.
 */
export interface BottomPanelItem {
  id: string;
  label: string;
  meta?: string;      // petit badge à droite (ex: "8 champs")
  route?: string;
  isAction?: boolean; // style "action" (ex: "+ Nouveau template")
}

/**
 * Panneau secondaire collapsible en bas de la sidebar (sous l'arbre).
 * Utilisé notamment pour le panneau "Templates" côté Lore.
 */
export interface BottomPanel {
  id: string;         // identifiant pour mémoriser l'état ouvert/fermé
  title: string;
  items: BottomPanelItem[];
  /** Action "+" inline dans le header — créer un item sans déplier le panneau. */
  headerAction?: { label: string; route: string };
}

export interface SecondarySidebarConfig {
  title: string;
  /**
   * Si défini, le titre devient cliquable et navigue vers cette route
   * (ex: accueil de la campagne depuis n'importe quelle sous-page). Absent =
   * titre statique (cas du Lore).
   */
  titleRoute?: string;
  items: TreeItem[];
  createActions: SidebarAction[];
  globalItems: GlobalItem[];
  globalBackLabel: string;
  globalBackRoute: string;
  bottomPanel?: BottomPanel;   // optionnel : présent côté Lore (Templates)
  /** @deprecated Remplacé par bottomPanel. Gardé pour compat des callers campagne. */
  footerLabel?: string;
  /** Types déplaçables acceptés à la RACINE de l'arbre (ex: arcs côté campagne). */
  rootDropKinds?: ReorderKind[];
  /** Parent transmis au reorder pour les éléments racine (campaignId, ou null = racine lore). */
  rootDropParentId?: string | null;
  /** Contexte de rechargement après un réordonnancement (présent = DnD activé). */
  reorderContext?: SidebarReorderContext;
}

/**
 * Service de layout — contrôle l'affichage de la secondary sidebar
 * et les données contextuelles de la sidebar globale.
 *
 * L'état d'expansion des items de l'arbre est maintenu au niveau du service
 * (et non dans le composant secondary-sidebar), pour survivre aux
 * destructions/recréations du composant lors des navigations (le *ngIf dans
 * app.component.html détruit la sidebar à chaque `hide()`).
 */
@Injectable({ providedIn: 'root' })
export class LayoutService {
  private config$ = new BehaviorSubject<SecondarySidebarConfig | null>(null);
  private readonly expanded = new Set<string>();

  readonly secondarySidebar$ = this.config$.asObservable();

  show(config: SecondarySidebarConfig): void {
    this.config$.next(config);
  }

  hide(): void {
    this.config$.next(null);
  }

  isExpanded(id: string): boolean {
    return this.expanded.has(id);
  }

  toggleExpanded(id: string): void {
    if (this.expanded.has(id)) this.expanded.delete(id);
    else this.expanded.add(id);
  }

  setExpanded(id: string, state: boolean): void {
    if (state) this.expanded.add(id);
    else this.expanded.delete(id);
  }
}
