import { render, screen, fireEvent } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';

import { BillingLink } from './BillingLink';

// usePage is globally mocked in test/setup.ts; override props per-test.
const { usePage } = await import('@inertiajs/react');

function mockBillingEnabled(enabled: boolean) {
  vi.mocked(usePage).mockReturnValue({
    props: {
      auth: { user: null },
      errors: {},
      flash: {},
      polling_interval_ms: 5000,
      features: {
        billing: enabled,
        socialAuth: false,
        emailVerification: false,
        apiTokens: false,
        userSettings: false,
        notifications: false,
        onboarding: false,
        apiDocs: false,
        twoFactor: false,
        webhooks: false,
        admin: false,
        dataExport: false,
        referrals: false,
      },
    },
  } as unknown as ReturnType<typeof usePage>);
}

describe('BillingLink', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('renders a billing.plans link when features.billing === true', () => {
    mockBillingEnabled(true);
    render(<BillingLink>Upgrade</BillingLink>);
    const link = screen.getByRole('link', { name: 'Upgrade' });
    expect(link).toBeInTheDocument();
    expect(link).toHaveAttribute('href', '/billing/plans');
  });

  it('renders null (no link) when features.billing === false', () => {
    mockBillingEnabled(false);
    render(<BillingLink>Upgrade</BillingLink>);
    expect(screen.queryByRole('link')).toBeNull();
    expect(screen.queryByText('Upgrade')).toBeNull();
  });

  it('renders fallback when features.billing === false and fallback is provided', () => {
    mockBillingEnabled(false);
    render(
      <BillingLink fallback={<span data-testid="fallback">Upgrades unavailable</span>}>
        Upgrade
      </BillingLink>,
    );
    expect(screen.queryByRole('link')).toBeNull();
    expect(screen.getByTestId('fallback')).toBeInTheDocument();
    expect(screen.getByText('Upgrades unavailable')).toBeInTheDocument();
  });

  it('forwards query params to route when billing is enabled', () => {
    mockBillingEnabled(true);
    render(
      <BillingLink params={{ plan: 'pro', utm_source: 'test', source: 'dashboard' }}>
        Upgrade
      </BillingLink>,
    );
    const link = screen.getByRole('link', { name: 'Upgrade' });
    // The route mock in setup.ts appends params as query string
    expect(link).toHaveAttribute('href', expect.stringContaining('/billing/plans'));
  });

  it('fires the onClick analytics handler when clicked and billing is enabled', () => {
    mockBillingEnabled(true);
    const onClick = vi.fn();
    render(<BillingLink onClick={onClick}>Upgrade</BillingLink>);
    fireEvent.click(screen.getByRole('link', { name: 'Upgrade' }));
    expect(onClick).toHaveBeenCalledTimes(1);
  });

  it('does not fire onClick when billing is disabled (renders null)', () => {
    mockBillingEnabled(false);
    const onClick = vi.fn();
    render(<BillingLink onClick={onClick}>Upgrade</BillingLink>);
    expect(screen.queryByRole('link')).toBeNull();
    expect(onClick).not.toHaveBeenCalled();
  });

  it('passes data-testid to the link element when billing is enabled', () => {
    mockBillingEnabled(true);
    render(
      <BillingLink data-testid="upgrade-cta">Upgrade</BillingLink>,
    );
    expect(screen.getByTestId('upgrade-cta')).toBeInTheDocument();
  });

  it('passes className to the link element when billing is enabled', () => {
    mockBillingEnabled(true);
    render(<BillingLink className="text-primary underline">Upgrade</BillingLink>);
    expect(screen.getByRole('link')).toHaveClass('text-primary', 'underline');
  });
});
