/**
 * Tests for Puck theme tokens and design controls
 */
import { describe, it, expect } from 'vitest';

// These will be imported from the theme module once implemented
import {
  defaultThemeTokens,
  GRADIENT_PRESETS,
  PADDING_PRESETS,
  CONTAINER_WIDTH_PRESETS,
  BUTTON_RADIUS_PRESETS,
  SHADOW_PRESETS,
  createDesignControlsFields,
  applyDesignControls,
} from '../theme';

describe('Theme Tokens', () => {
  describe('defaultThemeTokens', () => {
    it('should have color tokens', () => {
      expect(defaultThemeTokens.colors).toBeDefined();
      expect(defaultThemeTokens.colors.primary).toBeDefined();
      expect(defaultThemeTokens.colors.secondary).toBeDefined();
      expect(defaultThemeTokens.colors.accent).toBeDefined();
      expect(defaultThemeTokens.colors.neutral).toBeDefined();
    });

    it('should have typography tokens', () => {
      expect(defaultThemeTokens.typography).toBeDefined();
      expect(defaultThemeTokens.typography.fontScale).toBeDefined();
      expect(defaultThemeTokens.typography.headingFamily).toBeDefined();
      expect(defaultThemeTokens.typography.bodyFamily).toBeDefined();
    });

    it('should have button tokens', () => {
      expect(defaultThemeTokens.buttons).toBeDefined();
      expect(defaultThemeTokens.buttons.radius).toBeDefined();
      expect(defaultThemeTokens.buttons.variants).toBeDefined();
      expect(defaultThemeTokens.buttons.variants.primary).toBeDefined();
      expect(defaultThemeTokens.buttons.variants.secondary).toBeDefined();
      expect(defaultThemeTokens.buttons.variants.ghost).toBeDefined();
    });

    it('should have container width tokens', () => {
      expect(defaultThemeTokens.containerWidths).toBeDefined();
      expect(defaultThemeTokens.containerWidths.narrow).toBeDefined();
      expect(defaultThemeTokens.containerWidths.normal).toBeDefined();
      expect(defaultThemeTokens.containerWidths.wide).toBeDefined();
      expect(defaultThemeTokens.containerWidths.full).toBeDefined();
    });
  });

  describe('GRADIENT_PRESETS', () => {
    it('should have dark purple preset', () => {
      const darkPurple = GRADIENT_PRESETS.find(g => g.name === 'dark-purple');
      expect(darkPurple).toBeDefined();
      expect(darkPurple?.value).toContain('gradient');
    });

    it('should have dark blue preset', () => {
      const darkBlue = GRADIENT_PRESETS.find(g => g.name === 'dark-blue');
      expect(darkBlue).toBeDefined();
      expect(darkBlue?.value).toContain('gradient');
    });

    it('should have at least 5 gradient presets', () => {
      expect(GRADIENT_PRESETS.length).toBeGreaterThanOrEqual(5);
    });

    it('should have CSS-valid gradient values', () => {
      GRADIENT_PRESETS.forEach(preset => {
        expect(preset.value).toMatch(/^(linear-gradient|radial-gradient)/);
      });
    });
  });

  describe('PADDING_PRESETS', () => {
    it('should have standard padding sizes', () => {
      expect(PADDING_PRESETS).toHaveProperty('xs');
      expect(PADDING_PRESETS).toHaveProperty('sm');
      expect(PADDING_PRESETS).toHaveProperty('md');
      expect(PADDING_PRESETS).toHaveProperty('lg');
      expect(PADDING_PRESETS).toHaveProperty('xl');
    });

    it('should have increasing padding values', () => {
      const sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const;
      let prevValue = 0;
      sizes.forEach(size => {
        const match = PADDING_PRESETS[size].match(/\d+/);
        const value = match ? parseInt(match[0], 10) : 0;
        expect(value).toBeGreaterThanOrEqual(prevValue);
        prevValue = value;
      });
    });
  });

  describe('CONTAINER_WIDTH_PRESETS', () => {
    it('should have all width options', () => {
      expect(CONTAINER_WIDTH_PRESETS).toHaveProperty('narrow');
      expect(CONTAINER_WIDTH_PRESETS).toHaveProperty('normal');
      expect(CONTAINER_WIDTH_PRESETS).toHaveProperty('wide');
      expect(CONTAINER_WIDTH_PRESETS).toHaveProperty('full');
    });

    it('should have valid CSS classes or values', () => {
      Object.values(CONTAINER_WIDTH_PRESETS).forEach(value => {
        expect(value).toMatch(/^(max-w-|w-)/);
      });
    });
  });
});

