#!/usr/bin/env node
/** Detect circular imports within src/modules/accounting. */
import { readFileSync, readdirSync, statSync } from "node:fs";
import { join, relative, sep, dirname } from "node:path";
import { fileURLToPath } from "node:url";

const ROOT = join(fileURLToPath(new URL(".", import.meta.url)), "..");
const MOD = join(ROOT, "src", "modules", "accounting");
const EXT = new Set([".ts", ".tsx"]);
const importRe = /from\s+["'](@\/src\/modules\/accounting\/[^"']+)["']/g;

function walk(dir, files = []) {
  for (const entry of readdirSync(dir)) {
    const full = join(dir, entry);
    if (statSync(full).isDirectory()) walk(full, files);
    else if (EXT.has(entry.slice(entry.lastIndexOf(".")))) files.push(full);
  }
  return files;
}

/** @type {Map<string, string[]>} */
const graph = new Map();

for (const file of walk(MOD)) {
  const rel = relative(MOD, file).split(sep).join("/").replace(/\.tsx?$/, "");
  const content = readFileSync(file, "utf8");
  const deps = [];
  let m;
  importRe.lastIndex = 0;
  while ((m = importRe.exec(content)) !== null) {
    const p = m[1].replace("@/src/modules/accounting/", "");
    deps.push(p);
  }
  graph.set(rel, deps);
}

function findCycles() {
  /** @type {string[][]} */
  const cycles = [];
  const visiting = new Set();
  const visited = new Set();
  /** @type {string[]} */
  const stack = [];

  function dfs(node) {
    if (visiting.has(node)) {
      const idx = stack.indexOf(node);
      cycles.push(stack.slice(idx).concat(node));
      return;
    }
    if (visited.has(node)) return;
    visiting.add(node);
    stack.push(node);
    for (const dep of graph.get(node) ?? []) {
      const key = dep.replace(/\/index$/, "");
      if (graph.has(key)) dfs(key);
    }
    stack.pop();
    visiting.delete(node);
    visited.add(node);
  }

  for (const node of graph.keys()) dfs(node);
  return cycles;
}

const cycles = findCycles();
console.log("Circular Dependency Check (accounting module)\n");
if (cycles.length) {
  console.error(`❌ ${cycles.length} cycle(s):`);
  for (const c of cycles) console.error(`   ${c.join(" → ")}`);
  process.exit(1);
}
console.log(`✅ No cycles in ${graph.size} accounting module files`);
process.exit(0);
