import { render, screen, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { vi, describe, it, expect, beforeEach } from 'vitest';
import { ConnectHealthBanner } from '../connect-health-banner';

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>;
}

const HEALTHY = {
  data: {
    available_cents: 1000,
    pending_cents: 0,
    next_payout_date: '2026-05-17T00:00:00Z',
    payouts_enabled: true,
    disabled_reason: null,
  },
};

const PAUSED = {
  data: {
    available_cents: 1000,
    pending_cents: 0,
    next_payout_date: '2026-05-17T00:00:00Z',
    payouts_enabled: false,
    disabled_reason: 'Stripe needs more docs.',
  },
};

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

  it('renders nothing when payouts_enabled is true', async () => {
    getForStoreMock.mockResolvedValue(HEALTHY);
    const { container } = render(
      wrap(<ConnectHealthBanner storeId="s1" />),
    );
    await waitFor(() => expect(getForStoreMock).toHaveBeenCalled());
    expect(
      screen.queryByTestId('connect-health-banner'),
    ).not.toBeInTheDocument();
    expect(container.firstChild).toBeNull();
  });

  it('renders the banner with disabled_reason when payouts are paused', async () => {
    getForStoreMock.mockResolvedValue(PAUSED);
    render(wrap(<ConnectHealthBanner storeId="s1" />));
    const banner = await screen.findByTestId('connect-health-banner');
    expect(banner).toBeInTheDocument();
    expect(banner.textContent).toMatch(/Stripe needs more docs/);
    expect(banner.textContent).toMatch(/Your payouts are paused/);
  });

  it('renders a fallback reason when disabled_reason is null', async () => {
    getForStoreMock.mockResolvedValue({
      data: { ...PAUSED.data, disabled_reason: null },
    });
    render(wrap(<ConnectHealthBanner storeId="s1" />));
    const banner = await screen.findByTestId('connect-health-banner');
    expect(banner.textContent).toMatch(/Stripe needs more information/i);
  });

  it('links the CTA to the test-mode Stripe onboarding url', async () => {
    getForStoreMock.mockResolvedValue(PAUSED);
    render(wrap(<ConnectHealthBanner storeId="s1" />));
    const cta = await screen.findByTestId('connect-health-cta');
    expect(cta).toHaveAttribute(
      'href',
      'https://dashboard.stripe.com/test/account/onboarding',
    );
    expect(cta).toHaveAttribute('target', '_blank');
  });

  it('renders nothing while the balance query is loading', () => {
    getForStoreMock.mockReturnValue(new Promise(() => {}));
    render(wrap(<ConnectHealthBanner storeId="s1" />));
    expect(
      screen.queryByTestId('connect-health-banner'),
    ).not.toBeInTheDocument();
  });
});
