// Types REST partagés (préfixe /api/v1).
import type { GroupSummary, PostCreateHook, RepoSummary, SessionSummary, WorktreeSummary } from './protocol.js';

export interface ApiError {
  error: { code: string; message: string; details?: unknown };
}

export interface LoginRequest {
  token: string;
}
export interface LoginResponse {
  ok: true;
  label: string;
}
export interface MeResponse {
  ok: true;
  /** id du token de la session courante — sert à marquer « courant » dans la liste des tokens. */
  tokenId: string;
  tokenLabel: string;
  serverVersion: string;
}

// ---- Gestion des tokens d'accès (onglet Réglages) ----
export interface TokenInfo {
  id: string;
  label: string;
  createdAt: string;
  lastUsedAt: string | null;
  /** true pour le token de la session courante. */
  current: boolean;
}
export interface TokensListResponse {
  tokens: TokenInfo[];
}
export interface CreateTokenRequest {
  label: string;
}
export interface CreateTokenResponse {
  id: string;
  label: string;
  /** valeur en clair — affichée une seule fois, jamais re-récupérable. */
  token: string;
}

export interface CreateSessionRequest {
  cwd: string;
  /** binaire à lancer — défaut "claude" ; "bash" sert aux tests d'acceptation sans quota */
  command?: 'claude' | 'bash';
}
export interface SessionsListResponse {
  sessions: SessionSummary[];
}
export interface SessionResponse {
  session: SessionSummary;
}

// POST /sessions/:id/resume et /sessions/:id/fork (P2) : aucun corps — cwd et command
// sont TOUJOURS dérivés du :id (lu sur disque), jamais fournis par le client (cf. spike S1).
export type ResumeSessionRequest = Record<string, never>;
export type ForkSessionRequest = Record<string, never>;

// ---- Repos & worktrees (P3) ----
export interface ReposListResponse {
  repos: RepoSummary[];
}
export interface RepoResponse {
  repo: RepoSummary;
}
export interface CreateRepoRequest {
  path: string;
  label?: string;
  postCreateHooks?: PostCreateHook[];
  preTrust?: boolean;
}
export interface UpdateRepoRequest {
  label?: string;
  postCreateHooks?: PostCreateHook[];
  preTrust?: boolean;
  /** true = masquer le repo (exclu du dashboard, conservé en DB) ; false = ré-afficher. */
  hidden?: boolean;
}

/** Résultat d'un scan de découverte (POST /api/v1/repos/discover). */
export interface DiscoverReposResponse {
  /** dossiers-repos trouvés sur disque. */
  scanned: number;
  /** repos réellement insérés (nouveaux, non déjà enregistrés). */
  added: number;
  durationMs: number;
  /** true si la limite (maxRepos / timeout) a été atteinte avant la fin du scan. */
  truncated: boolean;
}

export interface WorktreesListResponse {
  worktrees: WorktreeSummary[];
}
export interface WorktreeResponse {
  worktree: WorktreeSummary;
}
export interface HookRunResult {
  hookId: string;
  label: string;
  exitCode: number | null;
  output: string;
  durationMs: number;
}
export interface CreateWorktreeRequest {
  branch: string;
  /** true : créer la branche (`-b`) ; false : checkout d'une branche existante. */
  newBranch: boolean;
  /** point de départ de la nouvelle branche (défaut : HEAD courant du repo). */
  baseRef?: string;
  /** chemin cible du worktree (défaut : `<parent>/<repo>-wt-<branch>`). */
  path?: string;
  runHooks?: boolean;
  preTrust?: boolean;
  /** lancer une session dans le worktree créé (défaut : aucune). */
  startSession?: 'claude' | 'bash' | null;
}
export interface CreateWorktreeResponse {
  worktree: WorktreeSummary;
  hookResults: HookRunResult[];
  session: SessionSummary | null;
}
export interface AdoptWorktreeRequest {
  path: string;
  runHooks?: boolean;
  preTrust?: boolean;
}

// ---- Groupes de travail (P5) ----
export interface GroupsListResponse {
  groups: GroupSummary[];
}
export interface GroupResponse {
  group: GroupSummary;
}
export interface CreateGroupRequest {
  label: string;
  description?: string;
  color?: string;
  /** ids de repos initiaux (défaut : []). */
  repoIds?: string[];
}
export interface UpdateGroupRequest {
  label?: string;
  /** null pour effacer. */
  description?: string | null;
  color?: string | null;
}
export interface AddRepoRequest {
  repoId: string;
}

