/**
 * HTMLEditorTesting Component Tests
 *
 * Tests for the console-controlled HTMLEditor testing component
 */

import React from 'react';
import { render, screen, fireEvent, act } from '@testing-library/react';
import '@testing-library/jest-dom';
import HTMLEditorTesting from '../HTMLEditorTesting';
import { HTML_EDITOR_VARIANTS } from '../../../../v2Components/HtmlEditor/constants';
import { LAYOUT_TYPES } from '../../../../v2Components/HtmlEditor/components/InAppPreviewPane/constants';

// Mock the HTMLEditor component
jest.mock('../../../../v2Components/HtmlEditor', () => {
  return function MockHTMLEditor({ variant, layoutType, initialContent, onContentChange, onSave }) {
    return (
      <div data-testid="mock-html-editor">
        <div data-testid="editor-variant">{variant}</div>
        <div data-testid="editor-layout">{layoutType}</div>
        <div data-testid="editor-content">{initialContent}</div>
        <button
          onClick={() => onContentChange && onContentChange('<p>Changed content</p>')}
          data-testid="trigger-content-change"
        >
          Change Content
        </button>
        <button
          onClick={() => onSave && onSave('<p>Saved content</p>')}
          data-testid="trigger-save"
        >
          Save
        </button>
      </div>
    );
  };
});

// Mock IntlProvider
jest.mock('react-intl', () => ({
  IntlProvider: ({ children }) => <div data-testid="intl-provider">{children}</div>
}));

