/**
 * Unit Tests: component-config.js
 * Tests extensible component registry system
 */

// Mock config-loader before importing component-config
jest.mock('../config-loader.js', () => ({
  getConfig: jest.fn(() => ({
    dssHost: 'dss.overbits.luz.uy',
    dssPort: '3456',
    storybookPort: 6006,
  })),
  getDssHost: jest.fn(() => 'dss.overbits.luz.uy'),
  getDssPort: jest.fn(() => '3456'),
  getStorybookPort: jest.fn(() => 6006),
  getStorybookUrl: jest.fn(() => 'https://dss.overbits.luz.uy/storybook/'),
  loadConfig: jest.fn(),
  __resetForTesting: jest.fn(),
}));

import {
  componentRegistry,
  getEnabledComponents,
  getComponentsByCategory,
  getComponent,
  getComponentSetting,
  setComponentSetting,
  getComponentSettings
} from '../component-config.js';

describe('component-config', () => {
  beforeEach(() => {
    // Clear localStorage before each test
    localStorage.clear();
  });

  describe('componentRegistry', () => {
    test('contains Storybook component', () => {
      expect(componentRegistry.storybook).toBeDefined();
      expect(componentRegistry.storybook.id).toBe('storybook');
    });

    test('contains Figma component', () => {
      expect(componentRegistry.figma).toBeDefined();
      expect(componentRegistry.figma.id).toBe('figma');
    });

    test('contains placeholder components (Jira, Confluence)', () => {
      expect(componentRegistry.jira).toBeDefined();
      expect(componentRegistry.confluence).toBeDefined();
    });

    test('placeholder components are disabled', () => {
      expect(componentRegistry.jira.enabled).toBe(false);
      expect(componentRegistry.confluence.enabled).toBe(false);
    });
  });

  describe('getEnabledComponents()', () => {
    test('returns only enabled components', () => {
      const enabled = getEnabledComponents();

      // Should include Storybook and Figma
      expect(enabled.some(c => c.id === 'storybook')).toBe(true);
      expect(enabled.some(c => c.id === 'figma')).toBe(true);

      // Should NOT include disabled components
      expect(enabled.some(c => c.id === 'jira')).toBe(false);
      expect(enabled.some(c => c.id === 'confluence')).toBe(false);
    });

    test('returns components with full structure', () => {
      const enabled = getEnabledComponents();

      enabled.forEach(component => {
        expect(component).toHaveProperty('id');
        expect(component).toHaveProperty('name');
        expect(component).toHaveProperty('description');
        expect(component).toHaveProperty('icon');
        expect(component).toHaveProperty('category');
        expect(component).toHaveProperty('config');
      });
    });
  });

  describe('getComponentsByCategory()', () => {
    test('filters components by category', () => {
      const docComponents = getComponentsByCategory('documentation');

      expect(docComponents.length).toBeGreaterThan(0);
      expect(docComponents.every(c => c.category === 'documentation')).toBe(true);
    });

    test('returns design category components', () => {
      const designComponents = getComponentsByCategory('design');

      expect(designComponents.some(c => c.id === 'figma')).toBe(true);
    });

    test('returns empty array for non-existent category', () => {
      const components = getComponentsByCategory('nonexistent');
      expect(components).toEqual([]);
    });

    test('excludes disabled components', () => {
      const projectComponents = getComponentsByCategory('project');

      expect(projectComponents.every(c => c.enabled !== false)).toBe(true);
    });
  });

  describe('getComponent()', () => {
    test('returns Storybook component by ID', () => {
      const storybook = getComponent('storybook');

      expect(storybook).toBeDefined();
      expect(storybook.id).toBe('storybook');
      expect(storybook.name).toBe('Storybook');
    });

    test('returns Figma component by ID', () => {
      const figma = getComponent('figma');

      expect(figma).toBeDefined();
      expect(figma.id).toBe('figma');
      expect(figma.name).toBe('Figma');
    });

    test('returns null for non-existent component', () => {
      const component = getComponent('nonexistent');
      expect(component).toBeNull();
    });
  });

  describe('Component Configuration Schema', () => {
    test('Storybook config has correct schema', () => {
      const storybook = getComponent('storybook');
      const config = storybook.config;

      expect(config.port).toBeDefined();
      expect(config.theme).toBeDefined();
      expect(config.showDocs).toBeDefined();

      expect(config.port.type).toBe('number');
      expect(config.theme.type).toBe('select');
      expect(config.showDocs.type).toBe('boolean');
    });

    test('Figma config has correct schema', () => {
      const figma = getComponent('figma');
      const config = figma.config;

      expect(config.apiKey).toBeDefined();
      expect(config.fileKey).toBeDefined();
      expect(config.autoSync).toBeDefined();

      expect(config.apiKey.type).toBe('password');
      expect(config.fileKey.type).toBe('text');
      expect(config.autoSync.type).toBe('boolean');
    });

    test('sensitive fields are marked', () => {
      const figma = getComponent('figma');
      expect(figma.config.apiKey.sensitive).toBe(true);
    });
  });

  describe('getComponentSetting()', () => {
    test('returns default value if not set', () => {
      const theme = getComponentSetting('storybook', 'theme');
      expect(theme).toBe('auto');
    });

    test('returns stored value from localStorage', () => {
      setComponentSetting('storybook', 'theme', 'dark');
      const theme = getComponentSetting('storybook', 'theme');

      expect(theme).toBe('dark');
    });

    test('returns null for non-existent setting', () => {
      const value = getComponentSetting('nonexistent', 'setting');
      expect(value).toBeNull();
    });

    test('parses JSON values from localStorage', () => {
      const obj = { key: 'value', nested: { prop: 123 } };
      setComponentSetting('storybook', 'customSetting', obj);

      const retrieved = getComponentSetting('storybook', 'customSetting');
      expect(retrieved).toEqual(obj);
    });
  });

  describe('setComponentSetting()', () => {
    test('persists string values to localStorage', () => {
      setComponentSetting('storybook', 'theme', 'dark');
      const stored = localStorage.getItem('dss_component_storybook_theme');

      expect(stored).toBe(JSON.stringify('dark'));
    });

    test('persists boolean values', () => {
      setComponentSetting('storybook', 'showDocs', false);
      const value = getComponentSetting('storybook', 'showDocs');

      expect(value).toBe(false);
    });

    test('persists object values as JSON', () => {
      const config = { enabled: true, level: 5 };
      setComponentSetting('figma', 'config', config);
      const retrieved = getComponentSetting('figma', 'config');

      expect(retrieved).toEqual(config);
    });

    test('uses correct localStorage key format', () => {
      setComponentSetting('figma', 'apiKey', 'test123');

      const key = 'dss_component_figma_apiKey';
      expect(localStorage.getItem(key)).toBeDefined();
    });
  });

  describe('getComponentSettings()', () => {
    test('returns all settings for a component', () => {
      setComponentSetting('figma', 'apiKey', 'token123');
      setComponentSetting('figma', 'fileKey', 'abc123');

      const settings = getComponentSettings('figma');

      expect(settings.apiKey).toBe('token123');
      expect(settings.fileKey).toBe('abc123');
    });

    test('returns defaults for unset settings', () => {
      const settings = getComponentSettings('storybook');

      expect(settings.theme).toBe('auto');
      expect(settings.showDocs).toBe(true);
      expect(settings.port).toBe(6006);
    });

    test('returns empty object for non-existent component', () => {
      const settings = getComponentSettings('nonexistent');
      expect(settings).toEqual({});
    });

    test('mixes stored and default values', () => {
      setComponentSetting('storybook', 'theme', 'dark');
      const settings = getComponentSettings('storybook');

      // Stored value
      expect(settings.theme).toBe('dark');
      // Default value
      expect(settings.showDocs).toBe(true);
    });
  });

  describe('Component Methods', () => {
    test('Storybook.getUrl() returns correct URL', () => {
      const storybook = getComponent('storybook');
      const url = storybook.getUrl();

      expect(url).toContain('/storybook/');
    });

    test('Figma.getUrl() returns Figma website', () => {
      const figma = getComponent('figma');
      const url = figma.getUrl();

      expect(url).toBe('https://www.figma.com');
    });

    test('Storybook.checkStatus() is async', async () => {
      const storybook = getComponent('storybook');
      const statusPromise = storybook.checkStatus();

      expect(statusPromise).toBeInstanceOf(Promise);

      const status = await statusPromise;
      expect(status).toHaveProperty('status');
      expect(status).toHaveProperty('message');
    });

    test('Figma.checkStatus() is async', async () => {
      const figma = getComponent('figma');
      const statusPromise = figma.checkStatus();

      expect(statusPromise).toBeInstanceOf(Promise);

      const status = await statusPromise;
      expect(status).toHaveProperty('status');
    });
  });

  describe('Component Validation', () => {
    test('all enabled components have required properties', () => {
      const enabled = getEnabledComponents();

      enabled.forEach(component => {
        expect(component.id).toBeTruthy();
        expect(component.name).toBeTruthy();
        expect(component.description).toBeTruthy();
        expect(component.icon).toBeTruthy();
        expect(component.category).toBeTruthy();
        expect(component.config).toBeTruthy();
        expect(typeof component.getUrl).toBe('function');
        expect(typeof component.checkStatus).toBe('function');
      });
    });

    test('all config schemas have valid types', () => {
      const enabled = getEnabledComponents();

      enabled.forEach(component => {
        Object.entries(component.config).forEach(([key, setting]) => {
          const validTypes = ['text', 'password', 'number', 'boolean', 'select', 'url'];
          expect(validTypes).toContain(setting.type);
        });
      });
    });
  });

  describe('Edge Cases', () => {
    test('handles undefined settings gracefully', () => {
      const value = getComponentSetting('storybook', 'undefined_setting');
      expect(value).toBeNull();
    });

    test('handles corrupted localStorage JSON', () => {
      localStorage.setItem('dss_component_test_corrupt', 'invalid json{]');
      const value = getComponentSetting('test', 'corrupt');

      // Should return the raw string
      expect(typeof value).toBe('string');
    });

    test('component settings survive localStorage clear', () => {
      setComponentSetting('figma', 'fileKey', 'abc123');
      localStorage.clear();

      // After clear, should return default
      const value = getComponentSetting('figma', 'fileKey');
      expect(value).toBeNull();
    });
  });
});
