/**
 * simplePerformance Tests
 *
 * Tests for performance optimization utilities
 */

import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import { renderHook, act } from '@testing-library/react-hooks';
import {
  useSmartDebounce,
  withPerformanceOptimization,
  useCleanup,
  analyzeContentSize,
  useVirtualization,
  PERFORMANCE_THRESHOLDS
} from '../simplePerformance';

describe('simplePerformance', () => {
  beforeEach(() => {
    jest.useFakeTimers();
  });

  afterEach(() => {
    jest.clearAllTimers();
    jest.useRealTimers();
  });

  describe('useSmartDebounce', () => {
    it('debounces callback execution', () => {
      const callback = jest.fn();
      const { result } = renderHook(() => useSmartDebounce(callback, 300));

      act(() => {
        result.current('test value');
      });

      expect(callback).not.toHaveBeenCalled();

      act(() => {
        jest.advanceTimersByTime(300);
      });

      expect(callback).toHaveBeenCalledWith('test value');
      expect(callback).toHaveBeenCalledTimes(1);
    });

    it('adjusts delay for small content (< 1KB)', () => {
      const callback = jest.fn();
      const { result } = renderHook(() => useSmartDebounce(callback, 300));

      act(() => {
        result.current('test', 500); // Small content (< 1KB)
      });

      // Should use 200ms delay for small content (Math.round(300 * 2/3) = 200ms)
      act(() => {
        jest.advanceTimersByTime(199);
      });
      expect(callback).not.toHaveBeenCalled();

      act(() => {
        jest.advanceTimersByTime(1);
      });
      expect(callback).toHaveBeenCalled();
    });

    it('handles boundary test at exactly SMALL_CONTENT_DEBOUNCE threshold', () => {
      const callback = jest.fn();
      const { result } = renderHook(() => useSmartDebounce(callback, 300));

      // Test exactly at threshold (should use base delay, not small content delay)
      act(() => {
        result.current('test', PERFORMANCE_THRESHOLDS.SMALL_CONTENT_DEBOUNCE);
      });

      // Should use base delay (300ms) for content >= SMALL_CONTENT_DEBOUNCE
      act(() => {
        jest.advanceTimersByTime(299);
      });
      expect(callback).not.toHaveBeenCalled();

      act(() => {
        jest.advanceTimersByTime(1);
      });
      expect(callback).toHaveBeenCalled();
    });

    it('handles boundary test just below SMALL_CONTENT_DEBOUNCE threshold', () => {
      const callback = jest.fn();
      const { result } = renderHook(() => useSmartDebounce(callback, 300));

      // Test just below threshold (should use small content delay)
      act(() => {
        result.current('test', PERFORMANCE_THRESHOLDS.SMALL_CONTENT_DEBOUNCE - 1);
      });

      // Should use 200ms delay for small content (< SMALL_CONTENT_DEBOUNCE)
      act(() => {
        jest.advanceTimersByTime(199);
      });
      expect(callback).not.toHaveBeenCalled();

      act(() => {
        jest.advanceTimersByTime(1);
      });
      expect(callback).toHaveBeenCalled();
    });

    it('adjusts delay for medium content (10KB - 50KB)', () => {
      const callback = jest.fn();
      const { result } = renderHook(() => useSmartDebounce(callback, 300));

      act(() => {
        result.current('test', 25000); // 25KB
      });

      // Should use 399ms delay for medium content (Math.round(300 * 1.33) = 399ms)
      act(() => {
        jest.advanceTimersByTime(398);
      });
      expect(callback).not.toHaveBeenCalled();

      act(() => {
        jest.advanceTimersByTime(1);
      });
      expect(callback).toHaveBeenCalled();
    });

    it('adjusts delay for large content (> 50KB)', () => {
      const callback = jest.fn();
      const { result } = renderHook(() => useSmartDebounce(callback, 300));

      act(() => {
        result.current('test', 75000); // 75KB
      });

      // Should use 600ms delay for large content
      act(() => {
        jest.advanceTimersByTime(599);
      });
      expect(callback).not.toHaveBeenCalled();

      act(() => {
        jest.advanceTimersByTime(1);
      });
      expect(callback).toHaveBeenCalled();
    });

    it('cancels previous timeout on new call', () => {
      const callback = jest.fn();
      const { result } = renderHook(() => useSmartDebounce(callback, 300));

      act(() => {
        result.current('first');
      });

      act(() => {
        jest.advanceTimersByTime(100);
      });

      act(() => {
        result.current('second');
      });

      act(() => {
        jest.advanceTimersByTime(300);
      });

      expect(callback).toHaveBeenCalledTimes(1);
      expect(callback).toHaveBeenCalledWith('second');
    });

    it('respects custom base delay', () => {
      const callback = jest.fn();
      const { result } = renderHook(() => useSmartDebounce(callback, 500));

      act(() => {
        result.current('test', 5000); // Medium content (1KB-10KB range, uses baseDelay as-is)
      });

      act(() => {
        jest.advanceTimersByTime(499); // Should use 500ms (custom baseDelay)
      });
      expect(callback).not.toHaveBeenCalled();

      act(() => {
        jest.advanceTimersByTime(1);
      });
      expect(callback).toHaveBeenCalled();
    });

    it('handles zero content size', () => {
      const callback = jest.fn();
      const { result } = renderHook(() => useSmartDebounce(callback, 300));

      act(() => {
        result.current('test', 0);
      });

      // Zero content size should use reduced delay (Math.round(300 * 2/3) = 200ms)
      act(() => {
        jest.advanceTimersByTime(199);
      });
      expect(callback).not.toHaveBeenCalled();

      act(() => {
        jest.advanceTimersByTime(1);
      });
      expect(callback).toHaveBeenCalled();
    });
  });

  describe('withPerformanceOptimization', () => {
    const TestComponent = ({ content, variant, readOnly, testId }) => (
      <div data-testid={testId || 'test-component'}>
        Content: {content}, Variant: {variant}, ReadOnly: {readOnly ? 'true' : 'false'}
      </div>
    );

    it('creates a memoized component', () => {
      const OptimizedComponent = withPerformanceOptimization(TestComponent);

      expect(OptimizedComponent).toBeDefined();
      expect(typeof OptimizedComponent).toBe('object'); // React.memo returns an object
      expect(OptimizedComponent.$$typeof).toBeDefined(); // React component symbol
    });

    it('prevents re-render when props have not changed', () => {
      const OptimizedComponent = withPerformanceOptimization(TestComponent);
      const renderSpy = jest.fn();

      const SpyComponent = (props) => {
        renderSpy();
        return <TestComponent {...props} />;
      };

      const OptimizedSpyComponent = withPerformanceOptimization(SpyComponent);

      const { rerender } = render(
        <OptimizedSpyComponent
          content="test content"
          variant="email"
          readOnly={false}
        />
      );

      expect(renderSpy).toHaveBeenCalledTimes(1);

      // Re-render with same props
      rerender(
        <OptimizedSpyComponent
          content="test content"
          variant="email"
          readOnly={false}
        />
      );

      expect(renderSpy).toHaveBeenCalledTimes(1); // Should not re-render
    });

    it('allows re-render when content changes', () => {
      const OptimizedComponent = withPerformanceOptimization(TestComponent);

      const { rerender } = render(
        <OptimizedComponent
          content="original content"
          variant="email"
          readOnly={false}
        />
      );

      expect(screen.getByText('Content: original content, Variant: email, ReadOnly: false')).toBeInTheDocument();

      rerender(
        <OptimizedComponent
          content="updated content"
          variant="email"
          readOnly={false}
        />
      );

      expect(screen.getByText('Content: updated content, Variant: email, ReadOnly: false')).toBeInTheDocument();
    });

    it('allows re-render when variant changes', () => {
      const OptimizedComponent = withPerformanceOptimization(TestComponent);

      const { rerender } = render(
        <OptimizedComponent
          content="test content"
          variant="email"
          readOnly={false}
        />
      );

      expect(screen.getByText('Content: test content, Variant: email, ReadOnly: false')).toBeInTheDocument();

      rerender(
        <OptimizedComponent
          content="test content"
          variant="inapp"
          readOnly={false}
        />
      );

      expect(screen.getByText('Content: test content, Variant: inapp, ReadOnly: false')).toBeInTheDocument();
    });

    it('allows re-render when readOnly changes', () => {
      const OptimizedComponent = withPerformanceOptimization(TestComponent);

      const { rerender } = render(
        <OptimizedComponent
          content="test content"
          variant="email"
          readOnly={false}
        />
      );

      expect(screen.getByText('Content: test content, Variant: email, ReadOnly: false')).toBeInTheDocument();

      rerender(
        <OptimizedComponent
          content="test content"
          variant="email"
          readOnly={true}
        />
      );

      expect(screen.getByText('Content: test content, Variant: email, ReadOnly: true')).toBeInTheDocument();
    });

    it('handles multiple prop changes', () => {
      const OptimizedComponent = withPerformanceOptimization(TestComponent);

      const { rerender } = render(
        <OptimizedComponent
          content="original"
          variant="email"
          readOnly={false}
        />
      );

      rerender(
        <OptimizedComponent
          content="updated"
          variant="inapp"
          readOnly={true}
        />
      );

      expect(screen.getByText('Content: updated, Variant: inapp, ReadOnly: true')).toBeInTheDocument();
    });

    it('ignores other props changes', () => {
      const renderSpy = jest.fn();

      const SpyComponent = (props) => {
        renderSpy();
        return <TestComponent {...props} />;
      };

      const OptimizedComponent = withPerformanceOptimization(SpyComponent);

      const { rerender } = render(
        <OptimizedComponent
          content="test content"
          variant="email"
          readOnly={false}
          otherProp="value1"
        />
      );

      expect(renderSpy).toHaveBeenCalledTimes(1);

      // Change only otherProp
      rerender(
        <OptimizedComponent
          content="test content"
          variant="email"
          readOnly={false}
          otherProp="value2"
        />
      );

      expect(renderSpy).toHaveBeenCalledTimes(1); // Should not re-render
    });

    it('handles undefined props gracefully', () => {
      const OptimizedComponent = withPerformanceOptimization(TestComponent);

      expect(() => {
        render(
          <OptimizedComponent
            content={undefined}
            variant={undefined}
            readOnly={undefined}
          />
        );
      }).not.toThrow();
    });

    it('maintains component functionality', () => {
      const OptimizedComponent = withPerformanceOptimization(TestComponent);

      render(
        <OptimizedComponent
          content="functional test"
          variant="email"
          readOnly={true}
          testId="optimized-component"
        />
      );

      expect(screen.getByTestId('optimized-component')).toBeInTheDocument();
      expect(screen.getByText(/Content: functional test/)).toBeInTheDocument();
    });
  });

  describe('useCleanup', () => {
    it('calls cleanup function on unmount', () => {
      const cleanup = jest.fn();
      const { unmount } = renderHook(() => useCleanup(cleanup));

      expect(cleanup).not.toHaveBeenCalled();

      unmount();

      expect(cleanup).toHaveBeenCalledTimes(1);
    });

    it('handles multiple mount/unmount cycles', () => {
      const cleanup = jest.fn();
      const { unmount, rerender } = renderHook(() => useCleanup(cleanup));

      rerender();
      expect(cleanup).not.toHaveBeenCalled();

      unmount();
      expect(cleanup).toHaveBeenCalledTimes(1);
    });
  });

  describe('analyzeContentSize', () => {
    it('analyzes small content (< 10KB)', () => {
      const content = 'a'.repeat(5000);
      const result = analyzeContentSize(content);

      expect(result.size).toBe(5000);
      expect(result.isSmall).toBe(true);
      expect(result.isMedium).toBe(true);
      expect(result.isLarge).toBe(false);
      expect(result.shouldOptimize).toBe(false);
      expect(result.recommendedDebounce).toBe(200);
    });

    it('analyzes medium content (10KB - 50KB)', () => {
      const content = 'a'.repeat(25000);
      const result = analyzeContentSize(content);

      expect(result.size).toBe(25000);
      expect(result.isSmall).toBe(false);
      expect(result.isMedium).toBe(true);
      expect(result.isLarge).toBe(false);
      expect(result.shouldOptimize).toBe(true);
      expect(result.recommendedDebounce).toBe(400);
    });

    it('analyzes large content (>= 50KB)', () => {
      const content = 'a'.repeat(75000);
      const result = analyzeContentSize(content);

      expect(result.size).toBe(75000);
      expect(result.isSmall).toBe(false);
      expect(result.isMedium).toBe(false);
      expect(result.isLarge).toBe(true);
      expect(result.shouldOptimize).toBe(true);
      expect(result.recommendedDebounce).toBe(600);
    });

    it('handles empty content', () => {
      const result = analyzeContentSize('');

      expect(result.size).toBe(0);
      expect(result.isSmall).toBe(true);
      expect(result.shouldOptimize).toBe(false);
    });

    it('handles null content', () => {
      const result = analyzeContentSize(null);

      expect(result.size).toBe(0);
      expect(result.isSmall).toBe(true);
    });

    it('handles undefined content', () => {
      const result = analyzeContentSize(undefined);

      expect(result.size).toBe(0);
      expect(result.isSmall).toBe(true);
    });

    it('handles non-string content', () => {
      const result = analyzeContentSize(12345);

      expect(result.size).toBe(0);
      expect(result.isSmall).toBe(true);
    });

    it('provides correct size thresholds', () => {
      const exactly10KB = analyzeContentSize('a'.repeat(10000));
      expect(exactly10KB.isSmall).toBe(false);
      expect(exactly10KB.shouldOptimize).toBe(false);

      const exactly50KB = analyzeContentSize('a'.repeat(50000));
      expect(exactly50KB.isMedium).toBe(false);
      expect(exactly50KB.isLarge).toBe(true);
    });
  });

  describe('useVirtualization', () => {
    it('returns content as-is for small content', () => {
      const content = 'a'.repeat(5000);
      const { result } = renderHook(() => useVirtualization(content, 100000));

      expect(result.current.content).toBe(content);
      expect(result.current.isVirtualized).toBe(false);
    });

    it('returns content as-is when below threshold', () => {
      const content = 'a'.repeat(50000);
      const { result } = renderHook(() => useVirtualization(content, 100000));

      expect(result.current.content).toBe(content);
      expect(result.current.isVirtualized).toBe(false);
    });

    it('truncates very large content', () => {
      const content = 'a'.repeat(150000);
      const { result } = renderHook(() => useVirtualization(content, 100000));

      expect(result.current.isVirtualized).toBe(true);
      expect(result.current.originalSize).toBe(150000);
      expect(result.current.content.length).toBeLessThan(content.length);
      expect(result.current.content).toContain('Content truncated for performance');
    });

    it('truncates to 50KB for large content', () => {
      const content = 'a'.repeat(200000);
      const { result } = renderHook(() => useVirtualization(content, 100000));

      expect(result.current.isVirtualized).toBe(true);
      expect(result.current.content).toContain('a'.repeat(50000));
    });

    it('handles custom threshold', () => {
      const content = 'a'.repeat(60000);
      const { result } = renderHook(() => useVirtualization(content, 50000));

      expect(result.current.isVirtualized).toBe(true);
    });

    it('handles empty content', () => {
      const { result } = renderHook(() => useVirtualization(''));

      expect(result.current.content).toBe('');
      expect(result.current.isVirtualized).toBe(false);
    });

    it('handles null content', () => {
      const { result } = renderHook(() => useVirtualization(null));

      expect(result.current.content).toBe(null);
      expect(result.current.isVirtualized).toBe(false);
    });

    it('memoizes result', () => {
      const content = 'a'.repeat(5000);
      const { result, rerender } = renderHook(
        ({ c }) => useVirtualization(c, 100000),
        { initialProps: { c: content } }
      );

      const firstResult = result.current;

      rerender({ c: content });

      expect(result.current).toBe(firstResult);
    });

    it('updates when content changes', () => {
      const content1 = 'a'.repeat(5000);
      const content2 = 'b'.repeat(5000);
      const { result, rerender } = renderHook(
        ({ c }) => useVirtualization(c, 100000),
        { initialProps: { c: content1 } }
      );

      const firstResult = result.current;

      rerender({ c: content2 });

      expect(result.current).not.toBe(firstResult);
      expect(result.current.content).toBe(content2);
    });
  });

  describe('PERFORMANCE_THRESHOLDS', () => {
    it('exports correct threshold values', () => {
      // Debounce thresholds
      expect(PERFORMANCE_THRESHOLDS.SMALL_CONTENT_DEBOUNCE).toBe(1000);
      expect(PERFORMANCE_THRESHOLDS.MEDIUM_CONTENT_DEBOUNCE).toBe(10000);
      expect(PERFORMANCE_THRESHOLDS.LARGE_CONTENT_DEBOUNCE).toBe(50000);

      // Analysis thresholds
      expect(PERFORMANCE_THRESHOLDS.SMALL_CONTENT_ANALYSIS).toBe(10000);
      expect(PERFORMANCE_THRESHOLDS.LARGE_CONTENT_ANALYSIS).toBe(50000);
      expect(PERFORMANCE_THRESHOLDS.HUGE_CONTENT).toBe(100000);
    });

    it('exports correct debounce values', () => {
      expect(PERFORMANCE_THRESHOLDS.DEBOUNCE_FAST).toBe(200);
      expect(PERFORMANCE_THRESHOLDS.DEBOUNCE_NORMAL).toBe(300);
      expect(PERFORMANCE_THRESHOLDS.DEBOUNCE_SLOW).toBe(600);
    });

    it('has consistent threshold ordering', () => {
      // Debounce thresholds ordering
      expect(PERFORMANCE_THRESHOLDS.SMALL_CONTENT_DEBOUNCE).toBeLessThan(
        PERFORMANCE_THRESHOLDS.MEDIUM_CONTENT_DEBOUNCE
      );
      expect(PERFORMANCE_THRESHOLDS.MEDIUM_CONTENT_DEBOUNCE).toBeLessThan(
        PERFORMANCE_THRESHOLDS.LARGE_CONTENT_DEBOUNCE
      );

      // Analysis thresholds ordering
      expect(PERFORMANCE_THRESHOLDS.SMALL_CONTENT_ANALYSIS).toBeLessThan(
        PERFORMANCE_THRESHOLDS.LARGE_CONTENT_ANALYSIS
      );
      expect(PERFORMANCE_THRESHOLDS.LARGE_CONTENT_ANALYSIS).toBeLessThan(
        PERFORMANCE_THRESHOLDS.HUGE_CONTENT
      );
    });

    it('has consistent debounce ordering', () => {
      expect(PERFORMANCE_THRESHOLDS.DEBOUNCE_FAST).toBeLessThan(
        PERFORMANCE_THRESHOLDS.DEBOUNCE_NORMAL
      );
      expect(PERFORMANCE_THRESHOLDS.DEBOUNCE_NORMAL).toBeLessThan(
        PERFORMANCE_THRESHOLDS.DEBOUNCE_SLOW
      );
    });
  });

  describe('Integration Tests', () => {
    it('smart debounce works with content analysis', () => {
      const callback = jest.fn();
      const content = 'a'.repeat(75000);
      const analysis = analyzeContentSize(content);

      const { result } = renderHook(() => useSmartDebounce(callback, 300));

      act(() => {
        result.current(content, analysis.size);
      });

      act(() => {
        jest.advanceTimersByTime(analysis.recommendedDebounce);
      });

      expect(callback).toHaveBeenCalledWith(content);
    });

    it('virtualization and content analysis work together', () => {
      const largeContent = 'a'.repeat(150000);
      const analysis = analyzeContentSize(largeContent);

      expect(analysis.isLarge).toBe(true);
      expect(analysis.shouldOptimize).toBe(true);

      const { result } = renderHook(() => useVirtualization(largeContent, 100000));

      expect(result.current.isVirtualized).toBe(true);
      expect(result.current.content.length).toBeLessThan(largeContent.length);
    });

    it('handles realistic editor scenarios', () => {
      // Small email template
      const smallEmail = '<p>Hello World</p>';
      const smallAnalysis = analyzeContentSize(smallEmail);
      expect(smallAnalysis.shouldOptimize).toBe(false);
      expect(smallAnalysis.recommendedDebounce).toBe(200);

      // Large email template with images
      const largeEmail = '<div>' + 'a'.repeat(60000) + '</div>';
      const largeAnalysis = analyzeContentSize(largeEmail);
      expect(largeAnalysis.shouldOptimize).toBe(true);
      expect(largeAnalysis.recommendedDebounce).toBe(600);
    });
  });

  describe('Edge Cases', () => {
    it('handles rapid successive calls to smart debounce', () => {
      const callback = jest.fn();
      const { result } = renderHook(() => useSmartDebounce(callback, 300));

      act(() => {
        for (let i = 0; i < 10; i++) {
          result.current(`value${i}`, 0); // Zero content size = small content delay (200ms)
        }
      });

      act(() => {
        jest.advanceTimersByTime(200);
      });

      expect(callback).toHaveBeenCalledTimes(1);
      expect(callback).toHaveBeenCalledWith('value9');
    });

    it('handles content at exact threshold boundaries', () => {
      const exactly10KB = analyzeContentSize('a'.repeat(10000));
      expect(exactly10KB.isSmall).toBe(false);
      expect(exactly10KB.isMedium).toBe(true);

      const exactly50KB = analyzeContentSize('a'.repeat(50000));
      expect(exactly50KB.isMedium).toBe(false);
      expect(exactly50KB.isLarge).toBe(true);

      // Exactly at threshold (100000) should be virtualized (>= threshold)
      const exactly100KB = 'a'.repeat(100000);
      const { result } = renderHook(() => useVirtualization(exactly100KB, 100000));
      expect(result.current.isVirtualized).toBe(true);

      // Just below threshold should NOT be virtualized
      const justBelow100KB = 'a'.repeat(99999);
      const { result: result2 } = renderHook(() => useVirtualization(justBelow100KB, 100000));
      expect(result2.current.isVirtualized).toBe(false);
    });

    it('handles very small debounce delays', () => {
      const callback = jest.fn();
      const { result } = renderHook(() => useSmartDebounce(callback, 1));

      act(() => {
        result.current('test', 100);
      });

      act(() => {
        jest.advanceTimersByTime(200);
      });

      expect(callback).toHaveBeenCalled();
    });
  });

  describe('Performance Benchmarking', () => {
    it('measures smart debounce performance', () => {
      const callback = jest.fn();
      const startTime = performance.now();

      const { result } = renderHook(() => useSmartDebounce(callback, 300));

      act(() => {
        for (let i = 0; i < 1000; i++) {
          result.current(`test${i}`, 1000);
        }
      });

      const endTime = performance.now();
      const duration = endTime - startTime;

      // Should complete quickly (< 100ms for 1000 calls)
      expect(duration).toBeLessThan(100);
    });

    it('measures content analysis performance', () => {
      const startTime = performance.now();

      for (let i = 0; i < 100; i++) {
        const content = 'a'.repeat(i * 1000);
        analyzeContentSize(content);
      }

      const endTime = performance.now();
      const duration = endTime - startTime;

      // Should complete quickly (< 50ms for 100 analyses)
      expect(duration).toBeLessThan(50);
    });

    it('measures virtualization performance with large content', () => {
      const largeContent = 'a'.repeat(500000); // 500KB
      const startTime = performance.now();

      const { result } = renderHook(() => useVirtualization(largeContent, 100000));

      const endTime = performance.now();
      const duration = endTime - startTime;

      expect(result.current.isVirtualized).toBe(true);
      expect(duration).toBeLessThan(50); // Should be fast even for large content
    });
  });

  describe('Memory Management', () => {
    it('properly cleans up debounce timeouts', () => {
      const callback = jest.fn();
      const { result, unmount } = renderHook(() => useSmartDebounce(callback, 300));

      act(() => {
        result.current('test');
      });

      // Unmount before timeout completes
      unmount();

      act(() => {
        jest.advanceTimersByTime(300);
      });

      // After unmount and timer advance, callback should NOT be called
      // The cleanup effect should have cleared the pending timeout
      expect(callback).not.toHaveBeenCalled();
    });

    it('handles multiple cleanup functions', () => {
      const cleanup1 = jest.fn();
      const cleanup2 = jest.fn();

      const { unmount: unmount1 } = renderHook(() => useCleanup(cleanup1));
      const { unmount: unmount2 } = renderHook(() => useCleanup(cleanup2));

      unmount1();
      expect(cleanup1).toHaveBeenCalledTimes(1);
      expect(cleanup2).not.toHaveBeenCalled();

      unmount2();
      expect(cleanup2).toHaveBeenCalledTimes(1);
    });

    it('prevents memory leaks with large content virtualization', () => {
      const contents = [];

      // Create multiple large content instances
      for (let i = 0; i < 10; i++) {
        contents.push('a'.repeat(200000)); // 200KB each
      }

      const { result, rerender } = renderHook(
        ({ content }) => useVirtualization(content, 100000),
        { initialProps: { content: contents[0] } }
      );

      // Switch between different large contents
      contents.forEach(content => {
        rerender({ content });
        expect(result.current.isVirtualized).toBe(true);
        expect(result.current.content.length).toBeLessThan(content.length);
      });
    });
  });

  describe('Real-world Scenarios', () => {
    it('handles typical HTML email content', () => {
      const htmlEmail = `
        <html>
          <body>
            <div style="font-family: Arial, sans-serif;">
              <h1>Welcome to our newsletter!</h1>
              <p>This is a typical email with some content.</p>
              <img src="https://example.com/image.jpg" alt="Example" />
              <table>
                <tr><td>Cell 1</td><td>Cell 2</td></tr>
              </table>
            </div>
          </body>
        </html>
      `;

      const analysis = analyzeContentSize(htmlEmail);
      expect(analysis.shouldOptimize).toBe(false); // Small email
      expect(analysis.recommendedDebounce).toBe(200);

      const { result } = renderHook(() => useVirtualization(htmlEmail));
      expect(result.current.isVirtualized).toBe(false);
    });

    it('handles large marketing email with inline styles', () => {
      const largeEmail = `
        <html>
          <head><style>/* Large CSS block */</style></head>
          <body>
            ${'<div style="margin: 10px; padding: 20px;">'.repeat(2000)}
              Large email content with many nested divs
            ${'</div>'.repeat(2000)}
          </body>
        </html>
      `;

      const analysis = analyzeContentSize(largeEmail);
      expect(analysis.shouldOptimize).toBe(true);
      expect(analysis.isLarge).toBe(true);

      const { result } = renderHook(() => useVirtualization(largeEmail, 50000));
      expect(result.current.isVirtualized).toBe(true);
    });

    it('optimizes editor performance for different content types', () => {
      const scenarios = [
        { name: 'Plain text', content: 'Hello world!', expectOptimize: false },
        { name: 'Small HTML', content: '<p>Hello <b>world</b>!</p>', expectOptimize: false },
        { name: 'Medium email', content: '<div>' + 'a'.repeat(15000) + '</div>', expectOptimize: true },
        { name: 'Large template', content: '<html>' + 'b'.repeat(60000) + '</html>', expectOptimize: true }
      ];

      scenarios.forEach(scenario => {
        const analysis = analyzeContentSize(scenario.content);
        expect(analysis.shouldOptimize).toBe(scenario.expectOptimize);

        if (scenario.expectOptimize) {
          expect(analysis.recommendedDebounce).toBeGreaterThan(200);
        } else {
          expect(analysis.recommendedDebounce).toBe(200);
        }
      });
    });

    it('integrates all performance optimizations', () => {
      const TestComponent = ({ content }) => <div>{content}</div>;
      const OptimizedComponent = withPerformanceOptimization(TestComponent);

      const largeContent = 'a'.repeat(75000);
      const analysis = analyzeContentSize(largeContent);

      // Test virtualization within a hook context
      const { result } = renderHook(() => useVirtualization(largeContent, 50000));
      const virtualization = result.current;

      // Should recommend optimizations for large content
      expect(analysis.shouldOptimize).toBe(true);
      expect(analysis.recommendedDebounce).toBe(600);
      expect(virtualization.isVirtualized).toBe(true);

      // Component should render with optimized content
      const { rerender } = render(
        <OptimizedComponent content={virtualization.content} />
      );

      // Should not re-render with same content
      rerender(<OptimizedComponent content={virtualization.content} />);
    });
  });

  describe('Cross-browser Compatibility', () => {
    it('works with different timer implementations', () => {
      const originalSetTimeout = global.setTimeout;
      const originalClearTimeout = global.clearTimeout;

      // Mock different timer behavior
      const mockSetTimeout = jest.fn((fn, delay) => originalSetTimeout(fn, delay));
      const mockClearTimeout = jest.fn(originalClearTimeout);

      global.setTimeout = mockSetTimeout;
      global.clearTimeout = mockClearTimeout;

      const callback = jest.fn();
      const { result } = renderHook(() => useSmartDebounce(callback, 300));

      act(() => {
        result.current('test');
      });

      expect(mockSetTimeout).toHaveBeenCalled();

      act(() => {
        result.current('test2');
      });

      expect(mockClearTimeout).toHaveBeenCalled();

      // Restore original functions
      global.setTimeout = originalSetTimeout;
      global.clearTimeout = originalClearTimeout;
    });

    it('handles performance.now() availability', () => {
      const originalPerformance = global.performance;

      // Test without performance.now()
      global.performance = undefined;

      expect(() => {
        analyzeContentSize('test content');
      }).not.toThrow();

      // Restore
      global.performance = originalPerformance;
    });

    it('works with different React versions', () => {
      // Test that hooks work correctly
      const { result } = renderHook(() => {
        const debounce = useSmartDebounce(() => {}, 300);
        const cleanup = useCleanup(() => {});
        const virtualization = useVirtualization('test');

        return { debounce, cleanup, virtualization };
      });

      expect(result.current.debounce).toBeInstanceOf(Function);
      expect(result.current.virtualization).toHaveProperty('content');
      expect(result.current.virtualization).toHaveProperty('isVirtualized');
    });
  });

  describe('Error Resilience', () => {
    it('handles callback errors in debounce', () => {
      const errorCallback = jest.fn(() => {
        throw new Error('Callback error');
      });

      const { result } = renderHook(() => useSmartDebounce(errorCallback, 300));

      act(() => {
        result.current('test');
      });

      expect(() => {
        act(() => {
          jest.advanceTimersByTime(300);
        });
      }).toThrow('Callback error');

      expect(errorCallback).toHaveBeenCalled();
    });

    it('handles cleanup function errors', () => {
      const errorCleanup = jest.fn(() => {
        throw new Error('Cleanup error');
      });

      // Test that the cleanup function is properly set up
      const { unmount } = renderHook(() => useCleanup(errorCleanup));

      // The cleanup function should be called on unmount
      // Note: React's error handling might suppress the error in test environment
      try {
        unmount();
      } catch (error) {
        expect(error.message).toBe('Cleanup error');
      }

      expect(errorCleanup).toHaveBeenCalled();
    });

    it('handles extreme content sizes gracefully', () => {
      // Very large content (10MB)
      const extremeContent = 'a'.repeat(10000000);

      expect(() => {
        const analysis = analyzeContentSize(extremeContent);
        expect(analysis.isLarge).toBe(true);
      }).not.toThrow();

      expect(() => {
        const { result } = renderHook(() => useVirtualization(extremeContent, 100000));
        expect(result.current.isVirtualized).toBe(true);
      }).not.toThrow();
    });

    it('handles invalid content types gracefully', () => {
      const invalidInputs = [
        null,
        undefined,
        123,
        {},
        [],
        true
      ];

      invalidInputs.forEach(input => {
        expect(() => {
          analyzeContentSize(input);
        }).not.toThrow();

        expect(() => {
          const { result } = renderHook(() => useVirtualization(input));
          expect(result.current).toBeDefined();
        }).not.toThrow();
      });

      // Test Symbol separately as it might behave differently
      if (typeof Symbol !== 'undefined') {
        expect(() => {
          analyzeContentSize(Symbol('test'));
        }).not.toThrow();

        expect(() => {
          const { result } = renderHook(() => useVirtualization(Symbol('test')));
          expect(result.current).toBeDefined();
        }).not.toThrow();
      }
    });
  });
});

