import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";

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

function toPascalCase(str) {
  return str.replace(/(^\w|-\w)/g, (match) =>
    match.replace(/-/, "").toUpperCase()
  );
}

function parseAttributes(attributeString) {
  const attributes = {};
  attributeString.replace(/(\w+)=["']([^"']*)["']/g, (match, name, value) => {
    const newName = name.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
    if (newName !== "xmlns" && newName !== "hidden" && newName !== "slot") {
      attributes[newName] = value;
    }
    return match;
  });
  return attributes;
}

function parseSvgContent(svgContent) {
  const svgMatch = svgContent.match(/<svg\s+([^>]+)>([\s\S]*?)<\/svg>/);
  if (!svgMatch) return null;

  const [_, svgAttributes, svgInner] = svgMatch;
  const svgData = {
    tag: "svg",
    attr: {
      viewBox: svgAttributes.match(/viewBox="([^"]*)"/)?.[1] || "0 0 24 24",
      fill: svgAttributes.match(/fill="([^"]*)"/)?.[1] || "currentColor",
      "aria-hidden": "true",
    },
    child: parseChildren(svgInner),
  };

  return svgData;
}

function parseChildren(innerContent) {
  const children = [];
  innerContent.replace(
    /<(\w+)\s+([^>]+)>([\s\S]*?)<\/\1>/g,
    (match, tag, attributes, inner) => {
      const child = {
        tag,
        attr: parseAttributes(attributes),
        child: parseChildren(inner),
      };
      children.push(child);
      return match;
    }
  );

  innerContent.replace(/<(\w+)\s+([^>]+)\/>/g, (match, tag, attributes) => {
    const child = {
      tag,
      attr: parseAttributes(attributes),
      child: [],
    };
    children.push(child);
    return match;
  });

  return children;
}

function generateIconComponents(prefix, folderPath, outputPath) {
  const files = fs.readdirSync(folderPath);
  let outputContent = `// THIS FILE IS AUTO GENERATED\nimport { GenIcon, IconBaseProps } from '../../lib';\n\n`;

  const componentNames = [];

  files.forEach((file) => {
    if (path.extname(file) === ".svg") {
      const iconName = path.basename(file, ".svg");
      const svgContent = fs.readFileSync(path.join(folderPath, file), "utf8");
      const svgData = parseSvgContent(svgContent);
      if (svgData) {
        const componentName = `${toPascalCase(iconName)}Icon`;
        outputContent += `export const ${componentName} = (props: IconBaseProps) => GenIcon(${JSON.stringify(
          svgData
        )})(props);\n\n`;
        componentNames.push(componentName);
      }
    }
  });

  fs.mkdirSync(path.dirname(outputPath), { recursive: true });
  fs.writeFileSync(outputPath, outputContent);

  return componentNames;
}

function generateHiIconComponents(
  outlineFolderPath,
  solidFolderPath,
  outputDir
) {
  const outlineOutputPath = path.join(outputDir, "outline", "index.ts");
  const solidOutputPath = path.join(outputDir, "solid", "index.ts");

  const outlineComponents = generateIconComponents(
    "",
    outlineFolderPath,
    outlineOutputPath
  );
  const solidComponents = generateIconComponents(
    "",
    solidFolderPath,
    solidOutputPath
  );

  const combinedIndexContent = outlineComponents
    .map(
      (component) =>
        `export { ${component} as HiOutline${component.replace(
          "Icon",
          ""
        )} } from './outline';`
    )
    .concat(
      solidComponents.map(
        (component) =>
          `export { ${component} as Hi${component.replace(
            "Icon",
            ""
          )} } from './solid';`
      )
    )
    .join("\n");

  fs.writeFileSync(path.join(outputDir, "index.ts"), combinedIndexContent);
}

// Special case for Hi icons
generateHiIconComponents(
  path.join(__dirname, "..", "src", "svgs", "hi", "outline"),
  path.join(__dirname, "..", "src", "svgs", "hi", "solid"),
  path.join(__dirname, "..", "src", "hi")
);
