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

const getForStoreMock = vi.fn();
vi.mock('@/lib/api', () => ({
  api: {
    balance: {
      getForStore: (...a: unknown[]) => getForStoreMock(...a),
    },
  },
}));

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

describe('SellerBalanceWidget', () => {
  beforeEach(() => {
    getForStoreMock.mockReset();
  });

  it('renders loading skeleton when the query is pending', () => {
    // Never-resolving promise keeps the query in loading state
    getForStoreMock.mockReturnValue(new Promise(() => {}));
    render(wrap(<SellerBalanceWidget storeId="store-1" />));

    expect(screen.getByTestId('seller-balance-widget-loading')).toBeInTheDocument();
  });

  it('renders error state when the query errors', async () => {
    getForStoreMock.mockRejectedValue(new Error('boom'));
    render(wrap(<SellerBalanceWidget storeId="store-1" />));

    await waitFor(() =>
      expect(screen.getByText(/couldn't load balance/i)).toBeInTheDocument(),
    );
  });

  it('renders available balance with payout date', async () => {
    getForStoreMock.mockResolvedValue({
      data: {
        available_cents: 12345,
        pending_cents: 6789,
        next_payout_date: '2026-05-17T00:00:00Z',
      },
    });
    render(wrap(<SellerBalanceWidget storeId="store-1" />));

    await waitFor(() =>
      expect(screen.getByText(/\$123\.45/)).toBeInTheDocument(),
    );
    expect(screen.getByText(/paying out May 17/i)).toBeInTheDocument();
  });

  it('renders pending balance with the release copy', async () => {
    getForStoreMock.mockResolvedValue({
      data: {
        available_cents: 0,
        pending_cents: 6789,
        next_payout_date: '2026-05-17T00:00:00Z',
      },
    });
    render(wrap(<SellerBalanceWidget storeId="store-1" />));

    await waitFor(() =>
      expect(screen.getByText(/\$67\.89/)).toBeInTheDocument(),
    );
    expect(screen.getByText(/releasing as orders deliver/i)).toBeInTheDocument();
  });

  it('formats cents to dollars correctly', async () => {
    getForStoreMock.mockResolvedValue({
      data: {
        available_cents: 100000,
        pending_cents: 50,
        next_payout_date: '2026-05-17T00:00:00Z',
      },
    });
    render(wrap(<SellerBalanceWidget storeId="store-1" />));

    await waitFor(() =>
      expect(screen.getByText(/\$1000\.00/)).toBeInTheDocument(),
    );
    expect(screen.getByText(/\$0\.50/)).toBeInTheDocument();
  });

  it('formats next_payout_date as month + day (e.g., May 17)', async () => {
    getForStoreMock.mockResolvedValue({
      data: {
        available_cents: 100,
        pending_cents: 100,
        next_payout_date: '2026-05-17T00:00:00Z',
      },
    });
    render(wrap(<SellerBalanceWidget storeId="store-1" />));

    await waitFor(() =>
      expect(screen.getByText(/paying out May 17/i)).toBeInTheDocument(),
    );
  });

  it('does not crash with zero balances', async () => {
    getForStoreMock.mockResolvedValue({
      data: {
        available_cents: 0,
        pending_cents: 0,
        next_payout_date: '2026-05-17T00:00:00Z',
      },
    });
    render(wrap(<SellerBalanceWidget storeId="store-1" />));

    await waitFor(() => {
      const zeros = screen.getAllByText(/\$0\.00/);
      expect(zeros.length).toBeGreaterThanOrEqual(2);
    });
  });

  it('passes the storeId through to the endpoint', async () => {
    getForStoreMock.mockResolvedValue({
      data: {
        available_cents: 100,
        pending_cents: 100,
        next_payout_date: '2026-05-17T00:00:00Z',
      },
    });
    render(wrap(<SellerBalanceWidget storeId="store-abc" />));

    await waitFor(() => expect(getForStoreMock).toHaveBeenCalledWith('store-abc'));
  });
});
