<template>
  <div class="flex h-dvh min-h-0 flex-col bg-surface-0 text-fg">
    <div v-if="isMobile" class="flex min-h-0 flex-1 flex-col">
      <header class="flex items-center gap-2 border-b border-border px-3 py-2">
        <span class="min-w-0 flex-1 truncate text-sm font-medium">{{ mobileTitle }}</span>
        <button type="button" class="rounded p-1 text-fg-muted hover:bg-surface-2 hover:text-fg" :title="t('common.settings')" @click="openMobileMenu">
          <MoreVertical :size="18" />
        </button>
      </header>
      <div class="min-h-0 flex-1 overflow-hidden">
        <ProjectTree v-if="ide.mobilePanel === 'explorer'" />
        <GitPanel v-else-if="ide.mobilePanel === 'git'" />
        <TerminalDock v-else-if="ide.mobilePanel === 'terminal'" />
        <SessionsPanel v-else-if="ide.mobilePanel === 'sessions'" />
        <GroupsPanel v-else-if="ide.mobilePanel === 'groups'" />
        <EditorArea v-else />
      </div>
      <nav class="flex shrink-0 border-t border-border">
        <button
          v-for="p in mobilePanels"
          :key="p.key"
          type="button"
          class="flex flex-1 flex-col items-center gap-0.5 py-1.5 text-[10px] transition-colors"
          :class="ide.mobilePanel === p.key ? 'text-accent' : 'text-fg-subtle'"
          @click="setMobilePanel(p.key)"
        >
          <component :is="p.icon" :size="18" />
          {{ p.label }}
        </button>
      </nav>
    </div>

    <div v-else class="flex min-h-0 flex-1 flex-col">
      <div class="flex min-h-0 flex-1">
        <ActivityBar />
        <template v-if="ide.leftVisible">
          <PrimarySidebar />
          <PanelSplitter v-model="ide.leftWidth" axis="x" :min="200" :max="560" />
        </template>

        <div class="flex min-w-0 flex-1 flex-col">
          <main class="min-h-0 flex-1 overflow-hidden">
            <EditorArea />
          </main>

          <template v-if="ide.bottomVisible">
            <PanelSplitter v-model="ide.bottomHeight" axis="y" :min="120" :max="640" invert />
            <section class="shrink-0 overflow-hidden border-t border-border" :style="{ height: `${ide.bottomHeight}px` }">
              <TerminalDock />
            </section>
          </template>
        </div>
      </div>

      <StatusBar />
    </div>

    <!-- Hôtes uniques (Teleport vers body) : pile de modals et menu contextuel de l'IDE. -->
    <ModalHost />
    <ContextMenu />
  </div>
</template>

