// Conscience du workspace (Phase D) : mappe les dossiers ouverts dans VS Code aux repos/worktrees
// Arboretum par égalité de chemin, met en évidence le worktree correspondant dans l'arbre, et fournit
// le repoId courant aux commandes contextuelles (« start session here », « create worktree here »).
import * as vscode from 'vscode';
import type { Store } from './state/store.js';
import type { ReposNode } from './views/nodes.js';
import type { ReposTreeProvider } from './views/repos-tree.js';

function normPath(p: string): string {
  return p.replace(/\/+$/, '') || '/';
}

export class WorkspaceMapper implements vscode.Disposable {
  private readonly disposables: vscode.Disposable[] = [];

  constructor(
    private readonly store: Store,
    private readonly treeView: vscode.TreeView<ReposNode>,
    private readonly provider: ReposTreeProvider,
  ) {
    this.disposables.push(vscode.workspace.onDidChangeWorkspaceFolders(() => this.revealCurrent()));
    // re-tente après chaque rafraîchissement de l'état (les worktrees arrivent après la connexion).
    this.disposables.push({ dispose: store.onDidChange(() => this.revealCurrent()) });
  }

  /** repoId correspondant à un dossier ouvert (via worktree ou racine de repo), pour les actions contextuelles. */
  currentRepoId(): string | undefined {
    for (const folder of vscode.workspace.workspaceFolders ?? []) {
      const p = normPath(folder.uri.fsPath);
      const match = this.store.findWorktreeByPath(p);
      if (match) return match.repoId;
      const repo = this.store.listRepos().find((r) => normPath(r.path) === p);
      if (repo) return repo.id;
    }
    return undefined;
  }

  /** Met en évidence dans l'arbre le worktree du premier dossier ouvert qui matche. */
  revealCurrent(): void {
    if (!this.treeView.visible) return;
    for (const folder of vscode.workspace.workspaceFolders ?? []) {
      const match = this.store.findWorktreeByPath(normPath(folder.uri.fsPath));
      if (!match) continue;
      const node = this.provider.worktreeNode(match.repoId, match.worktree.path);
      if (node) {
        void this.treeView.reveal(node, { select: false, focus: false, expand: true }).then(undefined, () => {
          /* reveal est best-effort : un échec (nœud pas encore matérialisé) n'est pas bloquant */
        });
        return;
      }
    }
  }

  dispose(): void {
    for (const d of this.disposables) d.dispose();
  }
}
