import { render, screen, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { vi, describe, it, expect, beforeEach } from 'vitest';
import { SellerReviewsWidget } from '../seller-reviews-widget';

const summaryMock = vi.fn();
vi.mock('@/lib/api', () => ({
  api: {
    reviews: {
      sellerRatingSummary: (...a: unknown[]) => summaryMock(...a),
    },
  },
}));

function wrap(node: React.ReactNode) {
  const qc = new QueryClient({
    defaultOptions: { queries: { retry: false }, mutations: { retry: false } },
  });
  return <QueryClientProvider client={qc}>{node}</QueryClientProvider>;
}

describe('SellerReviewsWidget', () => {
  beforeEach(() => {
    summaryMock.mockReset();
  });

  it('renders loading skeleton', () => {
    summaryMock.mockReturnValue(new Promise(() => {}));
    render(wrap(<SellerReviewsWidget storeId="store-1" />));
    expect(screen.getByTestId('seller-reviews-widget-loading')).toBeInTheDocument();
  });

  it('renders empty state when zero reviews', async () => {
    summaryMock.mockResolvedValue({
      data: {
        average_rating: null,
        review_count: 0,
        distribution: { '1': 0, '2': 0, '3': 0, '4': 0, '5': 0 },
        dimensions: {
          item_as_described: null,
          shipping_speed: null,
          communication: null,
          packaging: null,
        },
      },
    });
    render(wrap(<SellerReviewsWidget storeId="store-1" />));
    await waitFor(() =>
      expect(screen.getByText(/No reviews yet/i)).toBeInTheDocument(),
    );
  });

  it('renders rating + count + dimension breakdown when reviews exist', async () => {
    summaryMock.mockResolvedValue({
      data: {
        average_rating: 4.7,
        review_count: 24,
        distribution: { '1': 0, '2': 0, '3': 0, '4': 6, '5': 18 },
        dimensions: {
          item_as_described: 4.8,
          shipping_speed: 4.6,
          communication: 4.5,
          packaging: 4.7,
        },
      },
    });
    render(wrap(<SellerReviewsWidget storeId="store-1" />));
    await waitFor(() =>
      expect(screen.getByText(/24 reviews/i)).toBeInTheDocument(),
    );
    // Overall avg renders as a large heading.
    expect(screen.getAllByText('4.7').length).toBeGreaterThan(0);
    expect(screen.getByText(/Item as described/i)).toBeInTheDocument();
    expect(screen.getByText('4.8')).toBeInTheDocument();
  });

  it('passes storeId through to endpoint', async () => {
    summaryMock.mockResolvedValue({
      data: {
        average_rating: 4.0,
        review_count: 5,
        distribution: { '1': 0, '2': 0, '3': 1, '4': 2, '5': 2 },
        dimensions: {
          item_as_described: 4,
          shipping_speed: 4,
          communication: 4,
          packaging: 4,
        },
      },
    });
    render(wrap(<SellerReviewsWidget storeId="store-abc" />));
    await waitFor(() => expect(summaryMock).toHaveBeenCalledWith('store-abc'));
  });

  it('renders all four dimension labels matching the buyer-facing breakdown', async () => {
    summaryMock.mockResolvedValue({
      data: {
        average_rating: 4.3,
        review_count: 12,
        distribution: { '1': 0, '2': 0, '3': 2, '4': 4, '5': 6 },
        dimensions: {
          item_as_described: 4.3,
          shipping_speed: 4.1,
          communication: 4.5,
          packaging: 4.2,
        },
      },
    });
    render(wrap(<SellerReviewsWidget storeId="store-1" />));
    await waitFor(() =>
      expect(screen.getByTestId('dimension-breakdown')).toBeInTheDocument(),
    );
    // Labels must match the labels used by <DimensionBreakdownCard> on the
    // buyer-facing store-detail page (Item as described / Shipping speed /
    // Communication / Packaging).
    expect(screen.getByText(/Item as described/i)).toBeInTheDocument();
    expect(screen.getByText(/Shipping speed/i)).toBeInTheDocument();
    expect(screen.getByText(/Communication/i)).toBeInTheDocument();
    expect(screen.getByText(/Packaging/i)).toBeInTheDocument();
  });

  it('renders the dimension breakdown in compact mode (smaller spacing)', async () => {
    summaryMock.mockResolvedValue({
      data: {
        average_rating: 4.7,
        review_count: 24,
        distribution: { '1': 0, '2': 0, '3': 0, '4': 6, '5': 18 },
        dimensions: {
          item_as_described: 4.8,
          shipping_speed: 4.6,
          communication: 4.5,
          packaging: 4.7,
        },
      },
    });
    render(wrap(<SellerReviewsWidget storeId="store-1" />));
    await waitFor(() =>
      expect(screen.getByTestId('dimension-breakdown')).toBeInTheDocument(),
    );
    // The dashboard widget mounts the card in compact mode so it fits
    // alongside the balance widget in the dashboard grid.
    expect(screen.getByTestId('dimension-breakdown')).toHaveAttribute(
      'data-compact',
      'true',
    );
  });
});