describe('Design Controls', () => {
  describe('createDesignControlsFields', () => {
    it('should return Puck field definitions', () => {
      const fields = createDesignControlsFields();
      expect(fields).toBeDefined();
      expect(typeof fields).toBe('object');
    });

    it('should have padding field', () => {
      const fields = createDesignControlsFields();
      expect(fields.padding).toBeDefined();
      expect(fields.padding.type).toBe('select');
    });

    it('should have background variant field', () => {
      const fields = createDesignControlsFields();
      expect(fields.backgroundVariant).toBeDefined();
      expect(fields.backgroundVariant.type).toBe('select');
      const options = fields.backgroundVariant.options;
      expect(options.some((o: { value: string }) => o.value === 'none')).toBe(true);
      expect(options.some((o: { value: string }) => o.value === 'light')).toBe(true);
      expect(options.some((o: { value: string }) => o.value === 'dark')).toBe(true);
      expect(options.some((o: { value: string }) => o.value === 'gradient')).toBe(true);
    });

    it('should have gradient preset field', () => {
      const fields = createDesignControlsFields();
      expect(fields.gradientPreset).toBeDefined();
      expect(fields.gradientPreset.type).toBe('select');
    });

    it('should have content max width field', () => {
      const fields = createDesignControlsFields();
      expect(fields.contentMaxWidth).toBeDefined();
      expect(fields.contentMaxWidth.type).toBe('select');
    });

    it('should have alignment field', () => {
      const fields = createDesignControlsFields();
      expect(fields.alignment).toBeDefined();
      const options = fields.alignment.options;
      expect(options.some((o: { value: string }) => o.value === 'left')).toBe(true);
      expect(options.some((o: { value: string }) => o.value === 'center')).toBe(true);
      expect(options.some((o: { value: string }) => o.value === 'right')).toBe(true);
    });

    it('should have visibility toggles', () => {
      const fields = createDesignControlsFields();
      expect(fields.hideOnMobile).toBeDefined();
      expect(fields.hideOnTablet).toBeDefined();
      expect(fields.hideOnDesktop).toBeDefined();
    });
  });

  describe('applyDesignControls', () => {
    it('should return empty object for no controls', () => {
      const result = applyDesignControls({});
      expect(result.className).toBe('');
      expect(result.style).toEqual({});
    });

    it('should apply padding class', () => {
      const result = applyDesignControls({ padding: 'lg' });
      expect(result.className).toContain('py-');
    });

    it('should apply background variant styles', () => {
      const result = applyDesignControls({ backgroundVariant: 'dark' });
      expect(result.className).toContain('bg-');
    });

    it('should apply gradient preset', () => {
      const result = applyDesignControls({
        backgroundVariant: 'gradient',
        gradientPreset: 'dark-purple',
      });
      expect(result.style.background).toBeDefined();
      expect(result.style.background).toContain('gradient');
    });

    it('should apply content max width', () => {
      const result = applyDesignControls({ contentMaxWidth: 'narrow' });
      expect(result.containerClassName).toContain('max-w-');
    });

    it('should apply alignment', () => {
      const result = applyDesignControls({ alignment: 'center' });
      expect(result.className).toContain('text-center');
    });

    it('should apply visibility classes', () => {
      const result = applyDesignControls({ hideOnMobile: true });
      expect(result.className).toContain('hidden');
      expect(result.className).toContain('sm:block');
    });
  });
});

describe('BUTTON_RADIUS_PRESETS', () => {
  it('should have radius options', () => {
    expect(BUTTON_RADIUS_PRESETS).toHaveProperty('none');
    expect(BUTTON_RADIUS_PRESETS).toHaveProperty('sm');
    expect(BUTTON_RADIUS_PRESETS).toHaveProperty('md');
    expect(BUTTON_RADIUS_PRESETS).toHaveProperty('lg');
    expect(BUTTON_RADIUS_PRESETS).toHaveProperty('full');
  });
});

describe('SHADOW_PRESETS', () => {
  it('should have shadow options', () => {
    expect(SHADOW_PRESETS).toHaveProperty('none');
    expect(SHADOW_PRESETS).toHaveProperty('sm');
    expect(SHADOW_PRESETS).toHaveProperty('md');
    expect(SHADOW_PRESETS).toHaveProperty('lg');
    expect(SHADOW_PRESETS).toHaveProperty('xl');
  });
});
