<template>
  <PageHeader :title="t('nav.worktrees')">
    <BaseButton variant="ghost" size="sm" :icon="ScanSearch" :loading="scanning" @click="onDiscover">
      {{ t('repos.scan') }}
    </BaseButton>
    <BaseButton variant="ghost" size="sm" :icon="RefreshCw" :loading="store.loading" @click="refresh">
      {{ t('common.refresh') }}
    </BaseButton>
  </PageHeader>

  <AttentionSection />

  <form class="card flex flex-col gap-2 sm:flex-row sm:items-end" @submit.prevent="onAddRepo">
    <label class="flex flex-1 flex-col gap-1 text-xs text-zinc-400">
      {{ t('repos.pathLabel') }}
      <input v-model="newPath" type="text" class="input font-mono" :placeholder="t('repos.pathPlaceholder')" required />
    </label>
    <BaseButton type="button" :icon="FolderOpen" class="whitespace-nowrap" @click="showPicker = !showPicker">
      {{ t('fs.browse') }}
    </BaseButton>
    <BaseButton type="submit" variant="primary" :icon="Plus" class="whitespace-nowrap" :loading="adding" :disabled="newPath.trim() === ''">
      {{ t('repos.add') }}
    </BaseButton>
  </form>
  <DirectoryPicker
    v-if="showPicker"
    mode="repo"
    :initial-path="newPath"
    @select="onPickPath"
    @close="showPicker = false"
  />

  <SkeletonRow v-if="store.loading && store.repos.length === 0" />
  <EmptyState v-else-if="store.repos.length === 0" :icon="GitBranch" :title="t('repos.empty')" />

  <template v-else>
    <!-- une seule toolbar pilote le tri/filtre des worktrees de toutes les sections -->
    <ListToolbar :controls="view" search-placeholder-key="controls.searchPlaceholder" />
    <label v-if="hiddenCount > 0" class="flex items-center gap-2 px-1 text-xs text-zinc-400">
      <input v-model="showHidden" type="checkbox" /> {{ t('repos.showHidden', { n: hiddenCount }) }}
    </label>
    <EmptyState v-if="visibleRepos.length === 0" :icon="Search" :title="t('controls.results', 0)" />
    <RepoSection v-for="repo in pagedRepos" :key="repo.id" :repo="repo" />
    <Pagination
      :page="repoPage"
      :page-count="repoPageCount"
      :page-size="repoPageSize"
      :page-size-options="[10, 25, 50, 0]"
      :default-size="10"
      @update:page="repoPage = $event"
      @update:page-size="onRepoPageSize"
    />
  </template>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { GitBranch, RefreshCw, FolderOpen, Plus, Search, ScanSearch } from '@lucide/vue';
import { useWorktreesStore } from '../stores/worktrees';
import { useToastsStore } from '../stores/toasts';
import { useWorktreeView } from '../composables/useWorktreeView';
import PageHeader from '../components/layout/PageHeader.vue';
import BaseButton from '../components/ui/BaseButton.vue';
import EmptyState from '../components/ui/EmptyState.vue';
import SkeletonRow from '../components/ui/SkeletonRow.vue';
import ListToolbar from '../components/ListToolbar.vue';
import Pagination from '../components/Pagination.vue';
import AttentionSection from '../components/AttentionSection.vue';
import RepoSection from '../components/RepoSection.vue';
import DirectoryPicker from '../components/DirectoryPicker.vue';

const { t } = useI18n();
const store = useWorktreesStore();
const toasts = useToastsStore();
const view = useWorktreeView();

const newPath = ref('');
const showPicker = ref(false);
const adding = ref(false);
const scanning = ref(false);
const showHidden = ref(false);

const hiddenCount = computed(() => store.repos.filter((r) => r.hidden).length);

// repos visibles : les masqués sont exclus sauf si « afficher les masqués » est coché. Triés par libellé ;
// puis masqués quand un filtre/recherche worktree actif ne laisse rien dans le repo.
const sortedRepos = computed(() =>
  [...store.repos]
    .filter((r) => showHidden.value || !r.hidden)
    .sort((a, b) => a.label.localeCompare(b.label)),
);
const visibleRepos = computed(() =>
  view.isActive()
    ? sortedRepos.value.filter((r) => view.apply(store.worktreesForRepo(r.id)).length > 0)
    : sortedRepos.value,
);

// GET /worktrees exclut les repos masqués (perf) → charger paresseusement leurs worktrees au dévoilement.
watch(showHidden, (on) => {
  if (on) for (const r of store.repos.filter((x) => x.hidden)) void store.refreshRepoWorktrees(r.id);
});

// pagination des repos (rarement nombreux → masquée par défaut).
const repoPage = ref(1);
const repoPageSize = ref(10);
const repoPageCount = computed(() =>
  repoPageSize.value === 0 ? 1 : Math.max(1, Math.ceil(visibleRepos.value.length / repoPageSize.value)),
);
const pagedRepos = computed(() => {
  if (repoPageSize.value === 0) return visibleRepos.value;
  const start = (repoPage.value - 1) * repoPageSize.value;
  return visibleRepos.value.slice(start, start + repoPageSize.value);
});
watch(repoPageCount, (count) => {
  if (repoPage.value > count) repoPage.value = count;
});

function onRepoPageSize(n: number): void {
  repoPageSize.value = n;
  repoPage.value = 1;
}

function onPickPath(path: string): void {
  newPath.value = path;
  showPicker.value = false;
}

function refresh(): void {
  void store.fetchAll();
}

async function onDiscover(): Promise<void> {
  scanning.value = true;
  try {
    const res = await store.discover();
    toasts.success(t('repos.scanResult', res.added));
  } catch (err) {
    toasts.error(err);
  } finally {
    scanning.value = false;
  }
}

async function onAddRepo(): Promise<void> {
  adding.value = true;
  try {
    await store.addRepo(newPath.value.trim());
    newPath.value = '';
    toasts.success(t('toast.repoAdded'));
  } catch (err) {
    toasts.error(err);
  } finally {
    adding.value = false;
  }
}
</script>
