/**
 * MORPH-SPEC Design System Generator Library
 *
 * Reads ui-design-system.md and generates:
 * - wwwroot/css/design-system.css (CSS variables)
 * - Themes/FluentDesignTheme.cs (Fluent UI theme)
 * - Themes/MudTheme.cs (MudBlazor theme)
 *
 * Used both by CLI commands and internal automation.
 */

import { readFileSync, existsSync } from 'fs';

// ============================================================================
// Parsing Functions
// ============================================================================

/**
 * Parse colors from markdown
 * @param {string} markdown - Markdown content
 * @returns {Object} Colors object with primary, secondary, neutral, semantic
 */
export function parseColors(markdown) {
  const colors = { primary: {}, secondary: {}, neutral: {}, semantic: {} };

  // Match color definitions like: - **Primary 500** (`#...`) - ...
  const colorRegex = /(?:^|\n)[-*]\s+\*\*([^*]+)\*\*[^\(]*\(`(#[0-9A-Fa-f]{6})`\)/gm;

  let match;
  while ((match = colorRegex.exec(markdown)) !== null) {
    const [, name, hex] = match;
    const cleanName = name.trim().toLowerCase().replace(/\s+/g, '-');

    if (name.includes('Primary')) {
      const variant = name.match(/\d+/)?.[0] || 'default';
      colors.primary[variant] = hex;
    } else if (name.includes('Secondary')) {
      const variant = name.match(/\d+/)?.[0] || 'default';
      colors.secondary[variant] = hex;
    } else if (name.includes('Neutral') || name.includes('Gray')) {
      const variant = name.match(/\d+/)?.[0] || 'default';
      colors.neutral[variant] = hex;
    } else if (name.includes('Success') || name.includes('Error') || name.includes('Warning') || name.includes('Info')) {
      const type = name.toLowerCase().replace(/\s+/g, '-');
      colors.semantic[type] = hex;
    }
  }

  return colors;
}

/**
 * Parse typography from markdown
 * @param {string} markdown - Markdown content
 * @returns {Object} Typography object with fontFamily, fontSize, fontWeight, lineHeight
 */
export function parseTypography(markdown) {
  const typography = { fontFamily: {}, fontSize: {}, fontWeight: {}, lineHeight: {} };

  // Match font family
  const fontFamilyRegex = /(?:font[- ]?family|typeface)[:\s]+([^\n]+)/gi;
  const fontMatch = fontFamilyRegex.exec(markdown);
  if (fontMatch) {
    typography.fontFamily.primary = fontMatch[1].trim();
  }

  // Match font sizes (but exclude spacing-related)
  const fontSizeRegex = /(?:^|\n)[-*]\s+\*\*([^*]+)\*\*[^:]*:\s*(\d+(?:\.\d+)?(?:rem|px|em))/gm;
  let match;
  while ((match = fontSizeRegex.exec(markdown)) !== null) {
    const [, name, size] = match;
    const lowerName = name.toLowerCase();
    // Skip if it's spacing-related
    if (lowerName.includes('spacing') || lowerName.includes('gap') || lowerName.includes('margin') || lowerName.includes('padding')) {
      continue;
    }
    const cleanName = name.trim().toLowerCase().replace(/\s+/g, '-');
    typography.fontSize[cleanName] = size;
  }

  return typography;
}

/**
 * Parse spacing from markdown
 * @param {string} markdown - Markdown content
 * @returns {Object} Spacing object with spacing values
 */
export function parseSpacing(markdown) {
  const spacing = {};

  // Match spacing definitions
  const spacingRegex = /(?:^|\n)[-*]\s+\*\*([^*]+)\*\*[^:]*:\s*(\d+(?:\.\d+)?(?:rem|px|em))/gm;
  let match;
  while ((match = spacingRegex.exec(markdown)) !== null) {
    const [, name, value] = match;
    if (name.toLowerCase().includes('spacing') || name.toLowerCase().includes('gap') || name.toLowerCase().includes('margin') || name.toLowerCase().includes('padding')) {
      const cleanName = name.trim().toLowerCase().replace(/\s+/g, '-');
      spacing[cleanName] = value;
    }
  }

  return spacing;
}

/**
 * Parse all design system properties from markdown
 * @param {string} markdownPath - Path to ui-design-system.md file
 * @returns {Object} Parsed design system with colors, typography, spacing
 */
export function parseDesignSystem(markdownPath) {
  if (!existsSync(markdownPath)) {
    throw new Error(`File not found: ${markdownPath}`);
  }

  const markdown = readFileSync(markdownPath, 'utf-8');

  return {
    colors: parseColors(markdown),
    typography: parseTypography(markdown),
    spacing: parseSpacing(markdown)
  };
}

// ============================================================================
// Generation Functions
// ============================================================================

/**
 * Generate CSS variables file
 * @param {Object} colors - Colors object
 * @param {Object} typography - Typography object
 * @param {Object} spacing - Spacing object
 * @returns {string} CSS content
 */
export function generateCSS(colors, typography, spacing) {
  let css = `/* Auto-generated by MORPH-SPEC Design System Generator */\n`;
  css += `/* Do not edit manually - regenerate from ui-design-system.md */\n\n`;
  css += `:root {\n`;

  // Colors
  if (Object.keys(colors.primary).length > 0) {
    css += `  /* Primary Colors */\n`;
    Object.entries(colors.primary).forEach(([variant, hex]) => {
      css += `  --color-primary-${variant}: ${hex};\n`;
    });
    css += `\n`;
  }

  if (Object.keys(colors.secondary).length > 0) {
    css += `  /* Secondary Colors */\n`;
    Object.entries(colors.secondary).forEach(([variant, hex]) => {
      css += `  --color-secondary-${variant}: ${hex};\n`;
    });
    css += `\n`;
  }

  if (Object.keys(colors.neutral).length > 0) {
    css += `  /* Neutral Colors */\n`;
    Object.entries(colors.neutral).forEach(([variant, hex]) => {
      css += `  --color-neutral-${variant}: ${hex};\n`;
    });
    css += `\n`;
  }

  if (Object.keys(colors.semantic).length > 0) {
    css += `  /* Semantic Colors */\n`;
    Object.entries(colors.semantic).forEach(([type, hex]) => {
      css += `  --color-${type}: ${hex};\n`;
    });
    css += `\n`;
  }

  // Typography
  if (typography.fontFamily.primary) {
    css += `  /* Typography */\n`;
    css += `  --font-family-primary: ${typography.fontFamily.primary};\n`;
    css += `\n`;
  }

  if (Object.keys(typography.fontSize).length > 0) {
    css += `  /* Font Sizes */\n`;
    Object.entries(typography.fontSize).forEach(([name, size]) => {
      css += `  --font-size-${name}: ${size};\n`;
    });
    css += `\n`;
  }

  // Spacing
  if (Object.keys(spacing).length > 0) {
    css += `  /* Spacing */\n`;
    Object.entries(spacing).forEach(([name, value]) => {
      css += `  --${name}: ${value};\n`;
    });
  }

  css += `}\n`;

  return css;
}

/**
 * Generate Fluent UI theme (C#)
 * @param {Object} colors - Colors object
 * @param {Object} typography - Typography object
 * @param {string} namespace - C# namespace (default: YourProject.Themes)
 * @returns {string} C# code
 */
export function generateFluentTheme(colors, typography, namespace = 'YourProject.Themes') {
  const primary500 = colors.primary['500'] || '#0078d4';

  let csharp = `// Auto-generated by MORPH-SPEC Design System Generator\n`;
  csharp += `// Do not edit manually - regenerate from ui-design-system.md\n\n`;
  csharp += `using Microsoft.FluentUI.AspNetCore.Components;\n\n`;
  csharp += `namespace ${namespace};\n\n`;
  csharp += `public static class FluentDesignTheme\n{\n`;
  csharp += `    public static DesignThemePalette GetPalette()\n`;
  csharp += `    {\n`;
  csharp += `        return new DesignThemePalette\n`;
  csharp += `        {\n`;
  csharp += `            Accent = "${primary500}",\n`;
  csharp += `            // Add more theme properties as needed\n`;
  csharp += `        };\n`;
  csharp += `    }\n`;
  csharp += `}\n`;

  return csharp;
}

/**
 * Generate MudBlazor theme (C#)
 * @param {Object} colors - Colors object
 * @param {Object} typography - Typography object
 * @param {string} namespace - C# namespace (default: YourProject.Themes)
 * @returns {string} C# code
 */
export function generateMudTheme(colors, typography, namespace = 'YourProject.Themes') {
  const primary500 = colors.primary['500'] || '#594ae2';
  const secondary500 = colors.secondary['500'] || '#ff4081';

  let csharp = `// Auto-generated by MORPH-SPEC Design System Generator\n`;
  csharp += `// Do not edit manually - regenerate from ui-design-system.md\n\n`;
  csharp += `using MudBlazor;\n\n`;
  csharp += `namespace ${namespace};\n\n`;
  csharp += `public static class MudDesignTheme\n{\n`;
  csharp += `    public static MudTheme GetTheme()\n`;
  csharp += `    {\n`;
  csharp += `        return new MudTheme\n`;
  csharp += `        {\n`;
  csharp += `            Palette = new PaletteLight\n`;
  csharp += `            {\n`;
  csharp += `                Primary = "${primary500}",\n`;
  csharp += `                Secondary = "${secondary500}",\n`;
  csharp += `                // Add more palette colors as needed\n`;
  csharp += `            }\n`;
  csharp += `        };\n`;
  csharp += `    }\n`;
  csharp += `}\n`;

  return csharp;
}

/**
 * Generate all design system files
 * @param {string} designSystemPath - Path to ui-design-system.md
 * @param {Object} options - Generation options
 * @param {string} options.mode - Generation mode: 'fluent', 'mud', or 'both'
 * @param {string} options.namespace - C# namespace
 * @returns {Object} Generated files content
 */
export function generateDesignSystem(designSystemPath, options = {}) {
  const { mode = 'both', namespace = 'YourProject.Themes' } = options;

  // Parse design system
  const { colors, typography, spacing } = parseDesignSystem(designSystemPath);

  const generated = {
    css: generateCSS(colors, typography, spacing),
    stats: {
      primaryColors: Object.keys(colors.primary).length,
      neutralColors: Object.keys(colors.neutral).length,
      semanticColors: Object.keys(colors.semantic).length,
      fontSizes: Object.keys(typography.fontSize).length,
      spacingValues: Object.keys(spacing).length
    }
  };

  // Generate themes based on mode
  if (mode === 'fluent' || mode === 'both') {
    generated.fluentTheme = generateFluentTheme(colors, typography, namespace);
  }

  if (mode === 'mud' || mode === 'both') {
    generated.mudTheme = generateMudTheme(colors, typography, namespace);
  }

  return generated;
}
