import console from "node:console";
import { execFileSync } from "node:child_process";
import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import process from "node:process";

const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const dryRun = process.argv.includes("--check");
const removed = [];
const untracked = [];
const warnings = [];

function removeLocal(path) {
  const absolute = join(root, path);
  if (!existsSync(absolute)) return;
  if (!dryRun) unlinkSync(absolute);
  removed.push(path);
}

function git(args, capture = false) {
  return execFileSync("git", args, {
    cwd: root,
    encoding: "utf8",
    stdio: capture ? ["ignore", "pipe", "pipe"] : ["ignore", "ignore", "pipe"],
  });
}

function isGitRepository() {
  try {
    return git(["rev-parse", "--is-inside-work-tree"], true).trim() === "true";
  } catch {
    return false;
  }
}

function trackedFiles() {
  try {
    return git(["ls-files", "-z"], true).split("\0").filter(Boolean);
  } catch {
    return [];
  }
}

function ensureIgnoreRules() {
  const path = join(root, ".gitignore");
  const current = existsSync(path) ? readFileSync(path, "utf8") : "";
  const required = [
    ".env",
    ".env.*",
    "!.env.example",
    "!.env.*.example",
    "focus-shims.d.ts",
    "tsconfig.focus.json",
  ];
  const lines = new Set(current.split(/\r?\n/).map((line) => line.trim()));
  const missing = required.filter((line) => !lines.has(line));
  if (missing.length === 0) return;
  if (!dryRun) {
    const separator = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
    writeFileSync(path, `${current}${separator}${missing.join("\n")}\n`);
  }
  warnings.push(`Added missing .gitignore rules: ${missing.join(", ")}`);
}

removeLocal("focus-shims.d.ts");
removeLocal("tsconfig.focus.json");
ensureIgnoreRules();

if (isGitRepository()) {
  const secretPattern = /(?:^|\/)(?:\.env(?:\..+)?|id_rsa|id_ed25519|.*\.(?:pem|p12|pfx|key))$/i;
  const safeTemplate = /(?:^|\/)\.env(?:\.[^/]+)*\.(?:example|sample|template)$/i;
  const temporaryPattern = /(?:^|\/)(?:focus-shims\.d\.ts|tsconfig\.focus\.json)$/i;
  const unsafeTracked = trackedFiles().filter(
    (path) => temporaryPattern.test(path) || (secretPattern.test(path) && !safeTemplate.test(path)),
  );
  for (const path of unsafeTracked) {
    if (!dryRun) git(["rm", "--cached", "--ignore-unmatch", "--", path]);
    untracked.push(path);
  }
} else {
  warnings.push(
    "Git metadata was not found, so tracked secret files could not be removed from the Git index.",
  );
}

console.log(dryRun ? "Workspace repair check:" : "Workspace repaired:");
console.log(
  `- ${dryRun ? "would remove" : "removed"} temporary files: ${removed.length ? removed.join(", ") : "none"}`,
);
console.log(
  `- ${dryRun ? "would remove" : "removed"} from Git tracking: ${untracked.length ? untracked.join(", ") : "none"}`,
);
for (const warning of warnings) console.warn(`- warning: ${warning}`);

if (dryRun && (removed.length > 0 || untracked.length > 0)) {
  console.error("Workspace repair is required. Run: bun run repair:workspace");
  process.exitCode = 1;
}
