/**
 * properSyntaxHighlighting Tests
 *
 * Comprehensive tests for CodeMirror 6 syntax highlighting configuration
 */

import {
  comprehensiveVSCodeTheme,
  cleanEditorTheme,
  createRobustExtensions
} from '../properSyntaxHighlighting';

describe('properSyntaxHighlighting', () => {
  describe('comprehensiveVSCodeTheme', () => {
    it('is defined and has expected structure', () => {
      expect(comprehensiveVSCodeTheme).toBeDefined();
      expect(typeof comprehensiveVSCodeTheme).toBe('object');
    });

    it('is a HighlightStyle instance', () => {
      expect(comprehensiveVSCodeTheme).toBeTruthy();
      // HighlightStyle instances are objects created by HighlightStyle.define()
      expect(typeof comprehensiveVSCodeTheme).toBe('object');
      expect(comprehensiveVSCodeTheme).not.toBeNull();
    });

    it('can be used as an extension', () => {
      // Should not throw when used
      expect(() => {
        const theme = comprehensiveVSCodeTheme;
        expect(theme).toBeTruthy();
      }).not.toThrow();
    });

    it('maintains consistent reference', () => {
      const theme1 = comprehensiveVSCodeTheme;
      const theme2 = comprehensiveVSCodeTheme;
      expect(theme1).toBe(theme2);
    });
  });

  describe('cleanEditorTheme', () => {
    it('is defined and has expected structure', () => {
      expect(cleanEditorTheme).toBeDefined();
      expect(typeof cleanEditorTheme).toBe('object');
    });

    it('is an EditorView theme instance', () => {
      expect(cleanEditorTheme).toBeTruthy();
      // EditorView themes are objects created by EditorView.theme()
      expect(typeof cleanEditorTheme).toBe('object');
      expect(cleanEditorTheme).not.toBeNull();
    });

    it('can be used as an extension', () => {
      // Should not throw when used
      expect(() => {
        const theme = cleanEditorTheme;
        expect(theme).toBeTruthy();
      }).not.toThrow();
    });

    it('maintains consistent reference', () => {
      const theme1 = cleanEditorTheme;
      const theme2 = cleanEditorTheme;
      expect(theme1).toBe(theme2);
    });
  });

  describe('createRobustExtensions', () => {
    it('returns an array of extensions', () => {
      const extensions = createRobustExtensions();

      expect(Array.isArray(extensions)).toBe(true);
      expect(extensions.length).toBe(3);
    });

    it('returns extensions with proper structure', () => {
      const extensions = createRobustExtensions();

      // Each extension should be an object or function
      extensions.forEach((ext, index) => {
        expect(ext).toBeDefined();
        expect(['object', 'function'].includes(typeof ext)).toBe(true);
      });
    });

    it('includes HTML language support as first extension', () => {
      const extensions = createRobustExtensions();

      // First extension should be HTML language support
      expect(extensions[0]).toBeDefined();
      expect(typeof extensions[0]).toBe('object');
    });

    it('includes syntax highlighting as second extension', () => {
      const extensions = createRobustExtensions();

      // Second extension should be syntax highlighting
      expect(extensions[1]).toBeDefined();
      expect(typeof extensions[1]).toBe('object');
    });

    it('includes editor theme as third extension', () => {
      const extensions = createRobustExtensions();

      // Third extension should be the editor theme
      expect(extensions[2]).toBeDefined();
      expect(extensions[2]).toBe(cleanEditorTheme);
    });

    it('returns consistent results on multiple calls', () => {
      const extensions1 = createRobustExtensions();
      const extensions2 = createRobustExtensions();

      expect(extensions1.length).toBe(extensions2.length);
      expect(extensions1[2]).toBe(extensions2[2]); // Theme should be the same reference
    });

    it('does not throw errors during creation', () => {
      expect(() => {
        createRobustExtensions();
      }).not.toThrow();
    });

    it('creates valid extensions for CodeMirror', () => {
      const extensions = createRobustExtensions();

      // All extensions should be valid CodeMirror extensions
      extensions.forEach(ext => {
        expect(ext).toBeTruthy();
        // CodeMirror extensions are typically objects or functions
        expect(['object', 'function'].includes(typeof ext)).toBe(true);
      });
    });
  });

  describe('Default Export', () => {
    it('exports all main components', () => {
      const defaultExport = require('../properSyntaxHighlighting').default;

      expect(defaultExport).toBeDefined();
      expect(typeof defaultExport).toBe('object');
      expect(defaultExport).toHaveProperty('comprehensiveVSCodeTheme');
      expect(defaultExport).toHaveProperty('cleanEditorTheme');
      expect(defaultExport).toHaveProperty('createRobustExtensions');
    });

    it('default export contains correct references', () => {
      const defaultExport = require('../properSyntaxHighlighting').default;

      expect(defaultExport.comprehensiveVSCodeTheme).toBe(comprehensiveVSCodeTheme);
      expect(defaultExport.cleanEditorTheme).toBe(cleanEditorTheme);
      expect(defaultExport.createRobustExtensions).toBe(createRobustExtensions);
    });

    it('provides consistent interface', () => {
      const defaultExport = require('../properSyntaxHighlighting').default;

      // Should be able to use all exported functions
      expect(() => {
        const theme = defaultExport.comprehensiveVSCodeTheme;
        const editorTheme = defaultExport.cleanEditorTheme;
        const extensions = defaultExport.createRobustExtensions();

        expect(theme).toBeTruthy();
        expect(editorTheme).toBeTruthy();
        expect(extensions).toBeTruthy();
      }).not.toThrow();
    });
  });

  describe('Integration and Compatibility', () => {
    it('handles CodeMirror dependencies without errors', () => {
      // Should not throw when creating extensions
      expect(() => {
        const extensions = createRobustExtensions();
        expect(extensions).toBeTruthy();
      }).not.toThrow();
    });

    it('provides theme objects that can be used together', () => {
      const extensions = createRobustExtensions();

      // Should contain both themes
      expect(extensions).toContain(cleanEditorTheme);

      // Should be able to access syntax theme
      expect(comprehensiveVSCodeTheme).toBeTruthy();
    });

    it('maintains extension compatibility', () => {
      const extensions = createRobustExtensions();

      // All extensions should be compatible with CodeMirror
      extensions.forEach(ext => {
        expect(ext).toBeTruthy();
        expect(['object', 'function'].includes(typeof ext)).toBe(true);
      });
    });

    it('provides complete syntax highlighting solution', () => {
      const extensions = createRobustExtensions();

      // Should have exactly 3 extensions: language, highlighting, theme
      expect(extensions.length).toBe(3);

      // Each should be a valid extension
      extensions.forEach(ext => {
        expect(ext).toBeTruthy();
      });
    });
  });

  describe('Performance and Memory', () => {
    it('creates extensions reliably without throwing', () => {
      const results = [];

      // Call createRobustExtensions 50 times and collect results
      for (let i = 0; i < 50; i++) {
        expect(() => {
          const extensions = createRobustExtensions();
          results.push(extensions);
        }).not.toThrow();
      }

      // Verify all calls returned values of expected shape
      results.forEach((extensions, index) => {
        expect(extensions).toBeDefined();
        expect(Array.isArray(extensions)).toBe(true);
        expect(extensions.length).toBeGreaterThan(0);

        // Each extension should be a valid CodeMirror extension
        extensions.forEach(ext => {
          expect(ext).toBeTruthy();
          // Extensions can be functions, objects, or other valid CodeMirror extension types
          expect(typeof ext === 'function' || typeof ext === 'object').toBe(true);
        });
      });

      // Verify structural consistency - all results should have same length and types
      const firstResult = results[0];
      results.forEach((result, index) => {
        expect(result.length).toBe(firstResult.length);

        // Verify each extension at the same index has the same type and basic structure
        result.forEach((ext, extIndex) => {
          const firstExt = firstResult[extIndex];
          expect(typeof ext).toBe(typeof firstExt);

          // If it's an object, check it has similar keys (for memoization check)
          if (typeof ext === 'object' && ext !== null && typeof firstExt === 'object' && firstExt !== null) {
            expect(Object.keys(ext).sort()).toEqual(Object.keys(firstExt).sort());
          }
        });
      });
    });

    it('maintains object references efficiently', () => {
      const theme1 = comprehensiveVSCodeTheme;
      const theme2 = comprehensiveVSCodeTheme;
      const editorTheme1 = cleanEditorTheme;
      const editorTheme2 = cleanEditorTheme;

      // Should be the same objects (not recreated)
      expect(theme1).toBe(theme2);
      expect(editorTheme1).toBe(editorTheme2);
    });

    it('handles repeated extension creation', () => {
      // Should not accumulate memory or cause issues
      const results = [];

      for (let i = 0; i < 10; i++) {
        results.push(createRobustExtensions());
      }

      // All should be valid
      results.forEach(extensions => {
        expect(extensions.length).toBe(3);
      });

      // Theme references should be consistent
      results.forEach(extensions => {
        expect(extensions[2]).toBe(cleanEditorTheme);
      });
    });

    it('does not leak memory with theme creation', () => {
      // Create themes multiple times
      const themes = [];
      for (let i = 0; i < 20; i++) {
        themes.push(comprehensiveVSCodeTheme);
        themes.push(cleanEditorTheme);
      }

      // All references should be the same (no new objects created)
      themes.forEach((theme, index) => {
        if (index % 2 === 0) {
          expect(theme).toBe(comprehensiveVSCodeTheme);
        } else {
          expect(theme).toBe(cleanEditorTheme);
        }
      });
    });
  });

  describe('Error Handling and Edge Cases', () => {
    it('handles module import gracefully', () => {
      // Should not throw during import
      expect(() => {
        const module = require('../properSyntaxHighlighting');
        expect(module).toBeTruthy();
      }).not.toThrow();
    });

    it('provides fallback behavior', () => {
      // All exports should be defined even if dependencies fail
      expect(comprehensiveVSCodeTheme).toBeDefined();
      expect(cleanEditorTheme).toBeDefined();
      expect(createRobustExtensions).toBeDefined();
    });

    it('handles extension creation edge cases', () => {
      // Should work even with rapid successive calls
      const results = [];

      for (let i = 0; i < 5; i++) {
        results.push(createRobustExtensions());
      }

      results.forEach(extensions => {
        expect(Array.isArray(extensions)).toBe(true);
        expect(extensions.length).toBe(3);
      });
    });

    it('maintains stability across different usage patterns', () => {
      // Mixed usage patterns
      const theme = comprehensiveVSCodeTheme;
      const editorTheme = cleanEditorTheme;
      const extensions1 = createRobustExtensions();
      const extensions2 = createRobustExtensions();

      expect(theme).toBeTruthy();
      expect(editorTheme).toBeTruthy();
      expect(extensions1).toBeTruthy();
      expect(extensions2).toBeTruthy();

      // Should maintain consistency
      expect(extensions1[2]).toBe(extensions2[2]);
    });

    it('handles concurrent access', () => {
      // Simulate concurrent access
      const promises = [];

      for (let i = 0; i < 10; i++) {
        promises.push(Promise.resolve(createRobustExtensions()));
      }

      return Promise.all(promises).then(results => {
        results.forEach(extensions => {
          expect(extensions.length).toBe(3);
        });
      });
    });
  });

  describe('API Consistency', () => {
    it('provides stable API interface', () => {
      // Named exports
      expect(typeof comprehensiveVSCodeTheme).toBe('object');
      expect(typeof cleanEditorTheme).toBe('object');
      expect(typeof createRobustExtensions).toBe('function');

      // Default export
      const defaultExport = require('../properSyntaxHighlighting').default;
      expect(typeof defaultExport).toBe('object');
      expect(typeof defaultExport.createRobustExtensions).toBe('function');
    });

    it('maintains backward compatibility', () => {
      // Should support both import styles
      const namedImports = {
        comprehensiveVSCodeTheme,
        cleanEditorTheme,
        createRobustExtensions
      };

      const defaultImport = require('../properSyntaxHighlighting').default;

      expect(namedImports.comprehensiveVSCodeTheme).toBe(defaultImport.comprehensiveVSCodeTheme);
      expect(namedImports.cleanEditorTheme).toBe(defaultImport.cleanEditorTheme);
      expect(namedImports.createRobustExtensions).toBe(defaultImport.createRobustExtensions);
    });

    it('provides complete functionality', () => {
      // Should provide everything needed for CodeMirror setup
      const extensions = createRobustExtensions();

      expect(extensions.length).toBe(3);
      expect(comprehensiveVSCodeTheme).toBeTruthy();
      expect(cleanEditorTheme).toBeTruthy();

      // Should be usable together
      expect(() => {
        const combined = [
          ...extensions,
          comprehensiveVSCodeTheme,
          cleanEditorTheme
        ];
        expect(combined.length).toBeGreaterThan(3);
      }).not.toThrow();
    });
  });

  describe('Real-world Usage Scenarios', () => {
    it('supports typical CodeMirror editor setup', () => {
      // Typical usage pattern
      const extensions = createRobustExtensions();

      expect(extensions).toBeDefined();
      expect(extensions.length).toBe(3);

      // Should be able to use in editor configuration
      const editorConfig = {
        extensions: extensions,
        theme: cleanEditorTheme
      };

      expect(editorConfig.extensions).toBe(extensions);
      expect(editorConfig.theme).toBe(cleanEditorTheme);
    });

    it('supports theme customization scenarios', () => {
      // Should be able to access both themes
      const syntaxTheme = comprehensiveVSCodeTheme;
      const editorTheme = cleanEditorTheme;

      expect(syntaxTheme).toBeTruthy();
      expect(editorTheme).toBeTruthy();

      // Should be different objects
      expect(syntaxTheme).not.toBe(editorTheme);
    });

    it('supports extension composition', () => {
      const baseExtensions = createRobustExtensions();

      // Should be able to add more extensions
      const customExtensions = [
        ...baseExtensions,
        // Could add more extensions here
      ];

      expect(customExtensions.length).toBeGreaterThanOrEqual(3);
      expect(customExtensions.slice(0, 3)).toEqual(baseExtensions);
    });

    it('supports multiple editor instances', () => {
      // Should work for multiple editors
      const editor1Extensions = createRobustExtensions();
      const editor2Extensions = createRobustExtensions();

      expect(editor1Extensions).toBeTruthy();
      expect(editor2Extensions).toBeTruthy();

      // Should have same structure
      expect(editor1Extensions.length).toBe(editor2Extensions.length);
    });
  });
});