<script setup lang="ts">
// Coquille de la vue IDE (layout 'ide', plein écran). Assemble barre d'activité, panneau gauche,
// zone centrale (éditeur), dock terminaux et barre de statut. Propriétaire de la réconciliation
// des ressources ouvertes contre les données live (worktrees / sessions).
import { computed, defineAsyncComponent, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { Boxes, FileCode, FolderTree, GitCompare, LifeBuoy, List, LogOut, MoreVertical, Settings, SquareTerminal } from '@lucide/vue';
import { decodeWtKey } from '@arboretum/shared';
import { useIdeStore, wtKey } from '../../stores/ide';
import { useWorktreesStore } from '../../stores/worktrees';
import { useSessionsStore } from '../../stores/sessions';
import { useModalsStore } from '../../stores/modals';
import { useContextMenu } from '../../composables/useContextMenu';
import { useSession } from '../../composables/useSession';
import ActivityBar from './ActivityBar.vue';
import PrimarySidebar from './PrimarySidebar.vue';
import PanelSplitter from './PanelSplitter.vue';
import StatusBar from './StatusBar.vue';
import EditorArea from './EditorArea.vue';
import TerminalDock from './TerminalDock.vue';
import ProjectTree from './ProjectTree.vue';
import GitPanel from './GitPanel.vue';
import SessionsPanel from './SessionsPanel.vue';
import GroupsPanel from './GroupsPanel.vue';
import ModalHost from './ModalHost.vue';
import ContextMenu from './ContextMenu.vue';

const { t } = useI18n();
const ide = useIdeStore();
const worktrees = useWorktreesStore();
const sessions = useSessionsStore();
const modals = useModalsStore();
const ctx = useContextMenu();
const { logout } = useSession();
const route = useRoute();

// Overlays lazy (partagés avec l'ActivityBar desktop) : accès compte depuis le menu mobile.
const SettingsOverlay = defineAsyncComponent(() => import('./overlays/SettingsOverlay.vue'));
const HelpOverlay = defineAsyncComponent(() => import('./overlays/HelpOverlay.vue'));
function openMobileMenu(e: MouseEvent): void {
  ctx.open(e.clientX, e.clientY, [
    { label: t('nav.settings'), icon: Settings, onSelect: () => void modals.open(SettingsOverlay) },
    { label: t('nav.help'), icon: LifeBuoy, onSelect: () => void modals.open(HelpOverlay) },
    { label: t('common.logout'), icon: LogOut, onSelect: () => void logout() },
  ]);
}

// --- responsive : panneau unique sous le breakpoint md (768px) ---
const isMobile = ref(false);
let mql: MediaQueryList | null = null;
const syncMobile = (): void => {
  isMobile.value = !!mql?.matches;
};
onMounted(() => {
  mql = window.matchMedia('(max-width: 767px)');
  syncMobile();
  mql.addEventListener('change', syncMobile);
});
onBeforeUnmount(() => mql?.removeEventListener('change', syncMobile));

const mobilePanels = computed(() => [
  { key: 'explorer', icon: FolderTree, label: t('ide.activity.explorer') },
  { key: 'editor', icon: FileCode, label: t('workspace.editor') },
  { key: 'terminal', icon: SquareTerminal, label: t('ide.terminals') },
  { key: 'git', icon: GitCompare, label: t('ide.activity.git') },
  { key: 'sessions', icon: List, label: t('ide.activity.sessions') },
  { key: 'groups', icon: Boxes, label: t('ide.activity.groups') },
]);
const mobileTitle = computed(() => mobilePanels.value.find((p) => p.key === ide.mobilePanel)?.label ?? '');
const setMobilePanel = (key: string): void => {
  ide.mobilePanel = key;
};

// Deep-link / redirections rétro-compat. /workspace/:repoId/:wt (ex. extension VS Code) cible un
// worktree. Sur /ide, on consomme une query one-shot (terminal / panel / overlay) posée par les
// redirections des anciennes routes, puis on l'efface pour garder l'URL propre.
function applyRoute(): void {
  if (route.name === 'workspace') {
    const repoId = String(route.params.repoId ?? '');
    const wt = decodeWtKey(String(route.params.wt ?? ''));
    if (!repoId || !wt) return;
    ide.setActivity('explorer');
    ide.setActiveWorktree(repoId, wt);
    if (!ide.expandedRepoIds.includes(repoId)) ide.toggleRepo(repoId);
    if (!ide.expandedWtPaths.includes(wt)) ide.toggleWt(wt);
    const file = route.query.file ? String(route.query.file) : null;
    if (file) ide.openFile(repoId, wt, file);
    return;
  }
  // Intention portée par le meta de la route (rétro-compat des anciens chemins) : ouvrir un
  // terminal, activer un panneau, ou ouvrir un overlay. URL bookmarkable, aucun strip.
  const m = route.meta;
  if (m.terminal && route.params.id) ide.openTerminal(String(route.params.id));
  if (m.panel === 'sessions' || m.panel === 'groups') ide.setActivity(m.panel);
  if (m.overlay === 'settings') modals.open(SettingsOverlay);
  else if (m.overlay === 'help') modals.open(HelpOverlay);
}
onMounted(applyRoute);
watch(() => route.fullPath, applyRoute);

function prune(): void {
  const live = new Set(sessions.sessions.filter((s) => s.live).map((s) => s.id));
  const known = new Set(worktrees.worktrees.map((w) => wtKey(w.repoId, w.path)));
  ide.pruneDeadResources(live, known);
}

// On ne réconcilie qu'une fois les données prêtes (fetch initial terminé) pour ne pas fermer les
// onglets/terminaux persistés avant leur chargement. Puis à chaque ajout/retrait de worktree ou
// de session.
watch(
  [() => worktrees.loading, () => sessions.sessions.length, () => worktrees.worktrees.length],
  () => {
    if (!worktrees.loading) prune();
  },
  { immediate: true },
);
</script>
