import fs from "fs";
import path from "path";
import { optimize } from "svgo";
import { fileURLToPath } from "url";
import { dirname } from "path";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const mapSvgAttributes = (svgContent) =>
  svgContent
    .replace(/fill-rule/g, "fillRule")
    .replace(/clip-rule/g, "clipRule");

const generateIconComponent = (
  name,
  svgContent,
  description = "",
  usage = [],
  isDeprecated = false,
  aliases = [],
  appendIconSuffix = true
) => {
  const componentName = appendIconSuffix ? `${name}Icon` : name;
  return `import * as React from 'react';

interface IconProps extends React.SVGAttributes<SVGElement> {
  children?: never;
  color?: string;
}

/**
 * @name ${componentName}
 ${aliases.length ? `* @alias ${aliases.join(", ")}` : ""}
 *
 * @description
 * ${description}
 *
 * ${isDeprecated ? "@deprecated\n * " : ""}
 * @usage
 * ${usage.map((item) => `- ${item}`).join("\n * ")}
 *
 * @accessibility
 * Asegurarse de incluir un atributo \`aria-label\` o \`aria-hidden="true"\` si el ícono es decorativo.
 *
 * @returns {JSX.Element} Componente SVG.
 */
const ${componentName} = React.forwardRef<SVGSVGElement, IconProps>(
  ({ ...props }, forwardedRef) => {
    return (
      ${mapSvgAttributes(svgContent).replace(
        "<svg",
        "<svg {...props} ref={forwardedRef}"
      )}
    );
  }
);

${componentName}.displayName = '${componentName}';

export { ${componentName} };
`;
};

const generateIndexFile = (components, outputDir, prefix = "") => {
  const exports = components
    .map(({ name }) =>
      prefix
        ? `export { ${name} as ${prefix}${name} } from "./${name}";`
        : `export { ${name} } from "./${name}";`
    )
    .join("\n");

  fs.writeFileSync(path.resolve(outputDir, "index.ts"), exports, "utf-8");
};

const processIcons = async ({
  inputDir,
  outputDir,
  prefix = "",
  iconMetadata,
  deprecatedIcons,
  appendIconSuffix = true,
}) => {
  fs.mkdirSync(outputDir, { recursive: true });

  const files = fs.readdirSync(inputDir);
  const components = await Promise.all(
    files.map(async (file) => {
      const filePath = path.resolve(inputDir, file);
      if (fs.lstatSync(filePath).isDirectory()) return null;

      const svgContent = fs.readFileSync(filePath, "utf-8");

      const { data } = await optimize(svgContent, { plugins: [] });

      const baseName = file.replace(".svg", "");
      const componentBaseName = baseName.replace(/(^\w|-\w)/g, clearAndUpper);
      const componentName = appendIconSuffix
        ? `${componentBaseName}Icon`
        : componentBaseName;
      const metadata = iconMetadata[componentBaseName] || {};
      const description = metadata.description || "";
      const usage = metadata.usage || [];
      const aliases = metadata.aliases || [];
      const isDeprecated = deprecatedIcons.includes(componentBaseName);

      const componentContent = generateIconComponent(
        componentBaseName,
        data,
        description,
        usage,
        isDeprecated,
        aliases,
        appendIconSuffix
      );

      fs.writeFileSync(
        path.resolve(outputDir, `${componentName}.tsx`),
        componentContent,
        "utf-8"
      );

      return { name: componentName, aliases };
    })
  );

  generateIndexFile(components.filter(Boolean), outputDir, prefix);
};

const clearAndUpper = (text) => text.replace(/-/, "").toUpperCase();

(async () => {
  const iconSets = [
    {
      inputDir: path.resolve(__dirname, "../src/svgs/fc"),
      outputDir: path.resolve(__dirname, "../src/fc"),
      prefix: "Fc",
      iconMetadataPath: "../jsons/IconsList/flatColorIconsList.json",
    },
    {
      inputDir: path.resolve(__dirname, "../src/svgs/fa"),
      outputDir: path.resolve(__dirname, "../src/fa"),
      prefix: "Fa",
      iconMetadataPath: "../jsons/IconsList/fontAwesomeIconsList.json",
    },
    {
      inputDir: path.resolve(__dirname, "../src/svgs/rx"),
      outputDir: path.resolve(__dirname, "../src/rx"),
      prefix: "Rx",
      iconMetadataPath: "../jsons/IconsList/radixIconsList.json",
    },
    {
      inputDir: path.resolve(__dirname, "../src/svgs/tfi"),
      outputDir: path.resolve(__dirname, "../src/tfi"),
      prefix: "Tfi",
      iconMetadataPath: "../jsons/IconsList/themifyIconsList.json",
    },
    {
      inputDir: path.resolve(__dirname, "../src/svgs/hi/solid"),
      outputDir: path.resolve(__dirname, "../src/hi/solid"),
      iconMetadataPath: "../jsons/IconsList/heroiconsList.json",
    },
    {
      inputDir: path.resolve(__dirname, "../src/svgs/hi/outline"),
      outputDir: path.resolve(__dirname, "../src/hi/outline"),
      iconMetadataPath: "../jsons/IconsList/heroiconsList.json",
      isOutline: true,
    },
  ];

  const deprecatedIcons = JSON.parse(
    fs.readFileSync(
      path.resolve(__dirname, "../jsons/IconsList/deprecated.json"),
      "utf-8"
    )
  );

  for (const { inputDir, outputDir, iconMetadataPath, prefix } of iconSets) {
    const iconMetadataFullPath = path.resolve(__dirname, iconMetadataPath);

    if (!fs.existsSync(iconMetadataFullPath)) {
      console.error(
        `Error: El archivo de metadatos no existe en ${iconMetadataFullPath}`
      );
      continue;
    }

    const iconMetadata = JSON.parse(
      fs.readFileSync(iconMetadataFullPath, "utf-8")
    );

    await processIcons({
      inputDir,
      outputDir,
      iconMetadata,
      deprecatedIcons,
      prefix,
    });
  }

  const hiSolidComponents = fs
    .readdirSync(path.resolve(__dirname, "../src/hi/solid"))
    .filter((file) => file.endsWith(".tsx"))
    .map((file) => ({ name: file.replace(".tsx", "") }));

  const hiOutlineComponents = fs
    .readdirSync(path.resolve(__dirname, "../src/hi/outline"))
    .filter((file) => file.endsWith(".tsx"))
    .map((file) => ({ name: file.replace(".tsx", "") }));

  const hiIndexExports = hiSolidComponents
    .map(({ name }) => `export { ${name} as Hi${name} } from "./solid";`)
    .concat(
      hiOutlineComponents.map(
        ({ name }) => `export { ${name} as HiOutline${name} } from "./outline";`
      )
    )
    .join("\n");

  fs.writeFileSync(
    path.resolve(__dirname, "../src/hi/index.ts"),
    hiIndexExports,
    "utf-8"
  );
})();
