# design-system-generator.js

    /**
     * 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;
    }