import { resolve } from "node:path";
import { isEmpty } from "ts-extras";
import { filenameStem, toCasing } from "../_internal/casing.js";
import { ruleCreator } from "../_internal/rule-creator.js";
const exportedNamesFromDeclaration = (node) => {
    if (node.specifiers.length > 0) {
        return node.specifiers
            .filter((specifier) => specifier.type === "ExportSpecifier")
            .flatMap((specifier) => specifier.exported.type === "Identifier"
            ? [specifier.exported.name]
            : []);
    }
    if (node.declaration?.type === "ClassDeclaration" ||
        node.declaration?.type === "FunctionDeclaration") {
        return node.declaration.id === null ? [] : [node.declaration.id.name];
    }
    return [];
};
/**
 * Enforce that exports matching the filename are the only export in the file.
 */
const rule = ruleCreator({
    create: (context, [options]) => {
        let exports = [];
        return {
            ExportDefaultDeclaration: (node) => {
                exports = [
                    ...exports,
                    {
                        name: "default",
                        node,
                    },
                ];
            },
            ExportNamedDeclaration: (node) => {
                for (const name of exportedNamesFromDeclaration(node)) {
                    exports = [...exports, { name, node }];
                }
            },
            "Program:exit": () => {
                if (context.filename === "<input>") {
                    return;
                }
                const stem = filenameStem(resolve(context.filename));
                const expected = toCasing(stem, options.format ?? "PascalCase");
                const matching = exports.filter((entry) => entry.name === expected);
                if (isEmpty(matching) || exports.length <= 1) {
                    return;
                }
                for (const entry of exports) {
                    if (entry.name === expected) {
                        continue;
                    }
                    context.report({
                        data: {
                            expected,
                        },
                        messageId: "onlyExport",
                        node: entry.node,
                    });
                }
            },
        };
    },
    defaultOptions: [{ format: "PascalCase" }],
    meta: {
        defaultOptions: [{ format: "PascalCase" }],
        deprecated: false,
        docs: {
            deprecated: false,
            description: "enforce filename-matching exports to be the only export.",
            frozen: false,
            recommended: false,
            url: "https://nick2bad4u.github.io/eslint-plugin-etc-misc/docs/rules/export-matching-filename-only",
        },
        hasSuggestions: false,
        messages: {
            onlyExport: "When exporting '{{expected}}', it must be the only export in this file.",
        },
        schema: [
            {
                additionalProperties: false,
                description: "Configuration for filename-matching export exclusivity checks.",
                properties: {
                    format: {
                        description: "Casing format used to derive expected export name from filename.",
                        enum: [
                            "camelCase",
                            "kebab-case",
                            "PascalCase",
                        ],
                        type: "string",
                    },
                },
                type: "object",
            },
        ],
        type: "suggestion",
    },
    name: "export-matching-filename-only",
});
export default rule;
//# sourceMappingURL=export-matching-filename-only.js.map