describe('HTMLEditorTesting', () => {
  let consoleSpy;

  beforeEach(() => {
    // Mock console methods
    consoleSpy = {
      log: jest.spyOn(console, 'log').mockImplementation(() => { }),
      error: jest.spyOn(console, 'error').mockImplementation(() => { })
    };

    // Clear any existing window.htmlEditorTest
    if (window.htmlEditorTest) {
      delete window.htmlEditorTest;
    }
  });

  afterEach(() => {
    // Restore console methods
    consoleSpy.log.mockRestore();
    consoleSpy.error.mockRestore();

    // Clean up window.htmlEditorTest
    if (window.htmlEditorTest) {
      delete window.htmlEditorTest;
    }
  });

  describe('Initial Render', () => {
    it('renders nothing initially (hidden by default)', () => {
      render(<HTMLEditorTesting />);
      expect(screen.queryByTestId('mock-html-editor')).not.toBeInTheDocument();
    });

    it('sets up console interface on mount', () => {
      render(<HTMLEditorTesting />);

      expect(window.htmlEditorTest).toBeDefined();
      expect(typeof window.htmlEditorTest.show).toBe('function');
      expect(typeof window.htmlEditorTest.hide).toBe('function');
      expect(typeof window.htmlEditorTest.toggle).toBe('function');
      expect(typeof window.htmlEditorTest.setVariant).toBe('function');
      expect(typeof window.htmlEditorTest.setLayout).toBe('function');
      expect(typeof window.htmlEditorTest.setContent).toBe('function');
      expect(typeof window.htmlEditorTest.getContent).toBe('function');
      expect(typeof window.htmlEditorTest.status).toBe('function');
      expect(typeof window.htmlEditorTest.help).toBe('function');
    });
  });

  describe('Visibility Control', () => {
    it('shows editor when show() is called', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
      });

      expect(screen.getByTestId('mock-html-editor')).toBeInTheDocument();
    });

    it('hides editor when hide() is called', () => {
      render(<HTMLEditorTesting />);

      // Show first
      act(() => {
        window.htmlEditorTest.show();
      });
      expect(screen.getByTestId('mock-html-editor')).toBeInTheDocument();

      // Then hide
      act(() => {
        window.htmlEditorTest.hide();
      });
      expect(screen.queryByTestId('mock-html-editor')).not.toBeInTheDocument();
    });

    it('toggles editor visibility with toggle()', () => {
      render(<HTMLEditorTesting />);

      // Toggle to show
      act(() => {
        window.htmlEditorTest.toggle();
      });
      expect(screen.getByTestId('mock-html-editor')).toBeInTheDocument();
      // Toggle to hide
      act(() => {
        window.htmlEditorTest.toggle();
      });
      expect(screen.queryByTestId('mock-html-editor')).not.toBeInTheDocument();
    });

    it('closes editor when close button is clicked', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
      });

      const closeButton = screen.getByText('Close');
      fireEvent.click(closeButton);

      expect(screen.queryByTestId('mock-html-editor')).not.toBeInTheDocument();
    });
  });

  describe('Variant Control', () => {
    it('sets variant to email', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
        window.htmlEditorTest.setVariant('email');
      });

      expect(screen.getByTestId('editor-variant')).toHaveTextContent('email');
    });

    it('sets variant to inapp', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
        window.htmlEditorTest.setVariant('inapp');
      });

      expect(screen.getByTestId('editor-variant')).toHaveTextContent('inapp');
    });

    it('rejects invalid variant', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.setVariant('invalid');
      });

      expect(consoleSpy.error).toHaveBeenCalledWith('❌ Invalid variant. Use: "email" or "inapp"');
    });

    it('starts with email variant by default', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
      });

      expect(screen.getByTestId('editor-variant')).toHaveTextContent(HTML_EDITOR_VARIANTS.EMAIL);
    });
  });

  describe('Layout Control', () => {
    it('sets layout to POPUP (MODAL)', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
        window.htmlEditorTest.setLayout(LAYOUT_TYPES.MODAL);
      });

      expect(screen.getByTestId('editor-layout')).toHaveTextContent(LAYOUT_TYPES.MODAL);
    });

    it('sets layout to HEADER', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
        window.htmlEditorTest.setLayout(LAYOUT_TYPES.HEADER);
      });

      expect(screen.getByTestId('editor-layout')).toHaveTextContent(LAYOUT_TYPES.HEADER);
    });

    it('sets layout to FOOTER', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
        window.htmlEditorTest.setLayout(LAYOUT_TYPES.FOOTER);
      });

      expect(screen.getByTestId('editor-layout')).toHaveTextContent(LAYOUT_TYPES.FOOTER);
    });

    it('sets layout to FULLSCREEN', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
        window.htmlEditorTest.setLayout(LAYOUT_TYPES.FULLSCREEN);
      });

      expect(screen.getByTestId('editor-layout')).toHaveTextContent(LAYOUT_TYPES.FULLSCREEN);
    });

    it('rejects invalid layout', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.setLayout('INVALID');
      });

      const validLayouts = Object.values(LAYOUT_TYPES);
      expect(consoleSpy.error).toHaveBeenCalledWith(
        `❌ Invalid layout. Use: ${validLayouts.join(', ')}`
      );
    });

    it('starts with MODAL layout by default', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
      });

      expect(screen.getByTestId('editor-layout')).toHaveTextContent(LAYOUT_TYPES.MODAL);
    });
  });

  describe('Content Control', () => {
    it('sets content', () => {
      render(<HTMLEditorTesting />);

      const newContent = '<p>New test content</p>';
      act(() => {
        window.htmlEditorTest.show();
        window.htmlEditorTest.setContent(newContent);
      });

      expect(screen.getByTestId('editor-content')).toHaveTextContent(newContent);
    });

    it('gets current content', () => {
      render(<HTMLEditorTesting />);

      const result = window.htmlEditorTest.getContent();

      expect(result).toBe('<h1>Test HTML Editor</h1><p>This is a test integration.</p>');
    });

    it('starts with default content', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
      });

      expect(screen.getByTestId('editor-content')).toHaveTextContent(
        '<h1>Test HTML Editor</h1><p>This is a test integration.</p>'
      );
    });

    it('handles content change callback', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
      });

      const changeButton = screen.getByTestId('trigger-content-change');
      fireEvent.click(changeButton);
    });

    it('handles save callback', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
      });

      const saveButton = screen.getByTestId('trigger-save');
      fireEvent.click(saveButton);
    });
  });

  describe('UI Elements', () => {
    it('displays header with current configuration', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
        window.htmlEditorTest.setVariant('inapp');
        window.htmlEditorTest.setLayout(LAYOUT_TYPES.FOOTER);
      });

      expect(screen.getByText('HTMLEditor Testing Mode')).toBeInTheDocument();
      expect(screen.getByText('Variant: inapp | Layout: FOOTER')).toBeInTheDocument();
    });

    it('renders with proper styling structure', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
      });

      // Check for main container
      const container = screen.getByTestId('mock-html-editor').closest('div[style*="position: fixed"]');
      expect(container).toBeInTheDocument();

      // Check for IntlProvider wrapper
      expect(screen.getByTestId('intl-provider')).toBeInTheDocument();
    });
  });

  describe('Cleanup', () => {
    it('cleans up console interface on unmount', () => {
      const { unmount } = render(<HTMLEditorTesting />);

      expect(window.htmlEditorTest).toBeDefined();

      unmount();

      expect(window.htmlEditorTest).toBeUndefined();
    });

    it('handles cleanup when window.htmlEditorTest does not exist', () => {
      const { unmount } = render(<HTMLEditorTesting />);

      // Manually delete it first
      delete window.htmlEditorTest;

      // Should not throw when unmounting
      expect(() => unmount()).not.toThrow();
    });
  });

  describe('Integration Scenarios', () => {
    it('switches between variants and layouts', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
        window.htmlEditorTest.setVariant('inapp');
        window.htmlEditorTest.setLayout(LAYOUT_TYPES.HEADER);
      });

      expect(screen.getByTestId('editor-variant')).toHaveTextContent('inapp');
      expect(screen.getByTestId('editor-layout')).toHaveTextContent(LAYOUT_TYPES.HEADER);

      act(() => {
        window.htmlEditorTest.setVariant('email');
        window.htmlEditorTest.setLayout(LAYOUT_TYPES.FULLSCREEN);
      });

      expect(screen.getByTestId('editor-variant')).toHaveTextContent('email');
      expect(screen.getByTestId('editor-layout')).toHaveTextContent(LAYOUT_TYPES.FULLSCREEN);
    });

    it('updates content and checks status', () => {
      render(<HTMLEditorTesting />);

      const customContent = '<div><h2>Custom Title</h2><p>Custom content here</p></div>';

      act(() => {
        window.htmlEditorTest.show();
        window.htmlEditorTest.setContent(customContent);
      });

      expect(screen.getByTestId('editor-content')).toHaveTextContent(customContent);

      // Clear previous console calls before checking status
      consoleSpy.log.mockClear();

      act(() => {
        window.htmlEditorTest.status();
      });
    });

    it('handles multiple rapid operations', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
        window.htmlEditorTest.setVariant('inapp');
        window.htmlEditorTest.setLayout(LAYOUT_TYPES.MODAL);
        window.htmlEditorTest.setContent('<p>Rapid test</p>');
        window.htmlEditorTest.hide();
        window.htmlEditorTest.show();
      });

      expect(screen.getByTestId('editor-variant')).toHaveTextContent('inapp');
      expect(screen.getByTestId('editor-layout')).toHaveTextContent(LAYOUT_TYPES.MODAL);
      expect(screen.getByTestId('editor-content')).toHaveTextContent('<p>Rapid test</p>');
    });
  });

  describe('Edge Cases', () => {
    it('handles empty content', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
        window.htmlEditorTest.setContent('');
      });

      expect(screen.getByTestId('editor-content')).toHaveTextContent('');
    });

    it('handles very long content', () => {
      render(<HTMLEditorTesting />);

      const longContent = '<p>' + 'A'.repeat(10000) + '</p>';

      act(() => {
        window.htmlEditorTest.show();
        window.htmlEditorTest.setContent(longContent);
      });

      expect(screen.getByTestId('editor-content')).toHaveTextContent(longContent);
    });

    it('handles special characters in content', () => {
      render(<HTMLEditorTesting />);

      const specialContent = '<p>Special chars: &lt;&gt;&amp;"\'</p>';

      act(() => {
        window.htmlEditorTest.show();
        window.htmlEditorTest.setContent(specialContent);
      });

      expect(screen.getByTestId('editor-content')).toHaveTextContent(specialContent);
    });

    it('handles null/undefined content gracefully', () => {
      render(<HTMLEditorTesting />);

      act(() => {
        window.htmlEditorTest.show();
        window.htmlEditorTest.setContent(null);
      });

      // Should not throw and should handle gracefully
      expect(screen.getByTestId('editor-content')).toBeInTheDocument();
    });
  });
});
