import { computed, ref } from 'vue';
import type { WorktreeSummary } from '@arboretum/shared';
import type { ListToolbarControls, SortDir } from './useListControls';
import { useDebouncedRef } from './useDebouncedRef';
import { worktreeSorts, worktreeFilters } from './listDefs';
import { useWorktreesStore } from '../stores/worktrees';

export interface WorktreeView extends ListToolbarControls<WorktreeSummary> {
  apply: (list: readonly WorktreeSummary[]) => WorktreeSummary[];
  isActive: () => boolean;
}

/**
 * État de tri/filtre/recherche des worktrees, PARTAGÉ entre toutes les RepoSection du dashboard
 * (une seule toolbar pilote toutes les sections). Singleton module-level — et non un store Pinia,
 * car Pinia déballe les refs, ce que ListToolbar attend justement comme refs. Pas de pagination
 * (liste groupée par repo) ; `apply()` filtre+trie le sous-ensemble d'un repo donné.
 */
let instance: WorktreeView | null = null;

function create(): WorktreeView {
  const search = ref('');
  const debounced = useDebouncedRef(search, 150);
  const sortKey = ref('main');
  const sortDir = ref<SortDir>('asc');
  const filters = ref<Record<string, Set<string>>>({});

  const sortDefs = worktreeSorts();
  const filterDefList = worktreeFilters();
  const filterDefs = computed(() => filterDefList);

  const accessor = (w: WorktreeSummary): string => `${w.branch ?? ''} ${w.path}`.toLowerCase();

  function apply(list: readonly WorktreeSummary[]): WorktreeSummary[] {
    let items = [...list];
    for (const def of filterDefList) {
      const active = filters.value[def.key];
      if (active && active.size > 0) items = items.filter((it) => def.predicate(it, active));
    }
    const q = debounced.value.trim().toLowerCase();
    if (q) items = items.filter((w) => accessor(w).includes(q));
    const def = sortDefs.find((s) => s.key === sortKey.value) ?? sortDefs[0];
    if (def) {
      const dir = sortDir.value === 'desc' ? -1 : 1;
      items.sort((a, b) => def.compare(a, b) * dir);
    }
    return items;
  }

  const isActive = (): boolean => debounced.value.trim() !== '' || Object.keys(filters.value).length > 0;

  // total (compteur de la toolbar) : worktrees correspondants, tous repos confondus.
  const total = computed(() => apply(useWorktreesStore().worktrees).length);
  const activeFilterCount = computed(() =>
    Object.values(filters.value).reduce((n, set) => n + set.size, 0),
  );

  function setSearch(v: string): void {
    search.value = v;
  }
  function setSort(key: string): void {
    if (sortKey.value === key) sortDir.value = sortDir.value === 'asc' ? 'desc' : 'asc';
    else {
      sortKey.value = key;
      sortDir.value = sortDefs.find((s) => s.key === key)?.defaultDir ?? 'asc';
    }
  }
  function toggleFilter(key: string, value: string): void {
    const next = { ...filters.value };
    const set = new Set(next[key] ?? []);
    if (set.has(value)) set.delete(value);
    else set.add(value);
    if (set.size === 0) delete next[key];
    else next[key] = set;
    filters.value = next;
  }
  function clearAll(): void {
    search.value = '';
    filters.value = {};
  }

  return {
    search,
    sortKey,
    sortDir,
    filters,
    total,
    activeFilterCount,
    setSearch,
    setSort,
    toggleFilter,
    clearAll,
    sortDefs,
    filterDefs,
    apply,
    isActive,
  };
}

export function useWorktreeView(): WorktreeView {
  instance ??= create();
  return instance;
}
