import fs from "node:fs/promises";
import path from "node:path";

const ROOT = process.cwd();
const TARGET_DIRS = [
  path.join(ROOT, "apps", "bff", "src"),
  path.join(ROOT, "apps", "portal", "src"),
];

const FILE_EXTS = new Set([".ts", ".tsx"]);

async function* walk(dir) {
  const entries = await fs.readdir(dir, { withFileTypes: true });
  for (const e of entries) {
    const p = path.join(dir, e.name);
    if (e.isDirectory()) {
      if (e.name === "node_modules" || e.name === "dist" || e.name.startsWith(".")) continue;
      yield* walk(p);
    } else if (e.isFile()) {
      if (FILE_EXTS.has(path.extname(e.name))) yield p;
    }
  }
}

function replaceProvidersDeepImports(code) {
  // "@customer-portal/domain/<module>/providers/<anything>" -> ".../<module>/providers"
  return code
    .replaceAll(
      /from\s+"@customer-portal\/domain\/([a-z-]+)\/providers\/[^"]+"/g,
      'from "@customer-portal/domain/$1/providers"'
    )
    .replaceAll(
      /from\s+'@customer-portal\/domain\/([a-z-]+)\/providers\/[^']+'/g,
      "from '@customer-portal/domain/$1/providers'"
    );
}

function replaceCommonProviderTypes(code) {
  // Move provider response wrapper types out of common root -> common/providers
  // Only touches *type-only* imports to avoid moving runtime exports accidentally.
  return code
    .replaceAll(
      /import\s+type\s+\{([^}]*)\}\s+from\s+"@customer-portal\/domain\/common";/g,
      (m, spec) => {
        const s = String(spec);
        const needsMove =
          s.includes("WhmcsResponse") ||
          s.includes("WhmcsErrorResponse") ||
          s.includes("SalesforceResponse");
        if (!needsMove) return m;
        return `import type {${spec}} from "@customer-portal/domain/common/providers";`;
      }
    )
    .replaceAll(
      /import\s+type\s+\{([^}]*)\}\s+from\s+'@customer-portal\/domain\/common';/g,
      (m, spec) => {
        const s = String(spec);
        const needsMove =
          s.includes("WhmcsResponse") ||
          s.includes("WhmcsErrorResponse") ||
          s.includes("SalesforceResponse");
        if (!needsMove) return m;
        return `import type {${spec}} from '@customer-portal/domain/common/providers';`;
      }
    );
}

function replaceProvidersNamespaceImports(code) {
  // import { Providers } from "@customer-portal/domain/<module>";
  // import { Providers as Foo } from "@customer-portal/domain/<module>";
  return code
    .replaceAll(
      /import\s+\{\s*Providers\s*\}\s+from\s+"@customer-portal\/domain\/([a-z-]+)";/g,
      'import * as Providers from "@customer-portal/domain/$1/providers";'
    )
    .replaceAll(
      /import\s+\{\s*Providers\s+as\s+([A-Za-z_$][A-Za-z0-9_$]*)\s*\}\s+from\s+"@customer-portal\/domain\/([a-z-]+)";/g,
      'import * as $1 from "@customer-portal/domain/$2/providers";'
    )
    .replaceAll(
      /import\s+\{\s*Providers\s*\}\s+from\s+'@customer-portal\/domain\/([a-z-]+)';/g,
      "import * as Providers from '@customer-portal/domain/$1/providers';"
    )
    .replaceAll(
      /import\s+\{\s*Providers\s+as\s+([A-Za-z_$][A-Za-z0-9_$]*)\s*\}\s+from\s+'@customer-portal\/domain\/([a-z-]+)';/g,
      "import * as $1 from '@customer-portal/domain/$2/providers';"
    );
}

function replaceToolkitPaginationHelper(code) {
  if (!code.includes("@customer-portal/domain/toolkit/validation/helpers")) return code;
  let next = code;

  next = next
    .replaceAll(
      /import\s+\{\s*createPaginationSchema\s*\}\s+from\s+"@customer-portal\/domain\/toolkit\/validation\/helpers";/g,
      'import { Validation } from "@customer-portal/domain/toolkit";'
    )
    .replaceAll(
      /import\s+\{\s*createPaginationSchema\s*\}\s+from\s+'@customer-portal\/domain\/toolkit\/validation\/helpers';/g,
      "import { Validation } from '@customer-portal/domain/toolkit';"
    );

  // Update call sites
  next = next.replaceAll(/\bcreatePaginationSchema\b/g, "Validation.createPaginationSchema");

  return next;
}

function transform(code) {
  let next = code;
  next = replaceProvidersDeepImports(next);
  next = replaceCommonProviderTypes(next);
  next = replaceProvidersNamespaceImports(next);
  next = replaceToolkitPaginationHelper(next);
  return next;
}

let changedFiles = 0;
for (const dir of TARGET_DIRS) {
  for await (const file of walk(dir)) {
    const before = await fs.readFile(file, "utf8");
    const after = transform(before);
    if (after !== before) {
      await fs.writeFile(file, after, "utf8");
      changedFiles += 1;
    }
  }
}

console.log(`codemod-domain-imports: updated ${changedFiles} file(s)`);
