/**
 * DeviceFrame Tests
 *
 * Tests for the DeviceFrame component
 */

import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import { DEVICE_TYPES } from '../../../constants';

// Import after mocking
import DeviceFrame from '../DeviceFrame';

// Mock the entire DeviceFrame module to bypass image import issues
jest.mock('../../../../assets/Android.png', () => 'mocked-android-frame.png');
jest.mock('../../../../assets/iOS.png', () => 'mocked-ios-frame.png');

describe('DeviceFrame', () => {
  describe('Basic Rendering', () => {
    it('renders without crashing', () => {
      const { container } = render(<DeviceFrame />);
      expect(container.firstChild).toBeInTheDocument();
    });

    it('renders with default props', () => {
      const { container } = render(<DeviceFrame />);
      const frame = container.firstChild;

      expect(frame).toHaveClass('device-frame');
      expect(frame).toHaveClass('device-frame--android'); // Default device
    });

    it('renders children correctly', () => {
      render(
        <DeviceFrame>
          <div data-testid="child-content">Test Content</div>
        </DeviceFrame>
      );

      expect(screen.getByTestId('child-content')).toBeInTheDocument();
      expect(screen.getByTestId('child-content')).toHaveTextContent('Test Content');
    });

    it('renders multiple children', () => {
      render(
        <DeviceFrame>
          <div data-testid="child-1">Child 1</div>
          <div data-testid="child-2">Child 2</div>
          <div data-testid="child-3">Child 3</div>
        </DeviceFrame>
      );

      expect(screen.getByTestId('child-1')).toBeInTheDocument();
      expect(screen.getByTestId('child-2')).toBeInTheDocument();
      expect(screen.getByTestId('child-3')).toBeInTheDocument();
    });
  });

  describe('Device Types', () => {
    it('renders Android frame correctly', () => {
      const { container } = render(<DeviceFrame device={DEVICE_TYPES.ANDROID} />);
      const frame = container.firstChild;

      expect(frame).toHaveClass('device-frame--android');
      expect(frame.style.backgroundImage).toBeTruthy();
      expect(frame.style.backgroundImage).toMatch(/url\(/);
    });

    it('renders iOS frame correctly', () => {
      const { container } = render(<DeviceFrame device={DEVICE_TYPES.IOS} />);
      const frame = container.firstChild;

      expect(frame).toHaveClass('device-frame--ios');
      expect(frame.style.backgroundImage).toBeTruthy();
      expect(frame.style.backgroundImage).toMatch(/url\(/);
    });

    it('defaults to Android when no device specified', () => {
      const { container } = render(<DeviceFrame />);
      const frame = container.firstChild;

      expect(frame).toHaveClass('device-frame--android');
      expect(frame.style.backgroundImage).toBeTruthy();
      expect(frame.style.backgroundImage).toMatch(/url\(/);
    });

    it('handles device type case insensitivity', () => {
      const { container: androidContainer } = render(
        <DeviceFrame device={DEVICE_TYPES.ANDROID} />
      );
      expect(androidContainer.firstChild).toHaveClass('device-frame--android');

      const { container: iosContainer } = render(
        <DeviceFrame device={DEVICE_TYPES.IOS} />
      );
      expect(iosContainer.firstChild).toHaveClass('device-frame--ios');
    });
  });

  describe('Styling', () => {
    it('applies correct dimensions', () => {
      const { container } = render(<DeviceFrame />);
      const frame = container.firstChild;

      expect(frame.style.width).toBe('450px');
      expect(frame.style.height).toBe('920px');
    });

    it('applies unified dimensions for both devices', () => {
      const { container: androidContainer } = render(
        <DeviceFrame device={DEVICE_TYPES.ANDROID} />
      );
      const androidFrame = androidContainer.firstChild;

      const { container: iosContainer } = render(
        <DeviceFrame device={DEVICE_TYPES.IOS} />
      );
      const iosFrame = iosContainer.firstChild;

      expect(androidFrame.style.width).toBe(iosFrame.style.width);
      expect(androidFrame.style.height).toBe(iosFrame.style.height);
    });

    it('applies background styles correctly', () => {
      const { container } = render(<DeviceFrame />);
      const frame = container.firstChild;

      expect(frame.style.position).toBe('relative');
      expect(frame.style.display).toBe('inline-block');
      expect(frame.style.backgroundRepeat).toBe('no-repeat');
      expect(frame.style.backgroundPosition).toBe('center');
      expect(frame.style.backgroundSize).toBe('contain');
    });

    it('sets correct background image for Android', () => {
      const { container } = render(<DeviceFrame device={DEVICE_TYPES.ANDROID} />);
      const frame = container.firstChild;

      // Verify background image is set (actual mock value may vary)
      expect(frame.style.backgroundImage).toBeTruthy();
      expect(frame.style.backgroundImage).toMatch(/^url\(.+\)$/);
    });

    it('sets correct background image for iOS', () => {
      const { container } = render(<DeviceFrame device={DEVICE_TYPES.IOS} />);
      const frame = container.firstChild;

      // Verify background image is set (actual mock value may vary)
      expect(frame.style.backgroundImage).toBeTruthy();
      expect(frame.style.backgroundImage).toMatch(/^url\(.+\)$/);
    });
  });

  describe('Custom Props', () => {
    it('accepts and applies custom className', () => {
      const { container } = render(<DeviceFrame className="custom-frame" />);
      const frame = container.firstChild;

      expect(frame).toHaveClass('custom-frame');
      expect(frame).toHaveClass('device-frame'); // Base class still present
    });

    it('merges multiple classNames correctly', () => {
      const { container } = render(
        <DeviceFrame className="custom-class another-class" />
      );
      const frame = container.firstChild;

      expect(frame).toHaveClass('custom-class');
      expect(frame).toHaveClass('another-class');
      expect(frame).toHaveClass('device-frame');
    });

    it('forwards additional props to container', () => {
      const { container } = render(
        <DeviceFrame data-testid="custom-frame" aria-label="Device Preview" />
      );
      const frame = container.firstChild;

      expect(frame).toHaveAttribute('data-testid', 'custom-frame');
      expect(frame).toHaveAttribute('aria-label', 'Device Preview');
    });

    it('handles onClick event', () => {
      const handleClick = jest.fn();
      const { container } = render(<DeviceFrame onClick={handleClick} />);
      const frame = container.firstChild;

      frame.click();
      expect(handleClick).toHaveBeenCalledTimes(1);
    });

    it('handles custom styles via props', () => {
      const customStyle = { border: '2px solid red' };
      const { container } = render(<DeviceFrame style={customStyle} />);
      const frame = container.firstChild;

      // Note: inline styles from props override component styles
      expect(frame.style.border).toBe('2px solid red');
    });
  });

  describe('PropTypes Validation', () => {
    // Suppress console errors for these tests
    const originalError = console.error;
    beforeAll(() => {
      console.error = jest.fn();
    });
    afterAll(() => {
      console.error = originalError;
    });

    it('accepts valid device types', () => {
      expect(() => {
        render(<DeviceFrame device={DEVICE_TYPES.ANDROID} />);
      }).not.toThrow();

      expect(() => {
        render(<DeviceFrame device={DEVICE_TYPES.IOS} />);
      }).not.toThrow();
    });

    it('accepts string className', () => {
      expect(() => {
        render(<DeviceFrame className="test-class" />);
      }).not.toThrow();
    });

    it('accepts valid children types', () => {
      expect(() => {
        render(<DeviceFrame><div>Test</div></DeviceFrame>);
      }).not.toThrow();

      expect(() => {
        render(<DeviceFrame>Plain text</DeviceFrame>);
      }).not.toThrow();

      expect(() => {
        render(<DeviceFrame>{null}</DeviceFrame>);
      }).not.toThrow();
    });
  });

  describe('Edge Cases', () => {
    it('renders without children', () => {
      const { container } = render(<DeviceFrame />);
      expect(container.firstChild).toBeInTheDocument();
    });

    it('renders with null children', () => {
      const { container } = render(<DeviceFrame>{null}</DeviceFrame>);
      expect(container.firstChild).toBeInTheDocument();
    });

    it('renders with undefined children', () => {
      const { container } = render(<DeviceFrame>{undefined}</DeviceFrame>);
      expect(container.firstChild).toBeInTheDocument();
    });

    it('renders with empty string className', () => {
      const { container } = render(<DeviceFrame className="" />);
      const frame = container.firstChild;

      expect(frame).toHaveClass('device-frame');
    });

    it('renders with fragment children', () => {
      render(
        <DeviceFrame>
          <>
            <div data-testid="fragment-child-1">Child 1</div>
            <div data-testid="fragment-child-2">Child 2</div>
          </>
        </DeviceFrame>
      );

      expect(screen.getByTestId('fragment-child-1')).toBeInTheDocument();
      expect(screen.getByTestId('fragment-child-2')).toBeInTheDocument();
    });

    it('handles complex nested children', () => {
      render(
        <DeviceFrame>
          <div>
            <div>
              <div data-testid="nested-child">Deeply Nested</div>
            </div>
          </div>
        </DeviceFrame>
      );

      expect(screen.getByTestId('nested-child')).toBeInTheDocument();
    });
  });

  describe('Component Structure', () => {
    it('renders a single root div element', () => {
      const { container } = render(<DeviceFrame />);

      expect(container.firstChild.tagName).toBe('DIV');
      expect(container.children).toHaveLength(1);
    });

    it('maintains consistent class structure', () => {
      const { container: androidContainer } = render(
        <DeviceFrame device={DEVICE_TYPES.ANDROID} className="custom" />
      );
      const androidFrame = androidContainer.firstChild;

      const classes = androidFrame.className.split(' ').filter((c) => c);
      expect(classes).toContain('device-frame');
      expect(classes).toContain('device-frame--android');
      expect(classes).toContain('custom');
    });

    it('applies styles as inline styles object', () => {
      const { container } = render(<DeviceFrame />);
      const frame = container.firstChild;

      // Verify style is an object
      expect(typeof frame.style).toBe('object');
      expect(frame.style).not.toBeNull();
    });
  });

  describe('Accessibility', () => {
    it('can receive accessibility props', () => {
      const { container } = render(
        <DeviceFrame
          role="img"
          aria-label="Mobile Device Preview"
          aria-describedby="device-description"
        />
      );
      const frame = container.firstChild;

      expect(frame).toHaveAttribute('role', 'img');
      expect(frame).toHaveAttribute('aria-label', 'Mobile Device Preview');
      expect(frame).toHaveAttribute('aria-describedby', 'device-description');
    });

    it('allows custom data attributes', () => {
      const { container } = render(
        <DeviceFrame
          data-device="android"
          data-testid="device-frame"
          data-analytics="preview-frame"
        />
      );
      const frame = container.firstChild;

      expect(frame).toHaveAttribute('data-device', 'android');
      expect(frame).toHaveAttribute('data-testid', 'device-frame');
      expect(frame).toHaveAttribute('data-analytics', 'preview-frame');
    });
  });

  describe('Integration Scenarios', () => {
    it('works with ContentOverlay-style content', () => {
      render(
        <DeviceFrame device={DEVICE_TYPES.IOS}>
          <div style={{ width: '100%', height: '100%' }}>
            <iframe
              title="preview"
              srcDoc="<p>Preview Content</p>"
              data-testid="preview-iframe"
            />
          </div>
        </DeviceFrame>
      );

      expect(screen.getByTestId('preview-iframe')).toBeInTheDocument();
    });

    it('maintains structure when device changes', () => {
      const { container, rerender } = render(
        <DeviceFrame device={DEVICE_TYPES.ANDROID}>
          <div data-testid="content">Content</div>
        </DeviceFrame>
      );

      expect(container.firstChild).toHaveClass('device-frame--android');
      expect(screen.getByTestId('content')).toBeInTheDocument();

      rerender(
        <DeviceFrame device={DEVICE_TYPES.IOS}>
          <div data-testid="content">Content</div>
        </DeviceFrame>
      );

      expect(container.firstChild).toHaveClass('device-frame--ios');
      expect(screen.getByTestId('content')).toBeInTheDocument();
    });

    it('handles dynamic children updates', () => {
      const { rerender } = render(
        <DeviceFrame>
          <div data-testid="dynamic-content">Initial</div>
        </DeviceFrame>
      );

      expect(screen.getByTestId('dynamic-content')).toHaveTextContent('Initial');

      rerender(
        <DeviceFrame>
          <div data-testid="dynamic-content">Updated</div>
        </DeviceFrame>
      );

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