import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
import { dirname, join, resolve } from "node:path";

export interface ApplicationTypes {
  root: string;
  globalFile?: string;
  files: Map<string, string>;
}

function walk(dir: string, out: string[]): void {
  if (!existsSync(dir)) return;
  for (const name of readdirSync(dir)) {
    const path = join(dir, name);
    const stat = statSync(path);
    if (stat.isDirectory()) walk(path, out);
    else if (/\.(?:ts|d\.ts)$/.test(name)) out.push(path);
  }
}

export function findAppRoot(filePath: string): string {
  let current = resolve(dirname(filePath));
  while (true) {
    if (existsSync(join(current, "app"))) return current;
    const parent = dirname(current);
    if (parent === current) return resolve(dirname(filePath));
    current = parent;
  }
}

export function loadApplicationTypes(appRoot: string): ApplicationTypes {
  const typesRoot = join(appRoot, "app", "types");
  const paths: string[] = [];
  walk(typesRoot, paths);
  const files = new Map(paths.map((path) => [path, readFileSync(path, "utf8")]));
  const globalFile = join(typesRoot, "global.d.ts");
  return { root: typesRoot, ...(files.has(globalFile) ? { globalFile } : {}), files };
}
