/**
 * AtRiskPanel Component Tests
 *
 * Covers: loading, populated counts + rows, issue chips, positive empty state,
 * error state, and the Inspect callback wiring.
 */

import { render, screen, fireEvent } from '@testing-library/react';
import { AtRiskPanel } from '../admin/AtRiskPanel';

global.fetch = jest.fn();
const mockFetch = global.fetch as jest.Mock;

function resolveWith(body: unknown, ok = true) {
  mockFetch.mockResolvedValue({ ok, json: () => Promise.resolve(body) });
}

const populated = {
  success: true,
  counts: { missingZo: 5, missingSubdomain: 2, total: 6 },
  dealers: [
    {
      id: 'd1',
      businessName: 'Acme Oil',
      contactName: 'Jane',
      subdomain: 'acme',
      dealerNumber: null,
      status: 'active',
      createdAt: '2026-01-01T00:00:00.000Z',
      email: 'jane@acme.com',
      name: 'Jane',
      issues: ['missing_zo'],
    },
    {
      id: 'd2',
      businessName: 'Bob Co',
      contactName: 'Bob',
      subdomain: null,
      dealerNumber: '',
      status: 'active',
      createdAt: '2026-02-01T00:00:00.000Z',
      email: 'bob@bob.co',
      name: 'Bob',
      issues: ['missing_zo', 'missing_subdomain'],
    },
  ],
};

describe('AtRiskPanel', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  it('shows a loading state initially', () => {
    mockFetch.mockImplementation(() => new Promise(() => {}));
    render(<AtRiskPanel onInspect={jest.fn()} onViewDetails={jest.fn()} />);
    expect(screen.getByText(/at-risk dealers/i)).toBeInTheDocument();
    expect(screen.getByTestId('at-risk-loading')).toBeInTheDocument();
  });

  it('renders the failure-mode counts after fetch', async () => {
    resolveWith(populated);
    render(<AtRiskPanel onInspect={jest.fn()} onViewDetails={jest.fn()} />);

    expect(await screen.findByText('Missing ZO')).toBeInTheDocument();
    expect(screen.getByTestId('count-missing-zo')).toHaveTextContent('5');
    expect(screen.getByTestId('count-missing-subdomain')).toHaveTextContent('2');
  });

  it('renders a row per at-risk dealer with issue chips', async () => {
    resolveWith(populated);
    render(<AtRiskPanel onInspect={jest.fn()} onViewDetails={jest.fn()} />);

    expect(await screen.findByText('Acme Oil')).toBeInTheDocument();
    expect(screen.getByText('Bob Co')).toBeInTheDocument();
    const bobRow = screen.getByText('Bob Co').closest('tr')!;
    expect(bobRow).toHaveTextContent(/ZO/);
    expect(bobRow).toHaveTextContent(/subdomain/i);
  });

  it('shows a positive empty state when no dealers are at risk', async () => {
    resolveWith({
      success: true,
      counts: { missingZo: 0, missingSubdomain: 0, total: 0 },
      dealers: [],
    });
    render(<AtRiskPanel onInspect={jest.fn()} onViewDetails={jest.fn()} />);

    expect(
      await screen.findByText(/all dealers have a zo number and subdomain/i)
    ).toBeInTheDocument();
  });

  it('shows an error state when the request fails', async () => {
    resolveWith({ success: false, error: 'Failed to build at-risk report' }, false);
    render(<AtRiskPanel onInspect={jest.fn()} onViewDetails={jest.fn()} />);

    expect(await screen.findByText(/failed to build at-risk report/i)).toBeInTheDocument();
  });

  it('calls onInspect with the dealer email when "Show in table" is clicked', async () => {
    const onInspect = jest.fn();
    resolveWith(populated);
    render(<AtRiskPanel onInspect={onInspect} onViewDetails={jest.fn()} />);

    const buttons = await screen.findAllByRole('button', { name: /show in table/i });
    fireEvent.click(buttons[0]);
    expect(onInspect).toHaveBeenCalledWith('jane@acme.com');
  });

  it('calls onViewDetails with the dealer id when "View details" is clicked', async () => {
    const onViewDetails = jest.fn();
    resolveWith(populated);
    render(<AtRiskPanel onInspect={jest.fn()} onViewDetails={onViewDetails} />);

    const buttons = await screen.findAllByRole('button', { name: /view details/i });
    fireEvent.click(buttons[0]);
    expect(onViewDetails).toHaveBeenCalledWith('d1');
  });

  it('clicking a count chip filters the table to only dealers with that issue', async () => {
    resolveWith(populated);
    render(<AtRiskPanel onInspect={jest.fn()} onViewDetails={jest.fn()} />);

    // Both dealers visible initially
    await screen.findByText('Acme Oil');
    expect(screen.getByText('Bob Co')).toBeInTheDocument();

    // Click "Missing ZO" chip — Acme has missing_zo, Bob has both
    fireEvent.click(screen.getByRole('button', { name: /filter by missing zo/i }));
    expect(screen.getByText('Acme Oil')).toBeInTheDocument();
    expect(screen.getByText('Bob Co')).toBeInTheDocument();

    // Click "Missing Subdomain" chip — only Bob has missing_subdomain
    fireEvent.click(screen.getByRole('button', { name: /filter by missing subdomain/i }));
    expect(screen.queryByText('Acme Oil')).not.toBeInTheDocument();
    expect(screen.getByText('Bob Co')).toBeInTheDocument();
  });

  it('clicking an active chip a second time clears the filter', async () => {
    resolveWith(populated);
    render(<AtRiskPanel onInspect={jest.fn()} onViewDetails={jest.fn()} />);

    await screen.findByText('Acme Oil');

    const subdomainChip = screen.getByRole('button', { name: /filter by missing subdomain/i });

    // Activate filter — only Bob shown
    fireEvent.click(subdomainChip);
    expect(screen.queryByText('Acme Oil')).not.toBeInTheDocument();

    // Click again to toggle off — both dealers shown again
    fireEvent.click(subdomainChip);
    expect(screen.getByText('Acme Oil')).toBeInTheDocument();
    expect(screen.getByText('Bob Co')).toBeInTheDocument();
  });

  it('"Show all" button appears when a filter is active and clears it when clicked', async () => {
    resolveWith(populated);
    render(<AtRiskPanel onInspect={jest.fn()} onViewDetails={jest.fn()} />);

    await screen.findByText('Acme Oil');

    // No "Show all" button before any filter
    expect(screen.queryByRole('button', { name: /show all/i })).not.toBeInTheDocument();

    fireEvent.click(screen.getByRole('button', { name: /filter by missing zo/i }));
    const showAll = screen.getByRole('button', { name: /show all/i });
    expect(showAll).toBeInTheDocument();

    fireEvent.click(showAll);
    expect(screen.queryByRole('button', { name: /show all/i })).not.toBeInTheDocument();
    expect(screen.getByText('Acme Oil')).toBeInTheDocument();
    expect(screen.getByText('Bob Co')).toBeInTheDocument();
  });

  it('count chip has aria-pressed reflecting active filter state', async () => {
    resolveWith(populated);
    render(<AtRiskPanel onInspect={jest.fn()} onViewDetails={jest.fn()} />);

    const zoChip = await screen.findByRole('button', { name: /filter by missing zo/i });
    expect(zoChip).toHaveAttribute('aria-pressed', 'false');

    fireEvent.click(zoChip);
    expect(zoChip).toHaveAttribute('aria-pressed', 'true');
  });
});
