/**
 * Builds icon font with Figma names directly (no remapping needed)
 * Handles icon variants for one-to-many mappings
 */

import { execSync } from "child_process";
import * as fs from "fs";
import * as path from "path";

import { BWI_TO_FIGMA, FIGMA_VARIANTS } from "./migration-map";

const ICONS_DIR = path.join(__dirname, "../../libs/assets/src/material-icons");
const SCSS_PATH = path.join(__dirname, "../../libs/angular/src/scss/bwicons/styles/style.scss");
const CSS_PATH = path.join(__dirname, "../../libs/angular/src/scss/bwicons/styles/style.css");
const ICON_TS_PATH = path.join(__dirname, "../../libs/components/src/shared/icon.ts");

function buildIconFont(): void {
  const variantFiles: string[] = [];

  try {
    // Step 1: Handle variants (copy files for one-to-many mappings)
    for (const [figmaName, variants] of Object.entries(FIGMA_VARIANTS)) {
      const sourcePath = path.join(ICONS_DIR, `${figmaName}.svg`);

      for (const variantName of variants) {
        const targetPath = path.join(ICONS_DIR, `${variantName}.svg`);

        if (fs.existsSync(sourcePath)) {
          fs.copyFileSync(sourcePath, targetPath);
          variantFiles.push(targetPath);
          // eslint-disable-next-line no-console
          console.log(`Created variant: ${variantName}.svg from ${figmaName}.svg`);
        }
      }
    }

    // Step 2: Generate icon font directly from Figma-named SVGs
    // eslint-disable-next-line no-console
    console.log("\nGenerating icon font...");
    execSync(
      'fantasticon libs/assets/src/material-icons -o libs/angular/src/scss/bwicons/fonts -t woff2 woff ttf svg -n bwi-font --selector ".bwi-%s" --normalize -h 1024 --descent 128',
      { stdio: "inherit" },
    );

    // Step 3: Update SCSS
    // eslint-disable-next-line no-console
    console.log("\nUpdating SCSS...");
    const jsonPath = path.join(
      __dirname,
      "../../libs/angular/src/scss/bwicons/fonts/bwi-font.json",
    );
    const glyphMap: Record<string, number> = JSON.parse(fs.readFileSync(jsonPath, "utf-8"));

    const entries = Object.entries(glyphMap)
      .sort((a, b) => a[0].localeCompare(b[0]))
      .map(([name, code]) => {
        const hex = code.toString(16);
        return `  "${name}": "\\${hex}"`;
      });

    // Create reverse mapping: Figma → [legacy names]
    const reverseMap: Record<string, string[]> = {};
    for (const [legacy, figma] of Object.entries(BWI_TO_FIGMA)) {
      if (legacy !== figma) {
        // Skip identity mappings
        if (!reverseMap[figma]) {
          reverseMap[figma] = [];
        }
        reverseMap[figma].push(legacy);
      }
    }

    // Generate legacy alias entries for SCSS
    const legacyEntries = Object.entries(reverseMap)
      .flatMap(([figma, legacyNames]) => {
        const glyph = glyphMap[figma];
        if (!glyph) {
          return [];
        } // Skip if Figma name not in glyphMap
        return legacyNames
          .filter((legacy) => !glyphMap[legacy]) // skip if name is already a Figma icon
          .map((legacy) => ({ legacy, glyph }));
      })
      .sort((a, b) => a.legacy.localeCompare(b.legacy))
      .map(({ legacy, glyph }) => {
        const hex = glyph.toString(16);
        return `  "${legacy}": "\\${hex}"`;
      });

    const iconCount = entries.length + legacyEntries.length;
    const iconsMapContent = `// Auto-generated - do not edit manually
// Bidirectional icon name support (both Figma and legacy BWI names)
$icons: (
${entries.join(",\n")}${legacyEntries.length > 0 ? ",\n" + legacyEntries.join(",\n") : ""}
);`;

    let scssContent = fs.readFileSync(SCSS_PATH, "utf-8");

    // Replace the $icons map - matches the pattern with or without comments
    const iconsMapRegex = /(?:\/\/[^\n]*\n)*\$icons: \([\s\S]*?\);/;
    scssContent = scssContent.replace(iconsMapRegex, iconsMapContent);

    fs.writeFileSync(SCSS_PATH, scssContent, "utf-8");

    // Step 4: Compile SCSS to CSS
    // eslint-disable-next-line no-console
    console.log("\nCompiling SCSS to CSS...");
    execSync(`npx sass ${SCSS_PATH} ${CSS_PATH} --no-source-map`, { stdio: "inherit" });

    // Step 5: Update TypeScript icon array
    // eslint-disable-next-line no-console
    console.log("\nUpdating TypeScript icon array...");

    // Flatten all legacy names
    const allLegacyNames = Object.values(reverseMap).flat();

    // Combine Figma + legacy names
    const allIconNames = [...Object.keys(glyphMap), ...allLegacyNames]
      .sort((a, b) => a.localeCompare(b))
      .map((name) => `  "bwi-${name}"`);

    const iconTsContent = `/**
 * Array of available Bitwarden Web Icons (bwi) font names.
 * Includes both Figma names and legacy BWI names for bidirectional compatibility.
 * This allows both old and new icon names to work seamlessly.
 * Auto-generated by icons:build script - do not edit manually.
 */
export const BITWARDEN_ICONS = [
${allIconNames.join(",\n")},
] as const;

/**
 * Type-safe icon names derived from the BITWARDEN_ICONS array.
 * This ensures type safety while allowing runtime iteration and validation.
 */
export type BitwardenIcon = (typeof BITWARDEN_ICONS)[number];
`;

    fs.writeFileSync(ICON_TS_PATH, iconTsContent, "utf-8");

    // Step 6: Cleanup temporary files
    // eslint-disable-next-line no-console
    console.log("\nCleaning up...");
    execSync("rm -f libs/angular/src/scss/bwicons/fonts/bwi-font.{css,html,json,ts}", {
      stdio: "inherit",
    });

    // eslint-disable-next-line no-console
    console.log("\n✓ Icon font build complete!");
    // eslint-disable-next-line no-console
    console.log(`  Generated ${iconCount} icons with Figma names`);
    // eslint-disable-next-line no-console
    console.log(`  Updated icon.ts with ${iconCount} icons`);
  } finally {
    // Step 7: Remove variant copies
    for (const variantFile of variantFiles) {
      if (fs.existsSync(variantFile)) {
        fs.unlinkSync(variantFile);
      }
    }
  }
}

buildIconFont();
