import { existsSync } from "node:fs";
import { homedir } from "node:os";
import { resolve } from "node:path";
import { ValidationError } from "./errors.js";

export type AnalyticsSource = "codex" | "copilot" | "claude" | "hook_log";
export type ClientSurface = "cli" | "desktop" | "vscode" | "vscode_insiders" | "code" | "unknown";

export const ALL_SOURCES: readonly AnalyticsSource[] = ["codex", "copilot", "claude", "hook_log"];
export const DEFAULT_SCAN_SOURCES: readonly AnalyticsSource[] = ["codex", "copilot", "hook_log"];
export const SESSION_SOURCES: readonly AnalyticsSource[] = ["codex", "copilot", "claude"];

export function parseSources(value: unknown): AnalyticsSource[] | undefined {
  if (value === undefined) return undefined;
  if (!Array.isArray(value)) throw new ValidationError("sources must be an array.");
  const out: AnalyticsSource[] = [];
  const seen = new Set<string>();
  for (const entry of value) {
    if (typeof entry !== "string" || !ALL_SOURCES.includes(entry as AnalyticsSource)) {
      throw new ValidationError("sources contains unsupported values.");
    }
    if (!seen.has(entry)) {
      seen.add(entry);
      out.push(entry as AnalyticsSource);
    }
  }
  return out;
}

export function resolveCodexRoots(): string[] {
  return [resolve(homedir(), ".codex", "sessions"), resolve(homedir(), ".codex", "archived_sessions")];
}

export function resolveCopilotRoots(): string[] {
  if (process.platform === "win32") {
    const appData = process.env.APPDATA ?? resolve(homedir(), "AppData", "Roaming");
    return [
      resolve(appData, "Code", "User", "globalStorage"),
      resolve(appData, "Code", "User", "workspaceStorage"),
      resolve(appData, "Code - Insiders", "User", "globalStorage"),
      resolve(appData, "Code - Insiders", "User", "workspaceStorage")
    ];
  }
  return [
    resolve(homedir(), ".config", "Code", "User", "globalStorage"),
    resolve(homedir(), ".config", "Code", "User", "workspaceStorage"),
    resolve(homedir(), ".config", "Code - Insiders", "User", "globalStorage"),
    resolve(homedir(), ".config", "Code - Insiders", "User", "workspaceStorage")
  ];
}

export function resolveClaudeRoots(): string[] {
  if (process.platform === "win32") {
    const appData = process.env.APPDATA ?? resolve(homedir(), "AppData", "Roaming");
    return [resolve(homedir(), ".claude", "projects"), resolve(homedir(), ".claude"), resolve(appData, "Claude")];
  }
  return [resolve(homedir(), ".claude", "projects"), resolve(homedir(), ".claude"), resolve(homedir(), ".config", "Claude")];
}

export function resolveSourceRoots(source: AnalyticsSource, hookLogPath: string): string[] {
  switch (source) {
    case "codex":
      return resolveCodexRoots();
    case "copilot":
      return resolveCopilotRoots();
    case "claude":
      return resolveClaudeRoots();
    case "hook_log":
      return [hookLogPath];
  }
}

export function sourceExists(source: AnalyticsSource, hookLogPath: string): boolean {
  const roots = resolveSourceRoots(source, hookLogPath);
  return roots.some((entry) => existsSync(entry));
}
