import type { GroupSummary, RepoSummary, SessionSummary, WorktreeSummary } from '@arboretum/shared';
import type { FilterDef, SortDef } from './useListControls';

// ---- état canonique d'une session (réutilise la logique de SessionStateBadge) ----
type CanonState = 'waiting' | 'busy' | 'idle' | null;
const canonState = (s: SessionSummary): CanonState => (s.activity ?? s.registryStatus ?? null);

/** Rang d'actionnabilité : waiting(0) < busy(1) < idle(2) < live(3) < resumable(4) < exited(5). */
export function sessionStateRank(s: SessionSummary): number {
  if (s.live) {
    const st = canonState(s);
    return st === 'waiting' ? 0 : st === 'busy' ? 1 : st === 'idle' ? 2 : 3;
  }
  return s.resumable ? 4 : 5;
}

/** Une session correspond-elle à une valeur d'état de filtre ? */
function sessionMatchesState(s: SessionSummary, value: string): boolean {
  switch (value) {
    case 'live':
      return s.live;
    case 'waiting':
    case 'busy':
    case 'idle':
      return s.live && canonState(s) === value;
    case 'exited':
      return !s.live && !s.resumable;
    case 'resumable':
      return !s.live && s.resumable;
    default:
      return false;
  }
}

// ---- sessions ----
export function sessionSorts(): SortDef<SessionSummary>[] {
  return [
    { key: 'state', labelKey: 'sort.session.state', compare: (a, b) => sessionStateRank(a) - sessionStateRank(b), defaultDir: 'asc' },
    { key: 'recent', labelKey: 'sort.session.recent', compare: (a, b) => a.createdAt.localeCompare(b.createdAt), defaultDir: 'desc' },
    { key: 'clients', labelKey: 'sort.session.clients', compare: (a, b) => a.clients - b.clients, defaultDir: 'desc' },
    { key: 'cwd', labelKey: 'sort.session.cwd', compare: (a, b) => a.cwd.localeCompare(b.cwd), defaultDir: 'asc' },
    { key: 'command', labelKey: 'sort.session.command', compare: (a, b) => a.command.localeCompare(b.command), defaultDir: 'asc' },
  ];
}

export function sessionFilters(repos: readonly RepoSummary[]): FilterDef<SessionSummary>[] {
  const STATES = ['live', 'waiting', 'busy', 'idle', 'exited', 'resumable'];
  // corrélation session→repo par préfixe de chemin (cwd sous repo.path).
  const repoPaths = repos.map((r) => ({ id: r.id, path: r.path }));
  return [
    {
      key: 'state',
      labelKey: 'filter.state.label',
      options: STATES.map((v) => ({ value: v, labelKey: `filter.state.${v}` })),
      predicate: (s, active) => [...active].some((v) => sessionMatchesState(s, v)),
    },
    {
      key: 'command',
      labelKey: 'filter.command.label',
      options: [
        { value: 'claude', label: 'claude' },
        { value: 'bash', label: 'bash' },
      ],
      predicate: (s, active) => active.has(s.command),
    },
    {
      key: 'source',
      labelKey: 'filter.source.label',
      options: [
        { value: 'managed', labelKey: 'filter.source.managed' },
        { value: 'discovered', labelKey: 'filter.source.discovered' },
      ],
      predicate: (s, active) => active.has(s.source),
    },
    {
      key: 'repo',
      labelKey: 'filter.repo.label',
      options: repos.map((r) => ({ value: r.id, label: r.label })),
      predicate: (s, active) =>
        repoPaths.some((r) => active.has(r.id) && (s.cwd === r.path || s.cwd.startsWith(r.path + '/'))),
    },
  ];
}

// ---- worktrees ----
function worktreeActivityRank(w: WorktreeSummary): number {
  if (w.sessions.length === 0) return 99;
  return Math.min(...w.sessions.map(sessionStateRank));
}

