/**
 * src/http/session-groups.ts (W5 fan-out board) — cluster running sessions by
 * the repo they belong to, for the fan-out discovery endpoint.
 *
 * PURE + STRING-ONLY (no `git` exec, no filesystem I/O) — fully node-unit-testable.
 * Fan-out worktrees always live under `<repo>-worktrees/` (createWorktree's base,
 * worktrees.ts computeWorktreeDir), so a session whose cwd is
 * `<repo>-worktrees/<lane>` shares a group with the repo and its sibling lanes.
 * A session that is NOT under a `*-worktrees` parent groups under its own cwd.
 */

import path from 'node:path'
import type { LiveSessionInfo, SessionGroup } from '../types.js'

/** The suffix createWorktree appends to derive the worktree base dir name. */
const WORKTREES_SUFFIX = '-worktrees'

/**
 * Derive the repo root for a session cwd. If the cwd's PARENT directory is a
 * `<name>-worktrees` folder, the repo root is `<dirname-of-parent>/<name>` (strip
 * the `-worktrees` suffix). Otherwise the cwd is its own repo root. `null` in →
 * `null` out (a session with no known cwd has no repo to group under). Pure.
 */
export function deriveRepoRoot(cwd: string | null): string | null {
  if (cwd === null || cwd === '') return null
  const parent = path.dirname(cwd)
  const parentName = path.basename(parent)
  if (parentName.length > WORKTREES_SUFFIX.length && parentName.endsWith(WORKTREES_SUFFIX)) {
    const repoName = parentName.slice(0, -WORKTREES_SUFFIX.length)
    return path.join(path.dirname(parent), repoName)
  }
  return cwd
}

/**
 * Group live sessions by derived repo root. Sessions whose cwd resolves to the
 * same repo (a repo + its `*-worktrees/*` lanes) land in one SessionGroup.
 * Sessions with `cwd === null` are SKIPPED (no repo to attribute them to).
 * Group order and per-group member order both follow the input order (which
 * manager.list() already yields newest-first). Never mutates the input. Pure.
 */
export function groupSessionsByRepo(sessions: readonly LiveSessionInfo[]): SessionGroup[] {
  const byRoot = new Map<string, SessionGroup>()
  const order: string[] = []
  for (const session of sessions) {
    const repoRoot = deriveRepoRoot(session.cwd)
    if (repoRoot === null) continue // no cwd → not attributable to a repo
    let group = byRoot.get(repoRoot)
    if (group === undefined) {
      group = { repoRoot, label: path.basename(repoRoot), sessions: [] }
      byRoot.set(repoRoot, group)
      order.push(repoRoot)
    }
    group.sessions.push(session)
  }
  return order.map((root) => byRoot.get(root)!)
}
