import { render, screen, fireEvent } from '@testing-library/react';
import { ThemeProvider } from '../../theme';
import type { EarningsState, NurseEarningsItem } from '@/services/payouts/types';

jest.mock('next-intl', () => ({
  useTranslations: () => (key: string) => key,
  useLocale: () => 'en',
}));

import EarningsRow from './EarningsRow';

function makeItem(state: EarningsState, overrides: Partial<NurseEarningsItem> = {}): NurseEarningsItem {
  return {
    bookingId: 5001,
    patientName: 'Test Patient',
    scheduledDate: '2026-06-01',
    grossPriceIrr: '5000000',
    balinyaarCommissionIrr: '750000',
    nursePayoutAmount: '4250000',
    state,
    disputeWindowEndsAt: null,
    payoutEligibleAt: null,
    paidAt: null,
    transferReference: null,
    nursePayoutId: null,
    batchId: null,
    clawbackAppliedIrr: null,
    netAmountIrr: null,
    ...overrides,
  };
}

function renderRow(item: NurseEarningsItem, handlers?: { onViewBooking?: jest.Mock; onViewPayout?: jest.Mock }) {
  const onViewBooking = handlers?.onViewBooking ?? jest.fn();
  const onViewPayout = handlers?.onViewPayout ?? jest.fn();
  const utils = render(
    <ThemeProvider>
      <EarningsRow item={item} onViewBooking={onViewBooking} onViewPayout={onViewPayout} />
    </ThemeProvider>,
  );
  return { ...utils, onViewBooking, onViewPayout };
}

const STATE_KIND: Array<{ state: EarningsState; kind: string }> = [
  { state: 'pending', kind: 'pending' },
  { state: 'eligible', kind: 'info' },
  { state: 'paid', kind: 'verified' },
  { state: 'clawback_applied', kind: 'rejected' },
];

describe('<EarningsRow/> component', () => {
  it.each(STATE_KIND)('maps the $state state to the $kind chip kind', ({ state, kind }) => {
    const { container } = renderRow(makeItem(state));
    expect(container.querySelector(`[data-earnings-state="${state}"]`)).toBeInTheDocument();
    expect(container.querySelector(`[data-status="${kind}"]`)).toBeInTheDocument();
  });

  it('renders the reconciled payout as the breakdown total (gross − commission = payout)', () => {
    const { container } = renderRow(makeItem('eligible'));
    const total = container.querySelector('[data-row="total"]');
    // 4,250,000 IRR ÷ 10 = 425,000 Toman
    expect(total?.textContent).toContain('425,000');
  });

  it('shows the pending dispute-window affordance', () => {
    renderRow(makeItem('pending', { disputeWindowEndsAt: '2999-01-01T00:00:00Z' }));
    expect(screen.getByText('pending_affordance')).toBeInTheDocument();
  });

  it('shows the clawback net-explanation block for a clawed-back earning', () => {
    // Reconciling fixture: original payout 1,700,000 − clawback 1,700,000 = net 0 (PriceBreakdown guard stays silent).
    renderRow(
      makeItem('clawback_applied', {
        grossPriceIrr: '2000000',
        balinyaarCommissionIrr: '300000',
        nursePayoutAmount: '1700000',
        clawbackAppliedIrr: '1700000',
        netAmountIrr: '0',
      }),
    );
    expect(screen.getByText('clawback_explainer')).toBeInTheDocument();
    expect(screen.getByText('clawback_net')).toBeInTheDocument();
  });

  it('links a paid earning to its payout detail', () => {
    const onViewPayout = jest.fn();
    renderRow(
      makeItem('paid', { paidAt: '2026-06-10T00:00:00Z', transferReference: 'PAYA-1', nursePayoutId: 9001 }),
      { onViewPayout },
    );
    fireEvent.click(screen.getByText('view_payout'));
    expect(onViewPayout).toHaveBeenCalledWith(9001);
  });

  it('deep-links every row to its booking detail', () => {
    const onViewBooking = jest.fn();
    renderRow(makeItem('eligible', { bookingId: 5002 }), { onViewBooking });
    fireEvent.click(screen.getByText('view_booking'));
    expect(onViewBooking).toHaveBeenCalledWith(5002);
  });
});
