/**
 * CSS Generator for Kumo Themes
 *
 * Generates theme CSS files from the centralized config.
 * Outputs:
 * - theme-kumo.css: Base theme with all tokens
 * - theme-fedramp.css: Override layer for fedramp theme
 * - (future themes as needed)
 */

import { THEME_CONFIG, AVAILABLE_THEMES } from "./config.js";
import type { ThemeConfig, GeneratorOptions, TokenRenameMap } from "./types.js";

/**
 * Header comment for generated CSS files
 */
const GENERATED_FILE_HEADER = `/**
 * AUTO-GENERATED FILE - DO NOT EDIT DIRECTLY
 *
 * This file is generated by the theme generator.
 * To modify tokens, edit: scripts/theme-generator/config.ts
 * Then run: pnpm codegen:themes
 */

`;

/**
 * Generate a light-dark() CSS function call
 */
function lightDark(light: string, dark: string): string {
  return `light-dark(\n    ${light},\n    ${dark}\n  )`;
}

/**
 * Generate the base kumo theme CSS
 * This contains all tokens with their kumo theme values
 */
export function generateKumoThemeCSS(
  config: ThemeConfig,
  useNewNames = false,
): string {
  const lines: string[] = [GENERATED_FILE_HEADER];

  // Text color tokens
  lines.push("@theme {");

  for (const [tokenName, def] of Object.entries(config.text)) {
    const name = useNewNames ? def.newName : tokenName;
    const kumoColors = def.theme.kumo;

    lines.push(
      `  --text-color-${name}: ${lightDark(kumoColors.light, kumoColors.dark)};`,
    );
    lines.push("");
  }

  lines.push("}");
  lines.push("");

  // Color tokens (bg, border, ring, etc.)
  lines.push("@theme {");

  for (const [tokenName, def] of Object.entries(config.color)) {
    const name = useNewNames ? def.newName : tokenName;
    const kumoColors = def.theme.kumo;

    lines.push(
      `  --color-${name}: ${lightDark(kumoColors.light, kumoColors.dark)};`,
    );
    lines.push("");
  }

  lines.push("}");

  // Typography tokens (font sizes and line heights)
  if (config.typography && Object.keys(config.typography).length > 0) {
    lines.push("");
    lines.push("@theme {");
    lines.push("  /* Typography - text sizes and line heights */");

    for (const [tokenName, def] of Object.entries(config.typography)) {
      const name = useNewNames && def.newName ? def.newName : tokenName;
      const value = def.theme.kumo;

      lines.push(`  --text-${name}: ${value};`);
    }

    lines.push("}");
  }

  return lines.join("\n");
}

/**
 * Generate a theme override CSS file
 * Only includes tokens that differ from the base kumo theme
 */
export function generateThemeOverrideCSS(
  config: ThemeConfig,
  themeName: string,
  useNewNames = false,
): string {
  if (themeName === "kumo") {
    throw new Error("Use generateKumoThemeCSS for the base kumo theme");
  }

  const overrides: string[] = [];

  // Collect text token overrides
  for (const [tokenName, def] of Object.entries(config.text)) {
    const themeColors = def.theme[themeName];
    if (themeColors) {
      const name = useNewNames ? def.newName : tokenName;
      overrides.push(
        `    --text-color-${name}: ${lightDark(themeColors.light, themeColors.dark)};`,
      );
    }
  }

  // Collect color token overrides
  for (const [tokenName, def] of Object.entries(config.color)) {
    const themeColors = def.theme[themeName];
    if (themeColors) {
      const name = useNewNames ? def.newName : tokenName;
      overrides.push(
        `    --color-${name}: ${lightDark(themeColors.light, themeColors.dark)};`,
      );
    }
  }

  // Collect typography token overrides
  if (config.typography) {
    for (const [tokenName, def] of Object.entries(config.typography)) {
      const themeValue = def.theme[themeName];
      if (themeValue) {
        const name = useNewNames && def.newName ? def.newName : tokenName;
        overrides.push(`    --text-${name}: ${themeValue};`);
      }
    }
  }

  if (overrides.length === 0) {
    return `${GENERATED_FILE_HEADER}/* No overrides for ${themeName} theme */\n`;
  }

  return `${GENERATED_FILE_HEADER}@layer base {
  [data-theme="${themeName}"] {
${overrides.join("\n")}
  }
}
`;
}

/**
 * Get a mapping of old token names to new names
 * Useful for running codemods during migration
 */
export function getTokenRenameMap(config: ThemeConfig): TokenRenameMap {
  const textMap: Record<string, string> = {};
  const colorMap: Record<string, string> = {};

  for (const [tokenName, def] of Object.entries(config.text)) {
    textMap[tokenName] = def.newName;
  }

  for (const [tokenName, def] of Object.entries(config.color)) {
    colorMap[tokenName] = def.newName;
  }

  return { text: textMap, color: colorMap };
}

/**
 * Generate all theme CSS files
 */
export function generateAllThemes(
  options: GeneratorOptions,
): Map<string, string> {
  const { useNewNames = false, themes = [...AVAILABLE_THEMES] } = options;
  const files = new Map<string, string>();

  // Always generate base kumo theme
  if (themes.includes("kumo")) {
    files.set(
      "theme-kumo.css",
      generateKumoThemeCSS(THEME_CONFIG, useNewNames),
    );
  }

  // Generate override themes
  for (const themeName of themes) {
    if (themeName !== "kumo") {
      files.set(
        `theme-${themeName}.css`,
        generateThemeOverrideCSS(THEME_CONFIG, themeName, useNewNames),
      );
    }
  }

  return files;
}

/**
 * List all tokens with their current and new names
 * Useful for documentation and migration planning
 */
export function listAllTokens(config: ThemeConfig): Array<{
  type: "text" | "color" | "typography";
  currentName: string;
  newName: string;
  themes: string[];
}> {
  const tokens: Array<{
    type: "text" | "color" | "typography";
    currentName: string;
    newName: string;
    themes: string[];
  }> = [];

  for (const [tokenName, def] of Object.entries(config.text)) {
    tokens.push({
      type: "text",
      currentName: tokenName,
      newName: def.newName,
      themes: Object.keys(def.theme),
    });
  }

  for (const [tokenName, def] of Object.entries(config.color)) {
    tokens.push({
      type: "color",
      currentName: tokenName,
      newName: def.newName,
      themes: Object.keys(def.theme),
    });
  }

  if (config.typography) {
    for (const [tokenName, def] of Object.entries(config.typography)) {
      tokens.push({
        type: "typography",
        currentName: tokenName,
        newName: def.newName,
        themes: Object.keys(def.theme),
      });
    }
  }

  return tokens;
}
