import React from 'react';
import { describe, it, expect, vi, beforeAll, afterEach } from 'vitest';
import { cleanup, render, screen, fireEvent } from '@testing-library/react';
import { CheckoutWizard } from '../CheckoutWizard';
import { useCheckoutWizard } from '../WizardContext';

vi.mock('@/hooks/useAnalytics', () => ({
  useAnalytics: () => ({ trackEvent: vi.fn() }),
}));

vi.mock('../steps/PackageStep', () => ({
  PackageStep: () => <div data-testid="package-step" />,
}));

vi.mock('../steps/AuthStep', () => ({
  AuthStep: () => <div data-testid="auth-step" />,
}));

vi.mock('../steps/PaymentStep', () => ({
  PaymentStep: () => {
    const { setPaymentCompleted } = useCheckoutWizard();

    return (
      <div data-testid="payment-step">
        <button type="button" onClick={() => setPaymentCompleted(true)}>
          mark-complete
        </button>
      </div>
    );
  },
}));

vi.mock('../steps/ConfirmationStep', () => ({
  ConfirmationStep: () => <div data-testid="confirmation-step" />,
}));

const basePackage = {
  id: 1,
  name: 'Starter',
  description: 'Test package',
  price: 0,
  type: 'endcustomer' as const,
  features: [],
};

describe('CheckoutWizard auth step navigation guard', () => {
  beforeAll(() => {
    // jsdom does not implement scrollTo, but the wizard calls it on step changes.
    Object.defineProperty(window, 'scrollTo', { value: vi.fn(), writable: true });
  });

  afterEach(() => {
    cleanup();
  });

  it('disables the next button when the user is not authenticated on the auth step', () => {
    render(
      <CheckoutWizard
        initialPackage={basePackage}
        packageOptions={[basePackage]}
        privacyHtml="<p>privacy</p>"
        initialAuthUser={null}
        initialStep="auth"
      />,
    );

    const nextButtons = screen.getAllByRole('button', { name: 'checkout.next' });
    nextButtons.forEach((button) => expect(button).toBeDisabled());
  });

  it('enables the next button once the user is authenticated on the auth step', () => {
    render(
      <CheckoutWizard
        initialPackage={basePackage}
        packageOptions={[basePackage]}
        privacyHtml="<p>privacy</p>"
        initialAuthUser={{ id: 42, email: 'user@example.com' }}
        initialStep="auth"
      />,
    );

    const nextButtons = screen.getAllByRole('button', { name: 'checkout.next' });
    nextButtons.forEach((button) => expect(button).not.toBeDisabled());
  });

  it('redirects to the auth step when the user is not authenticated on the payment step', async () => {
    render(
      <CheckoutWizard
        initialPackage={basePackage}
        packageOptions={[basePackage]}
        privacyHtml="<p>privacy</p>"
        initialAuthUser={null}
        initialStep="payment"
      />,
    );

    await screen.findByTestId('auth-step');
    expect(screen.queryByTestId('payment-step')).not.toBeInTheDocument();
  });

  it('only renders the next button on the payment step after the payment is completed', async () => {
    const paidPackage = { ...basePackage, id: 2, price: 99 };

    render(
      <CheckoutWizard
        initialPackage={paidPackage}
        packageOptions={[paidPackage]}
        privacyHtml="<p>privacy</p>"
        initialAuthUser={{ id: 42, email: 'user@example.com' }}
        initialStep="payment"
      />,
    );

    await screen.findByTestId('payment-step');

    const nextButtons = screen.getAllByRole('button', { name: 'checkout.next' });
    nextButtons.forEach((button) => expect(button).toBeDisabled());

    fireEvent.click(screen.getByRole('button', { name: 'mark-complete' }));

    const activatedButtons = await screen.findAllByRole('button', { name: 'checkout.next' });
    activatedButtons.forEach((button) => expect(button).toBeEnabled());
  });
});
