<template>
  <div>
    <!-- ligne repo (niveau projet) -->
    <div
      class="group flex items-center rounded text-xs text-fg hover:bg-surface-2/60"
      @contextmenu.prevent="openRepoMenu($event)"
    >
      <button type="button" class="flex min-w-0 flex-1 items-center gap-1 px-2 py-1 text-left" @click="ide.toggleRepo(repo.id)">
        <component :is="repoExpanded ? ChevronDown : ChevronRight" :size="14" class="shrink-0 text-fg-subtle" />
        <FolderGit2 :size="13" class="shrink-0 text-fg-subtle" />
        <span class="truncate font-medium">{{ repo.label }}</span>
        <span v-if="worktreeList.length" class="ml-auto shrink-0 pl-1 text-[10px] text-fg-subtle">{{ worktreeList.length }}</span>
      </button>
      <button
        type="button"
        class="shrink-0 rounded p-0.5 opacity-0 hover:bg-surface-3 hover:text-fg group-hover:opacity-100"
        :title="t('common.settings')"
        @click.stop="openRepoMenu($event)"
      >
        <MoreVertical :size="13" />
      </button>
    </div>

    <div v-if="repoExpanded" class="pl-3">
      <p v-if="worktreeList.length === 0" class="px-3 py-0.5 text-[11px] text-fg-subtle">{{ t('ide.noWorktrees') }}</p>

      <div v-for="wt in worktreeList" :key="wt.path">
        <!-- ligne worktree -->
        <div
          class="group flex items-center rounded text-xs"
          :class="isActiveWt(wt) ? 'bg-surface-2 text-fg' : 'text-fg-muted hover:bg-surface-2/60'"
          @contextmenu.prevent="openWtMenu($event, wt)"
        >
          <button type="button" class="flex min-w-0 flex-1 items-center gap-1 px-2 py-1 text-left" @click="onWtClick(wt)">
            <component :is="isWtExpanded(wt) ? ChevronDown : ChevronRight" :size="14" class="shrink-0 text-fg-subtle" />
            <component :is="wt.isMain ? Home : GitBranch" :size="12" class="shrink-0 text-fg-subtle" />
            <span class="truncate font-mono">{{ wt.branch ?? wt.head.slice(0, 7) }}</span>
            <span v-if="isDirty(wt)" class="ml-auto shrink-0 pl-1 text-warn" :title="t('worktrees.dirty', { n: wt.git.dirtyCount })">●</span>
          </button>
          <button
            type="button"
            class="shrink-0 rounded p-0.5 opacity-0 hover:bg-surface-3 hover:text-fg group-hover:opacity-100"
            :title="t('common.settings')"
            @click.stop="openWtMenu($event, wt)"
          >
            <MoreVertical :size="13" />
          </button>
        </div>

        <!-- sessions live corrélées au worktree (par cwd) -->
        <button
          v-for="s in sessionsFor(wt)"
          :key="s.id"
          type="button"
          class="flex w-full items-center gap-1.5 rounded py-0.5 pr-2 pl-9 text-left text-[11px] hover:bg-surface-2/60"
          :class="ide.activeDockSessionId === s.id ? 'bg-surface-2 text-fg' : 'text-fg-muted'"
          @click="ide.openTerminal(s.id)"
        >
          <SessionStateBadge :session="s" />
          <span class="truncate font-mono">{{ s.command }}</span>
        </button>

        <!-- fichiers du worktree (arbre embarqué, chargé paresseusement au dépliage) -->
        <div v-if="isWtExpanded(wt)" class="pl-4">
          <FileTree
            :wt="wt.path"
            :active="activeFileFor(wt)"
            embedded
            :depth="0"
            @open="(rel) => ide.openFile(wt.repoId, wt.path, rel)"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import {
  ChevronDown,
  ChevronRight,
  FolderGit2,
  GitBranch,
  Home,
  MoreVertical,
  SquareTerminal,
  GitCompare,
  Upload,
  ArrowUp,
  Trash2,
  Scissors,
  Eye,
  EyeOff,
} from '@lucide/vue';
import type { RepoSummary, SessionSummary, WorktreeSummary } from '@arboretum/shared';
import { ApiError } from '../../lib/api';
import { useIdeStore } from '../../stores/ide';
import { useWorktreesStore } from '../../stores/worktrees';
import { useSessionsStore } from '../../stores/sessions';
import { useToastsStore } from '../../stores/toasts';
import { useModalsStore } from '../../stores/modals';
import { useContextMenu, type ContextMenuItem } from '../../composables/useContextMenu';
import FileTree from '../workspace/FileTree.vue';
import SessionStateBadge from '../SessionStateBadge.vue';
import ConfirmModal from './modals/ConfirmModal.vue';
import WorktreeCreateModal from './modals/WorktreeCreateModal.vue';
import NewSessionModal from './modals/NewSessionModal.vue';

const props = defineProps<{ repo: RepoSummary }>();
const { t } = useI18n();
const ide = useIdeStore();
const worktrees = useWorktreesStore();
const sessions = useSessionsStore();
const toasts = useToastsStore();
const modals = useModalsStore();
const ctx = useContextMenu();

const repoExpanded = computed(() => ide.expandedRepoIds.includes(props.repo.id));
const worktreeList = computed(() => worktrees.worktreesForRepo(props.repo.id));

const isWtExpanded = (wt: WorktreeSummary): boolean => ide.expandedWtPaths.includes(wt.path);
const isActiveWt = (wt: WorktreeSummary): boolean =>
  ide.activeContext?.repoId === wt.repoId && ide.activeContext?.wtPath === wt.path;
const isDirty = (wt: WorktreeSummary): boolean => wt.git.dirtyCount > 0;