// ---- Navigateur de répertoires (sélecteur de dossier côté web) ----
export interface FsEntry {
  name: string;
  /** chemin absolu du dossier */
  path: string;
  /** présent (true) uniquement en mode markRepos quand le dossier est un dépôt git */
  isRepo?: boolean;
}
export interface FsListResponse {
  /** chemin absolu listé (normalisé) */
  path: string;
  /** parent (null à la racine `/`) — pour le bouton « remonter » */
  parent: string | null;
  /** home de l'utilisateur côté serveur — point de départ par défaut */
  home: string;
  /** sous-dossiers uniquement, triés sans tenir compte de la casse */
  entries: FsEntry[];
}

// ---- Web Push (P4) ----
export interface VapidKeyResponse {
  /** clé publique VAPID (applicationServerKey côté navigateur). */
  key: string;
}
export interface PushSubscribeRequest {
  endpoint: string;
  keys: { p256dh: string; auth: string };
}
export interface PushUnsubscribeRequest {
  endpoint: string;
}

// ---- Réglages & info serveur (onglet Réglages) ----
/** Config runtime non sensible du daemon — lecture seule (changée via flags CLI + redémarrage). */
export interface ServerInfo {
  version: string;
  port: number;
  bind: string;
  allowedOrigins: string[];
  dataDir: string;
  /** clé publique VAPID (sûre à exposer) ; null si push indisponible. */
  vapidPublicKey: string | null;
  vapidContact: string;
}
export interface SettingsResponse {
  /** réglages modifiables à chaud (allow-list serveur — jamais les secrets). */
  settings: {
    /** racines absolues scannées pour la découverte auto des repos (défaut : aucune → pas de scan). */
    scanRoots: string[];
    /** intervalle du re-scan périodique en minutes ; 0 = périodique désactivé. */
    scanIntervalMin: number;
  };
  server: ServerInfo;
}
export interface UpdateSettingsRequest {
  /** racines absolues à scanner (chemins normalisés, ≤ 16) ; remplace la liste. */
  scanRoots?: string[];
  /** intervalle du re-scan périodique en minutes (0–1440 ; 0 désactive). */
  scanIntervalMin?: number;
}

// ---- Journal d'audit (conformité entreprise) ----
export interface AuditLogEntry {
  id: string;
  /** horodatage ISO 8601 */
  ts: string;
  /** tokenId de l'acteur, 'system' (auto) ou 'anonymous' (avant auth) */
  actor: string;
  /** verbe.objet, ex. 'token.create', 'settings.update' */
  action: string;
  resourceId: string | null;
  /** métadonnées non sensibles (jamais de secret) */
  details: unknown;
  result: string;
}
export interface AuditLogsResponse {
  entries: AuditLogEntry[];
  /** curseur de pagination (ts à passer en `before`) ; null si fin de liste. */
  nextBefore: string | null;
}

// ---- RGPD : export / suppression des données liées au token authentifié ----
export interface DataExportResponse {
  exportedAt: string;
  tokens: Array<{ id: string; label: string; createdAt: string; lastUsedAt: string | null; current: boolean }>;
  pushSubscriptions: Array<{ endpoint: string; userAgent: string | null; createdAt: string; lastOkAt: string | null }>;
  sessions: Array<{ id: string; cwd: string; command: string; title: string | null; createdAt: string; endedAt: string | null; exitCode: number | null }>;
  settings: { scanRoots: string[]; scanIntervalMin: number };
}
export interface DeleteMyDataRequest {
  /** code de confirmation renvoyé par un premier appel sans `confirm` ; doit être renvoyé pour exécuter. */
  confirm?: string;
}
export interface DeleteMyDataResponse {
  /** 'pending' = confirmation requise (renvoie `confirm`) ; 'done' = suppression effectuée. */
  status: 'pending' | 'done';
  confirm?: string;
  /** récapitulatif de ce qui sera/a été supprimé. */
  summary: { pushSubscriptions: number; tokenRevoked: boolean };
}
