import { defineRule } from "oxlint";
import { readFileSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const __dirname = dirname(fileURLToPath(import.meta.url));
const RULE_NAME = "no-deprecated-props";

/**
 * Load deprecated props from the component registry (generated by codegen).
 * Returns a map of { ComponentName: { propName: "deprecation message" } }
 */
function loadDeprecatedProps() {
  const registryPath = resolve(__dirname, "../ai/component-registry.json");
  const registry = JSON.parse(readFileSync(registryPath, "utf-8"));

  const deprecatedMap = {};

  for (const [componentName, schema] of Object.entries(registry.components)) {
    if (!schema.props) continue;

    for (const [propName, propDef] of Object.entries(schema.props)) {
      if (propDef.deprecated) {
        if (!deprecatedMap[componentName]) {
          deprecatedMap[componentName] = {};
        }
        // deprecated can be true or a string message
        const message =
          typeof propDef.deprecated === "string"
            ? propDef.deprecated
            : "This prop is deprecated.";
        deprecatedMap[componentName][propName] = message;
      }
    }
  }

  return deprecatedMap;
}

const DEPRECATED_PROPS = loadDeprecatedProps();

/**
 * Extract component name from JSX element name node.
 * Handles both simple names (Banner) and member expressions (Checkbox.Item).
 */
function getComponentName(nameNode) {
  if (nameNode.type === "JSXIdentifier") {
    return nameNode.name;
  }
  if (nameNode.type === "JSXMemberExpression") {
    const obj =
      nameNode.object.type === "JSXIdentifier" ? nameNode.object.name : null;
    const prop =
      nameNode.property.type === "JSXIdentifier"
        ? nameNode.property.name
        : null;
    if (obj && prop) {
      return `${obj}.${prop}`;
    }
  }
  return null;
}

export const noDeprecatedPropsRule = defineRule({
  meta: {
    type: "problem",
    docs: {
      description: "Disallow deprecated props on Kumo components",
    },
    messages: {
      [RULE_NAME]:
        "The `{{prop}}` prop on <{{component}}> is deprecated. {{hint}}",
    },
    schema: [],
  },
  defaultOptions: [],
  createOnce(context) {
    return {
      JSXOpeningElement(node) {
        const componentName = getComponentName(node.name);
        if (!componentName || !DEPRECATED_PROPS[componentName]) {
          return;
        }

        const deprecatedMap = DEPRECATED_PROPS[componentName];

        for (const attr of node.attributes) {
          if (
            attr.type === "JSXAttribute" &&
            attr.name.type === "JSXIdentifier" &&
            deprecatedMap[attr.name.name]
          ) {
            context.report({
              node: attr,
              messageId: RULE_NAME,
              data: {
                prop: attr.name.name,
                component: componentName,
                hint: deprecatedMap[attr.name.name],
              },
            });
          }
        }
      },
    };
  },
});
