import { render, screen, fireEvent } from '@testing-library/react';
import { PhotoCarousel } from '@/components/PhotoCarousel';
import type { ListingDetailPhoto } from '@/types';

function photo(url: string, caption: string | null = null): ListingDetailPhoto {
  return { url, caption, type: null };
}

describe('PhotoCarousel', () => {
  describe('B23 — single-photo and broken-image handling', () => {
    it('suppresses the N/M counter when there is exactly one photo', () => {
      render(<PhotoCarousel photos={[photo('https://example.com/a.jpg')]} />);
      expect(screen.queryByText('1 / 1')).not.toBeInTheDocument();
    });

    it('renders the N/M counter when there are multiple photos', () => {
      render(
        <PhotoCarousel
          photos={[
            photo('https://example.com/a.jpg'),
            photo('https://example.com/b.jpg'),
            photo('https://example.com/c.jpg'),
          ]}
        />,
      );
      expect(screen.getByText('1 / 3')).toBeInTheDocument();
    });

    it('replaces a broken image with a placeholder tile when onError fires', () => {
      render(
        <PhotoCarousel
          photos={[
            photo('https://example.com/good.jpg'),
            photo('https://example.com/bad.jpg'),
          ]}
        />,
      );
      const imgs = screen.getAllByRole('img');
      expect(imgs).toHaveLength(2);
      // Simulate the second image failing to load
      fireEvent.error(imgs[1]);
      // After error, the placeholder appears and the broken img is gone
      expect(screen.getByText(/Photo unavailable/i)).toBeInTheDocument();
      // The good image is still rendered
      expect(screen.getAllByRole('img')).toHaveLength(1);
    });

    it('still renders "No photos available" when photos is empty', () => {
      render(<PhotoCarousel photos={[]} />);
      expect(screen.getByText(/No photos available/i)).toBeInTheDocument();
    });
  });

  describe('B26 — single-photo carousel should not loop', () => {
    it('does not render prev/next buttons for a single-photo carousel', () => {
      render(<PhotoCarousel photos={[photo('https://example.com/a.jpg')]} />);
      expect(screen.queryByLabelText(/Previous photo/i)).not.toBeInTheDocument();
      expect(screen.queryByLabelText(/Next photo/i)).not.toBeInTheDocument();
    });

    it('does not render dots for a single-photo carousel', () => {
      const { container } = render(
        <PhotoCarousel photos={[photo('https://example.com/a.jpg')]} />,
      );
      // No "Go to photo X" buttons (dots) should be rendered when single
      expect(container.querySelectorAll('button[aria-label^="Go to photo"]'))
        .toHaveLength(0);
    });

    it('renders prev/next + dots for a multi-photo carousel', () => {
      render(
        <PhotoCarousel
          photos={[
            photo('https://example.com/a.jpg'),
            photo('https://example.com/b.jpg'),
          ]}
        />,
      );
      expect(screen.getByLabelText(/Previous photo/i)).toBeInTheDocument();
      expect(screen.getByLabelText(/Next photo/i)).toBeInTheDocument();
    });
  });

  describe('B16 — keyboard navigation', () => {
    it('makes the multi-photo carousel root keyboard-focusable', () => {
      const { container } = render(
        <PhotoCarousel
          photos={[
            photo('https://example.com/a.jpg'),
            photo('https://example.com/b.jpg'),
          ]}
        />,
      );
      // The Embla overflow container is the focusable root
      const region = container.querySelector('[role="region"][aria-label="Property photos"]');
      expect(region).not.toBeNull();
      // tabIndex should be set to 0 so the carousel can receive keydown
      expect((region as HTMLElement).tabIndex).toBe(0);
    });

    it('does not make a single-photo carousel keyboard-focusable', () => {
      const { container } = render(
        <PhotoCarousel photos={[photo('https://example.com/a.jpg')]} />,
      );
      const region = container.querySelector('[role="region"][aria-label="Property photos"]');
      // Region still exists (Embla wrapping) but should not be focusable, since
      // there's nothing to navigate to.
      expect(region).not.toBeNull();
      const tabIndex = (region as HTMLElement).tabIndex;
      // Default tabIndex on non-interactive elements is -1; we only flip to 0
      // for multi-photo carousels.
      expect(tabIndex).toBeLessThan(0);
    });
  });
});