export function worktreeSorts(): SortDef<WorktreeSummary>[] {
  return [
    { key: 'main', labelKey: 'sort.worktree.main', compare: (a, b) => Number(b.isMain) - Number(a.isMain), defaultDir: 'asc' },
    { key: 'branch', labelKey: 'sort.worktree.branch', compare: (a, b) => (a.branch ?? '').localeCompare(b.branch ?? ''), defaultDir: 'asc' },
    { key: 'dirty', labelKey: 'sort.worktree.dirty', compare: (a, b) => a.git.dirtyCount - b.git.dirtyCount, defaultDir: 'desc' },
    { key: 'ahead', labelKey: 'sort.worktree.ahead', compare: (a, b) => a.git.ahead - b.git.ahead, defaultDir: 'desc' },
    { key: 'behind', labelKey: 'sort.worktree.behind', compare: (a, b) => a.git.behind - b.git.behind, defaultDir: 'desc' },
    { key: 'activity', labelKey: 'sort.worktree.activity', compare: (a, b) => worktreeActivityRank(a) - worktreeActivityRank(b), defaultDir: 'asc' },
  ];
}

export function worktreeFilters(): FilterDef<WorktreeSummary>[] {
  return [
    {
      key: 'dirtiness',
      labelKey: 'filter.worktree.dirtiness',
      options: [
        { value: 'dirty', labelKey: 'filter.worktree.dirty' },
        { value: 'clean', labelKey: 'filter.worktree.clean' },
      ],
      predicate: (w, active) =>
        (active.has('dirty') && w.git.dirtyCount > 0) || (active.has('clean') && w.git.dirtyCount === 0),
    },
    {
      key: 'session',
      labelKey: 'filter.worktree.session',
      options: [
        { value: 'with', labelKey: 'filter.worktree.with' },
        { value: 'without', labelKey: 'filter.worktree.without' },
      ],
      predicate: (w, active) =>
        (active.has('with') && w.sessions.length > 0) || (active.has('without') && w.sessions.length === 0),
    },
    {
      key: 'flags',
      labelKey: 'filter.worktree.flags',
      options: [
        { value: 'locked', labelKey: 'filter.worktree.locked' },
        { value: 'prunable', labelKey: 'filter.worktree.prunable' },
      ],
      predicate: (w, active) => (active.has('locked') && w.locked) || (active.has('prunable') && w.prunable),
    },
  ];
}

// ---- repos ----
export interface RepoSortCtx {
  worktreeCount: (repoId: string) => number;
  activeCount: (repoId: string) => number;
}
export function repoSorts(ctx: RepoSortCtx): SortDef<RepoSummary>[] {
  return [
    { key: 'label', labelKey: 'sort.repo.label', compare: (a, b) => a.label.localeCompare(b.label), defaultDir: 'asc' },
    { key: 'created', labelKey: 'sort.repo.created', compare: (a, b) => a.createdAt.localeCompare(b.createdAt), defaultDir: 'desc' },
    { key: 'worktrees', labelKey: 'sort.repo.worktrees', compare: (a, b) => ctx.worktreeCount(a.id) - ctx.worktreeCount(b.id), defaultDir: 'desc' },
    { key: 'activity', labelKey: 'sort.repo.activity', compare: (a, b) => ctx.activeCount(a.id) - ctx.activeCount(b.id), defaultDir: 'desc' },
  ];
}

// ---- groupes ----
export interface GroupSortCtx {
  activeCount: (groupId: string) => number;
}
export function groupSorts(ctx: GroupSortCtx): SortDef<GroupSummary>[] {
  return [
    { key: 'label', labelKey: 'sort.group.label', compare: (a, b) => a.label.localeCompare(b.label), defaultDir: 'asc' },
    { key: 'created', labelKey: 'sort.group.created', compare: (a, b) => a.createdAt.localeCompare(b.createdAt), defaultDir: 'desc' },
    { key: 'repos', labelKey: 'sort.group.repos', compare: (a, b) => a.repoIds.length - b.repoIds.length, defaultDir: 'desc' },
    { key: 'activeSessions', labelKey: 'sort.group.activeSessions', compare: (a, b) => ctx.activeCount(a.id) - ctx.activeCount(b.id), defaultDir: 'desc' },
  ];
}
