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

/**
 * Identifies "component files" by location + extension:
 * - `.tsx` extension
 * - Inside `packages/core-ui/src/` OR `packages/<feature>/src/ui/`
 * - NOT a test, stories, spec, or barrel file
 */
function isComponentFile(filename) {
  if (!filename.endsWith(".tsx")) return false;
  const base = path.basename(filename);
  if (
    base === "index.tsx" ||
    base.endsWith(".test.tsx") ||
    base.endsWith(".stories.tsx") ||
    base.endsWith(".spec.tsx")
  ) {
    return false;
  }
  return (
    filename.includes("/packages/core-ui/src/") ||
    /\/packages\/[^/]+\/src\/ui\//.test(filename)
  );
}

/** @type {import("eslint").Rule.RuleModule} */
export default {
  meta: {
    type: "problem",
    docs: {
      description:
        "Every component file must have a sibling *.stories.tsx for Storybook coverage.",
    },
    schema: [],
    messages: {
      missingStory:
        "Component {{filename}} has no sibling Storybook story at {{expected}}. Stories are the spec for visual conformance.",
    },
  },
  create(context) {
    return {
      Program(node) {
        const filename = context.filename;
        if (!isComponentFile(filename)) return;
        const expected = filename.replace(/\.tsx$/, ".stories.tsx");
        if (fs.existsSync(expected)) return;
        context.report({
          node,
          messageId: "missingStory",
          data: {
            filename: path.basename(filename),
            expected: path.basename(expected),
          },
        });
      },
    };
  },
};
