/**
 * HeroSlider Component Tests
 *
 * Tests BEHAVIOR of the hero image slider:
 * - Renders slides with correct content
 * - Handles empty/null slider content gracefully
 * - Renders headlines, subheadings, and CTA buttons
 * - Applies text formatting (bold, italic, color)
 * - Handles alignment (left, right, center)
 *
 * Philosophy: Test what the user sees, not Swiper internals.
 */

import { render, screen } from '@testing-library/react';
import { SliderContent, Slide } from '@/types/slider';

// Mock Swiper to avoid ESM issues — capture props to verify config
let capturedSwiperProps: Record<string, unknown> = {};

jest.mock('swiper/react', () => ({
  Swiper: ({
    children,
    className,
    ...props
  }: {
    children: React.ReactNode;
    className: string;
    [key: string]: unknown;
  }) => {
    capturedSwiperProps = props;
    return (
      <div data-testid="swiper" className={className}>
        {children}
      </div>
    );
  },
  SwiperSlide: ({ children }: { children: React.ReactNode }) => (
    <div data-testid="swiper-slide">{children}</div>
  ),
}));

jest.mock('swiper/modules', () => ({
  Autoplay: {},
  Navigation: {},
  Pagination: {},
  Keyboard: {},
  A11y: {},
}));

jest.mock('swiper/css', () => ({}));
jest.mock('swiper/css/navigation', () => ({}));
jest.mock('swiper/css/pagination', () => ({}));

// Import after mocks
import { HeroSlider } from '../HeroSlider';

