import fs from "node:fs";
import path from "node:path";
import { readManifestSource } from "./_manifest-source.js";
import { readWorkspacePackages } from "./_workspace.js";

/**
 * Check whether `packages/core-<name>` exists under any of the workspace
 * globs. The glob set is small and predictable (e.g. ["apps/*", "packages/*"]);
 * we simulate matching by checking each glob's directory portion + verifying
 * `core-<name>` exists in that directory.
 */
function coreExistsInWorkspace(coreName, repoRoot, packageGlobs) {
  for (const glob of packageGlobs) {
    const slashStar = glob.endsWith("/*") ? glob.slice(0, -2) : null;
    if (!slashStar) continue;
    const candidate = path.join(repoRoot, slashStar, `core-${coreName}`);
    if (fs.existsSync(candidate)) return true;
  }
  return false;
}

/** @type {import("eslint").Rule.RuleModule} */
export default {
  meta: {
    type: "problem",
    docs: {
      description:
        "Cores declared in a feature.manifest.ts's requiredCores must exist as core-<name> packages within a workspace glob.",
    },
    schema: [
      {
        type: "object",
        properties: {
          repoRoot: { type: "string" },
        },
        additionalProperties: false,
      },
    ],
    messages: {
      coreNotInstalled:
        "Manifest declares requiredCores: [..., \"{{core}}\", ...] but `core-{{core}}` is not present in any workspace glob. Run `pnpm turbo gen core-package {{core}}` or drop the entry.",
    },
  },
  create(context) {
    const opts = context.options[0] ?? {};
    const repoRoot = opts.repoRoot ?? context.cwd ?? process.cwd();
    return {
      Program(node) {
        const filename = context.filename;
        if (!filename.endsWith("/feature.manifest.ts") && !filename.endsWith("\\feature.manifest.ts")) {
          return;
        }
        const manifest = readManifestSource(filename);
        if (!manifest) return;
        const globs = readWorkspacePackages(repoRoot);
        for (const core of manifest.requiredCores) {
          if (!coreExistsInWorkspace(core, repoRoot, globs)) {
            context.report({
              node,
              messageId: "coreNotInstalled",
              data: { core },
            });
          }
        }
      },
    };
  },
};
