import fs from "node:fs";
import os from "node:os";
import path from "node:path";

const DEFAULT_INSTANCE_ID = "default";
const INSTANCE_ID_RE = /^[a-zA-Z0-9_-]+$/;
const PATH_SEGMENT_RE = /^[a-zA-Z0-9_-]+$/;
const FRIENDLY_PATH_SEGMENT_RE = /[^a-zA-Z0-9._-]+/g;

function expandHomePrefix(value: string): string {
  if (value === "~") return os.homedir();
  if (value.startsWith("~/")) return path.resolve(os.homedir(), value.slice(2));
  return value;
}

// [nexus] Read ~/.nexus pointer file for custom home directory
function resolveNexusPointerFile(): string | null {
  const pointerPath = path.resolve(os.homedir(), ".nexus");
  try {
    const raw = fs.readFileSync(pointerPath, "utf-8").trim();
    if (raw.length > 0) {
      return path.resolve(expandHomePrefix(raw));
    }
  } catch {
    // ~/.nexus does not exist or is unreadable — fall through
  }
  return null;
}

export function resolvePaperclipHomeDir(): string {
  // [nexus] Pointer-file: ~/.nexus overrides all other home resolution
  const nexusRoot = resolveNexusPointerFile();
  if (nexusRoot) return nexusRoot;

  const envHome = process.env.PAPERCLIP_HOME?.trim();
  if (envHome) return path.resolve(expandHomePrefix(envHome));
  return path.resolve(os.homedir(), ".paperclip");
}

export function resolvePaperclipInstanceId(): string {
  const raw = process.env.PAPERCLIP_INSTANCE_ID?.trim() || DEFAULT_INSTANCE_ID;
  if (!INSTANCE_ID_RE.test(raw)) {
    throw new Error(`Invalid PAPERCLIP_INSTANCE_ID '${raw}'.`);
  }
  return raw;
}

export function resolvePaperclipInstanceRoot(): string {
  return path.resolve(resolvePaperclipHomeDir(), "instances", resolvePaperclipInstanceId());
}

export function resolveDefaultConfigPath(): string {
  return path.resolve(resolvePaperclipInstanceRoot(), "config.json");
}

export function resolveDefaultEmbeddedPostgresDir(): string {
  return path.resolve(resolvePaperclipInstanceRoot(), "db");
}

export function resolveDefaultLogsDir(): string {
  return path.resolve(resolvePaperclipInstanceRoot(), "logs");
}

export function resolveDefaultSecretsKeyFilePath(): string {
  return path.resolve(resolvePaperclipInstanceRoot(), "secrets", "master.key");
}

export function resolveDefaultStorageDir(): string {
  return path.resolve(resolvePaperclipInstanceRoot(), "data", "storage");
}

export function resolveDefaultBackupDir(): string {
  return path.resolve(resolvePaperclipInstanceRoot(), "data", "backups");
}

// [nexus] Accept agent object for human-readable slugified workspace dirs
export function resolveDefaultAgentWorkspaceDir(agent: { id: string; name?: string | null }): string {
  // Use slugified name for human-readable dirs; fall back to sanitized id
  const segment = agent.name?.trim()
    ? sanitizeFriendlyPathSegment(agent.name, agent.id)
    : sanitizeFriendlyPathSegment(agent.id, agent.id);
  return path.resolve(resolvePaperclipInstanceRoot(), "workspaces", segment);
}

function sanitizeFriendlyPathSegment(value: string | null | undefined, fallback = "_default"): string {
  const trimmed = value?.trim() ?? "";
  if (!trimmed) return fallback;
  const sanitized = trimmed
    .replace(FRIENDLY_PATH_SEGMENT_RE, "-")
    .replace(/^-+|-+$/g, "");
  return sanitized || fallback;
}

export function resolveManagedProjectWorkspaceDir(input: {
  companyId: string;
  projectId: string;
  repoName?: string | null;
}): string {
  const companyId = input.companyId.trim();
  const projectId = input.projectId.trim();
  if (!companyId || !projectId) {
    throw new Error("Managed project workspace path requires companyId and projectId.");
  }
  return path.resolve(
    resolvePaperclipInstanceRoot(),
    "projects",
    sanitizeFriendlyPathSegment(companyId, "company"),
    sanitizeFriendlyPathSegment(projectId, "project"),
    sanitizeFriendlyPathSegment(input.repoName, "_default"),
  );
}

export function resolveHomeAwarePath(value: string): string {
  return path.resolve(expandHomePrefix(value));
}

// [nexus] Skill registry paths
export function resolveSkillRegistryDbPath(): string {
  return path.resolve(resolvePaperclipInstanceRoot(), "skills", "registry.db");
}

export function resolveSkillCacheDir(skillId: string, versionId: string): string {
  return path.resolve(resolvePaperclipInstanceRoot(), "skills", "cache", skillId, versionId);
}