describe('HeroSlider', () => {
  beforeEach(() => {
    capturedSwiperProps = {};
  });

  const createSlide = (overrides: Partial<Slide> = {}): Slide => ({
    id: 'slide-1',
    image: { url: '/images/hero.jpg' },
    headline: 'Test Headline',
    subheading: 'Test Subheading',
    alignment: 'left',
    button: { text: 'Shop Now', url: 'https://www.amsoil.com' },
    headlineFormatting: { color: '#ffffff', bold: true, italic: false },
    subheadingFormatting: { color: '#cccccc', bold: false, italic: true },
    ...overrides,
  });

  const createSliderContent = (slides: Slide[]): SliderContent => ({
    slides,
  });

  describe('Empty States', () => {
    it('returns null when slides array is empty', () => {
      const { container } = render(<HeroSlider sliderContent={{ slides: [] }} />);

      expect(container.firstChild).toBeNull();
    });

    it('returns null when slides is undefined', () => {
      const { container } = render(
        <HeroSlider sliderContent={{ slides: undefined as unknown as Slide[] }} />
      );

      expect(container.firstChild).toBeNull();
    });
  });

  describe('Slide Content Rendering', () => {
    it('renders headline text', () => {
      const slide = createSlide({ headline: 'Premium AMSOIL Products' });
      render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      expect(screen.getByText('Premium AMSOIL Products')).toBeInTheDocument();
    });

    it('renders subheading text', () => {
      const slide = createSlide({ subheading: 'Best synthetic oil on the market' });
      render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      expect(screen.getByText('Best synthetic oil on the market')).toBeInTheDocument();
    });

    it('renders CTA button with correct text and link', () => {
      const slide = createSlide({
        button: { text: 'Shop Now', url: 'https://www.amsoil.com/shop' },
      });
      render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      const button = screen.getByText('Shop Now');
      expect(button).toBeInTheDocument();
      expect(button.closest('a')).toHaveAttribute('href', 'https://www.amsoil.com/shop');
    });

    it('does not render headline when empty', () => {
      const slide = createSlide({ headline: '' });
      render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      // H1 should not be present
      expect(screen.queryByRole('heading', { level: 1 })).not.toBeInTheDocument();
    });

    it('does not render subheading when empty', () => {
      const slide = createSlide({ subheading: '' });
      render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      // Subheading paragraph should not exist (check by non-existence of text)
      expect(screen.queryByText('Test Subheading')).not.toBeInTheDocument();
    });

    it('does not render button when text is empty', () => {
      const slide = createSlide({ button: { text: '', url: 'https://example.com' } });
      render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      expect(screen.queryByRole('link', { name: '' })).not.toBeInTheDocument();
    });
  });

  describe('Text Formatting', () => {
    it('applies headline color from formatting', () => {
      const slide = createSlide({
        headline: 'Colored Headline',
        headlineFormatting: { color: '#ff0000', bold: false, italic: false },
      });
      render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      const headline = screen.getByText('Colored Headline');
      expect(headline).toHaveStyle({ color: '#ff0000' });
    });

    it('applies bold formatting to headline', () => {
      const slide = createSlide({
        headline: 'Bold Headline',
        headlineFormatting: { color: '#000', bold: true, italic: false },
      });
      render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      const headline = screen.getByText('Bold Headline');
      expect(headline).toHaveStyle({ fontWeight: 'bold' });
    });

    it('applies italic formatting to subheading', () => {
      const slide = createSlide({
        subheading: 'Italic Subheading',
        subheadingFormatting: { color: '#000', bold: false, italic: true },
      });
      render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      const subheading = screen.getByText('Italic Subheading');
      expect(subheading).toHaveStyle({ fontStyle: 'italic' });
    });
  });

  describe('Slide Alignment', () => {
    it('applies left alignment margin', () => {
      const slide = createSlide({ alignment: 'left' });
      const { container } = render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      const overlayContent = container.querySelector('.overlay-content');
      expect(overlayContent).toHaveStyle({ marginRight: 'auto' });
    });

    it('applies right alignment margin', () => {
      const slide = createSlide({ alignment: 'right' });
      const { container } = render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      const overlayContent = container.querySelector('.overlay-content');
      expect(overlayContent).toHaveStyle({ marginLeft: 'auto' });
    });
  });

  describe('Multiple Slides', () => {
    it('renders multiple slides', () => {
      const slides = [
        createSlide({ id: 'slide-1', headline: 'First Slide' }),
        createSlide({ id: 'slide-2', headline: 'Second Slide' }),
        createSlide({ id: 'slide-3', headline: 'Third Slide' }),
      ];
      render(<HeroSlider sliderContent={createSliderContent(slides)} />);

      expect(screen.getByText('First Slide')).toBeInTheDocument();
      expect(screen.getByText('Second Slide')).toBeInTheDocument();
      expect(screen.getByText('Third Slide')).toBeInTheDocument();
    });

    it('renders correct number of SwiperSlide components', () => {
      const slides = [createSlide({ id: 'slide-1' }), createSlide({ id: 'slide-2' })];
      render(<HeroSlider sliderContent={createSliderContent(slides)} />);

      const swiperSlides = screen.getAllByTestId('swiper-slide');
      expect(swiperSlides).toHaveLength(2);
    });
  });

  describe('Background Image', () => {
    it('sets background image from slide data', () => {
      const slide = createSlide({
        image: { url: '/images/hero-banner.jpg' },
      });
      const { container } = render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      const slideContent = container.querySelector('.slide-content');
      expect(slideContent).toHaveStyle({
        backgroundImage: 'url(/images/hero-banner.jpg)',
      });
    });
  });

  describe('Button Links', () => {
    it('opens button link in new tab with noopener noreferrer', () => {
      const slide = createSlide({
        button: { text: 'Shop Now', url: 'https://www.amsoil.com' },
      });
      render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      const button = screen.getByText('Shop Now').closest('a');
      expect(button).toHaveAttribute('target', '_blank');
      expect(button).toHaveAttribute('rel', 'noopener noreferrer');
    });

    it('uses # as fallback when button URL is empty', () => {
      const slide = createSlide({
        button: { text: 'Click Me', url: '' },
      });
      render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      const button = screen.getByText('Click Me').closest('a');
      expect(button).toHaveAttribute('href', '#');
    });
  });

  describe('Active/Inactive Slides', () => {
    it('does not render slides with active: false', () => {
      const slides = [
        createSlide({ id: 'slide-1', headline: 'Visible Slide', active: true }),
        createSlide({ id: 'slide-2', headline: 'Hidden Slide', active: false }),
      ];
      render(<HeroSlider sliderContent={createSliderContent(slides)} />);

      expect(screen.getByText('Visible Slide')).toBeInTheDocument();
      expect(screen.queryByText('Hidden Slide')).not.toBeInTheDocument();
    });

    it('treats slides without active field as active (backward compat)', () => {
      const slide = createSlide({ id: 'slide-1', headline: 'Legacy Slide' });
      delete (slide as Record<string, unknown>).active;
      render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      expect(screen.getByText('Legacy Slide')).toBeInTheDocument();
    });

    it('returns null when all slides are inactive', () => {
      const slides = [
        createSlide({ id: 'slide-1', active: false }),
        createSlide({ id: 'slide-2', active: false }),
      ];
      const { container } = render(<HeroSlider sliderContent={createSliderContent(slides)} />);

      expect(container.firstChild).toBeNull();
    });
  });

  describe('Accessibility', () => {
    it('disables PageUp/PageDown from navigating slides', () => {
      const slide = createSlide();
      render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      expect(capturedSwiperProps.keyboard).toEqual(expect.objectContaining({ pageUpDown: false }));
    });

    it('configures A11y module with carousel role description', () => {
      const slide = createSlide();
      render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      expect(capturedSwiperProps.a11y).toEqual(
        expect.objectContaining({
          containerRoleDescriptionMessage: 'carousel',
          itemRoleDescriptionMessage: 'slide',
        })
      );
    });

    it('configures A11y module with navigation labels', () => {
      const slide = createSlide();
      render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      expect(capturedSwiperProps.a11y).toEqual(
        expect.objectContaining({
          prevSlideMessage: 'Previous slide',
          nextSlideMessage: 'Next slide',
        })
      );
    });

    it('wraps carousel in a labeled section', () => {
      const slide = createSlide();
      render(<HeroSlider sliderContent={createSliderContent([slide])} />);

      const section = screen.getByRole('region', { name: /hero slideshow/i });
      expect(section).toBeInTheDocument();
    });

    it('hides inactive slide CTA links from tab order', () => {
      const slides = [
        createSlide({ id: 'slide-1', button: { text: 'First CTA', url: 'https://example.com/1' } }),
        createSlide({
          id: 'slide-2',
          button: { text: 'Second CTA', url: 'https://example.com/2' },
        }),
      ];
      render(<HeroSlider sliderContent={createSliderContent(slides)} />);

      // Use { hidden: true } because inactive slides have aria-hidden
      const links = screen.getAllByRole('link', { hidden: true });
      // First slide (active) should be tabbable
      expect(links[0]).not.toHaveAttribute('tabindex', '-1');
      // Second slide (inactive) should be hidden from tab order
      expect(links[1]).toHaveAttribute('tabindex', '-1');
    });

    it('marks inactive slides as aria-hidden', () => {
      const slides = [
        createSlide({ id: 'slide-1', headline: 'Active Slide' }),
        createSlide({ id: 'slide-2', headline: 'Inactive Slide' }),
      ];
      const { container } = render(<HeroSlider sliderContent={createSliderContent(slides)} />);

      const slideContents = container.querySelectorAll('.slide-content');
      expect(slideContents[0]).toHaveAttribute('aria-hidden', 'false');
      expect(slideContents[1]).toHaveAttribute('aria-hidden', 'true');
    });

    it('applies inert to inactive slides so focusable children cannot receive focus', () => {
      const slides = [
        createSlide({ id: 'slide-1', headline: 'Active Slide' }),
        createSlide({ id: 'slide-2', headline: 'Inactive Slide' }),
      ];
      const { container } = render(<HeroSlider sliderContent={createSliderContent(slides)} />);

      const slideContents = container.querySelectorAll('.slide-content');
      expect(slideContents[0]).not.toHaveAttribute('inert');
      expect(slideContents[1]).toHaveAttribute('inert');
    });
  });
});