// sessions vivantes dont le cwd correspond au worktree (corrélation par répertoire).
function sessionsFor(wt: WorktreeSummary): SessionSummary[] {
  return sessions.sessions.filter((s) => s.live && s.cwd === wt.path);
}

// fichier actif si l'onglet éditeur courant appartient à ce worktree.
function activeFileFor(wt: WorktreeSummary): string | null {
  const tab = ide.activeTab;
  return tab && tab.repoId === wt.repoId && tab.wtPath === wt.path ? tab.file : null;
}

function onWtClick(wt: WorktreeSummary): void {
  ide.setActiveWorktree(wt.repoId, wt.path);
  ide.toggleWt(wt.path);
}

// --- menu contextuel repo ---
function openRepoMenu(e: MouseEvent): void {
  const items: ContextMenuItem[] = [
    { label: t('ide.menu.newWorktree'), icon: GitBranch, onSelect: () => void modals.open(WorktreeCreateModal, { repo: props.repo, initialMode: 'worktree' }) },
    { label: t('ide.menu.workOnMain'), icon: Home, onSelect: () => void modals.open(WorktreeCreateModal, { repo: props.repo, initialMode: 'main' }) },
    { label: t('ide.menu.prune'), icon: Scissors, onSelect: () => void onPrune() },
    {
      label: props.repo.hidden ? t('ide.menu.showRepo') : t('ide.menu.hideRepo'),
      icon: props.repo.hidden ? Eye : EyeOff,
      onSelect: () => void onToggleHidden(),
    },
    { label: t('ide.menu.removeRepo'), icon: Trash2, danger: true, onSelect: () => confirmRemoveRepo() },
  ];
  ctx.open(e.clientX, e.clientY, items);
}

async function onPrune(): Promise<void> {
  try {
    await worktrees.prune(props.repo.id);
    toasts.success(t('toast.pruned'));
  } catch (err) {
    toasts.error(err);
  }
}

async function onToggleHidden(): Promise<void> {
  try {
    await worktrees.setHidden(props.repo.id, !props.repo.hidden);
  } catch (err) {
    toasts.error(err);
  }
}

function confirmRemoveRepo(): void {
  modals.open(ConfirmModal, {
    title: t('ide.menu.removeRepo'),
    message: props.repo.path,
    danger: true,
    confirmLabel: t('repos.remove'),
    onConfirm: async () => {
      await worktrees.removeRepo(props.repo.id);
      toasts.success(t('toast.repoRemoved'));
    },
  });
}

// --- menu contextuel worktree ---
function openWtMenu(e: MouseEvent, wt: WorktreeSummary): void {
  const items: ContextMenuItem[] = [
    { label: t('ide.menu.openTerminal'), icon: SquareTerminal, onSelect: () => void modals.open(NewSessionModal, { cwd: wt.path }) },
    { label: t('ide.menu.commit'), icon: GitCompare, onSelect: () => openGitPanel(wt) },
    { label: t('ide.menu.push'), icon: Upload, onSelect: () => void onPush(wt) },
  ];
  if (!wt.isMain) {
    items.push({ label: t('ide.menu.promote'), icon: ArrowUp, onSelect: () => confirmPromote(wt) });
    items.push({ label: t('ide.menu.deleteWorktree'), icon: Trash2, danger: true, onSelect: () => confirmDelete(wt) });
  }
  ctx.open(e.clientX, e.clientY, items);
}

function openGitPanel(wt: WorktreeSummary): void {
  ide.setActiveWorktree(wt.repoId, wt.path);
  ide.setActivity('git');
}

async function onPush(wt: WorktreeSummary): Promise<void> {
  try {
    await worktrees.pushWorktree(wt.repoId, wt.path);
    toasts.success(t('toast.pushed'));
  } catch (err) {
    toasts.error(err);
  }
}

// promotion : « passer en principal » ; escalade force sur 409 (arbre modifié).
function confirmPromote(wt: WorktreeSummary): void {
  modals.open(ConfirmModal, {
    title: t('ide.menu.promote'),
    message: t('worktrees.promoteConfirm', { branch: wt.branch ?? '' }),
    confirmLabel: t('worktrees.promote'),
    onConfirm: async () => {
      try {
        await worktrees.promoteWorktree(wt.repoId, wt.path, false);
        toasts.success(t('ide.menu.promote'));
      } catch (err) {
        if (err instanceof ApiError && err.status === 409) {
          modals.open(ConfirmModal, {
            title: t('worktrees.forcePromote'),
            message: err.message,
            danger: true,
            confirmLabel: t('worktrees.forcePromote'),
            onConfirm: async () => {
              await worktrees.promoteWorktree(wt.repoId, wt.path, true);
              toasts.success(t('ide.menu.promote'));
            },
          });
          return;
        }
        throw err;
      }
    },
  });
}

// suppression : escalade force sur 409 (arbre modifié ou session vivante).
function confirmDelete(wt: WorktreeSummary): void {
  modals.open(ConfirmModal, {
    title: t('ide.menu.deleteWorktree'),
    message: wt.path,
    danger: true,
    confirmLabel: t('worktrees.confirmDelete'),
    onConfirm: async () => {
      try {
        await worktrees.deleteWorktree(wt.repoId, wt.path, false);
        toasts.success(t('toast.worktreeDeleted'));
      } catch (err) {
        if (err instanceof ApiError && err.status === 409) {
          modals.open(ConfirmModal, {
            title: t('worktrees.forceDelete'),
            message: err.message,
            danger: true,
            confirmLabel: t('worktrees.forceDelete'),
            onConfirm: async () => {
              await worktrees.deleteWorktree(wt.repoId, wt.path, true);
              toasts.success(t('toast.worktreeDeleted'));
            },
          });
          return;
        }
        throw err;
      }
    },
  });
}
</script>
