// generator.ts — Token map → theme.ts emitter

import { TokenSet } from "./tokens";
import { PerryColor, colorLiteral } from "./color";

// Sanitize a token key for use as a TypeScript identifier
// "primary-dark" → "primaryDark", "font-size" → "fontSize"
function toIdent(key: string): string {
  const parts = key.split("-");
  let result = parts[0];
  for (let i = 1; i < parts.length; i = i + 1) {
    const part = parts[i];
    if (part.length > 0) {
      result = result + part.charAt(0).toUpperCase() + part.slice(1);
    }
  }
  return result;
}

// Check if a string is a valid TypeScript identifier (simple check)
function isValidIdent(key: string): boolean {
  if (key.length === 0) { return false; }
  const first = key.charAt(0);
  const isLetter = (first >= "a" && first <= "z") || (first >= "A" && first <= "Z") || first === "_";
  if (!isLetter) { return false; }
  for (let i = 1; i < key.length; i = i + 1) {
    const c = key.charAt(i);
    const ok = (c >= "a" && c <= "z") || (c >= "A" && c <= "Z") || (c >= "0" && c <= "9") || c === "_";
    if (!ok) { return false; }
  }
  return true;
}

// Format a key for use as an object property (quote if not a valid identifier)
function formatKey(key: string): string {
  const ident = toIdent(key);
  if (isValidIdent(ident)) {
    return ident;
  }
  return JSON.stringify(key);
}

// Generate a color property line: "  primary: { r: 0.231, ... },  // #3B82F6"
function colorProp(key: string, color: PerryColor, origValue: string, indent: string): string {
  const prop = formatKey(key);
  const padded = (prop + ":").padEnd(18);
  return indent + padded + " " + colorLiteral(color, origValue) + ",";
}

// Generate the complete theme.ts file content from a TokenSet.
// originalColorValues is a map of key -> original CSS string (for comments).
export function generateTheme(tokens: TokenSet, originalColorValues: { [key: string]: string }, originalDarkValues: { [key: string]: string }): string {
  const lines: string[] = [];

  lines.push("// Generated by perry-styling — do not edit manually");
  lines.push("// Re-generate: perry-styling generate --tokens tokens.json --out src/theme.ts");
  lines.push("");

  // PerryColor interface
  lines.push("export interface PerryColor { r: number; g: number; b: number; a: number }");
  lines.push("");

  // PerryColors interface — one entry per color key
  const colorKeys = tokens.colorKeys;
  if (colorKeys.length > 0) {
    lines.push("export interface PerryColors {");
    for (let i = 0; i < colorKeys.length; i = i + 1) {
      const k = colorKeys[i];
      lines.push("  " + formatKey(k) + ": PerryColor;");
    }
    lines.push("}");
    lines.push("");
  }

  // PerryTheme interface
  lines.push("export interface PerryTheme {");
  if (colorKeys.length > 0) {
    lines.push("  light:    PerryColors;");
    lines.push("  dark:     PerryColors;");
  }

  const spacingKeys = Object.keys(tokens.spacing);
  if (spacingKeys.length > 0) {
    let spacingType = "{ ";
    for (let i = 0; i < spacingKeys.length; i = i + 1) {
      spacingType = spacingType + formatKey(spacingKeys[i]) + ": number;";
      if (i < spacingKeys.length - 1) { spacingType = spacingType + " "; }
    }
    spacingType = spacingType + " }";
    lines.push("  spacing:  " + spacingType + ";");
  }

  const radiusKeys = Object.keys(tokens.radius);
  if (radiusKeys.length > 0) {
    let radiusType = "{ ";
    for (let i = 0; i < radiusKeys.length; i = i + 1) {
      radiusType = radiusType + formatKey(radiusKeys[i]) + ": number;";
      if (i < radiusKeys.length - 1) { radiusType = radiusType + " "; }
    }
    radiusType = radiusType + " }";
    lines.push("  radius:   " + radiusType + ";");
  }

  const fontSizeKeys = Object.keys(tokens.fontSize);
  if (fontSizeKeys.length > 0) {
    let fsType = "{ ";
    for (let i = 0; i < fontSizeKeys.length; i = i + 1) {
      fsType = fsType + formatKey(fontSizeKeys[i]) + ": number;";
      if (i < fontSizeKeys.length - 1) { fsType = fsType + " "; }
    }
    fsType = fsType + " }";
    lines.push("  fontSize: " + fsType + ";");
  }

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

  // const theme: PerryTheme = { ... }
  lines.push("export const theme: PerryTheme = {");

  // Light palette
  if (colorKeys.length > 0) {
    lines.push("  light: {");
    for (let i = 0; i < colorKeys.length; i = i + 1) {
      const k = colorKeys[i];
      const orig = originalColorValues[k] !== undefined ? originalColorValues[k] : "";
      lines.push(colorProp(k, tokens.lightColors[k], orig, "    "));
    }
    lines.push("  },");

    // Dark palette
    lines.push("  dark: {");
    for (let i = 0; i < colorKeys.length; i = i + 1) {
      const k = colorKeys[i];
      // Show the original dark value if there was one, else the light value
      const darkKey = k + "-dark";
      const orig = originalDarkValues[darkKey] !== undefined ? originalDarkValues[darkKey] : (originalColorValues[k] !== undefined ? originalColorValues[k] : "");
      lines.push(colorProp(k, tokens.darkColors[k], orig, "    "));
    }
    lines.push("  },");
  }

  // Spacing
  if (spacingKeys.length > 0) {
    let spacingLine = "  spacing:  { ";
    for (let i = 0; i < spacingKeys.length; i = i + 1) {
      const k = spacingKeys[i];
      spacingLine = spacingLine + formatKey(k) + ": " + String(tokens.spacing[k]);
      if (i < spacingKeys.length - 1) { spacingLine = spacingLine + ", "; }
    }
    spacingLine = spacingLine + " },";
    lines.push(spacingLine);
  }

  // Radius
  if (radiusKeys.length > 0) {
    let radiusLine = "  radius:   { ";
    for (let i = 0; i < radiusKeys.length; i = i + 1) {
      const k = radiusKeys[i];
      radiusLine = radiusLine + formatKey(k) + ": " + String(tokens.radius[k]);
      if (i < radiusKeys.length - 1) { radiusLine = radiusLine + ", "; }
    }
    radiusLine = radiusLine + " },";
    lines.push(radiusLine);
  }

  // FontSize
  if (fontSizeKeys.length > 0) {
    let fsLine = "  fontSize: { ";
    for (let i = 0; i < fontSizeKeys.length; i = i + 1) {
      const k = fontSizeKeys[i];
      fsLine = fsLine + formatKey(k) + ": " + String(tokens.fontSize[k]);
      if (i < fontSizeKeys.length - 1) { fsLine = fsLine + ", "; }
    }
    fsLine = fsLine + " },";
    lines.push(fsLine);
  }

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

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