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

// Mock Lucide icons
vi.mock('lucide-react', () => ({
  CreditCard: () => <span data-testid="icon-credit-card" />,
  ShieldCheck: () => <span data-testid="icon-shield-check" />,
  Lock: () => <span data-testid="icon-lock" />,
}));

describe('PaymentSection', () => {
  const mockService = {
    id: 1,
    name: 'Haircut',
    description: 'A professional haircut',
    duration: 30,
    price_cents: 2500,
    photos: [],
    deposit_amount_cents: 0,
  };

  const mockServiceWithDeposit = {
    ...mockService,
    deposit_amount_cents: 1000,
  };

  const defaultProps = {
    service: mockService,
    onPaymentComplete: vi.fn(),
  };

  beforeEach(() => {
    vi.clearAllMocks();
    vi.useFakeTimers();
  });

  afterEach(() => {
    vi.useRealTimers();
  });

  it('renders payment form', () => {
    render(React.createElement(PaymentSection, defaultProps));
    expect(screen.getByText('Card Details')).toBeInTheDocument();
    expect(screen.getByPlaceholderText('0000 0000 0000 0000')).toBeInTheDocument();
    expect(screen.getByPlaceholderText('MM / YY')).toBeInTheDocument();
    expect(screen.getByPlaceholderText('123')).toBeInTheDocument();
  });

  it('displays service total price', () => {
    render(React.createElement(PaymentSection, defaultProps));
    expect(screen.getByText('Service Total')).toBeInTheDocument();
    const prices = screen.getAllByText('$25.00');
    expect(prices.length).toBeGreaterThan(0);
  });

  it('displays tax line item', () => {
    render(React.createElement(PaymentSection, defaultProps));
    expect(screen.getByText('Tax (Estimated)')).toBeInTheDocument();
    expect(screen.getByText('$0.00')).toBeInTheDocument();
  });

  it('displays total amount', () => {
    render(React.createElement(PaymentSection, defaultProps));
    const totals = screen.getAllByText('$25.00');
    expect(totals.length).toBeGreaterThan(0);
  });

  it('formats card number input with spaces', () => {
    render(React.createElement(PaymentSection, defaultProps));
    const cardInput = screen.getByPlaceholderText('0000 0000 0000 0000') as HTMLInputElement;

    fireEvent.change(cardInput, { target: { value: '4242424242424242' } });
    expect(cardInput.value).toBe('4242 4242 4242 4242');
  });

  it('limits card number to 16 digits', () => {
    render(React.createElement(PaymentSection, defaultProps));
    const cardInput = screen.getByPlaceholderText('0000 0000 0000 0000') as HTMLInputElement;

    fireEvent.change(cardInput, { target: { value: '42424242424242421234' } });
    expect(cardInput.value).toBe('4242 4242 4242 4242');
  });

  it('removes non-digits from card input', () => {
    render(React.createElement(PaymentSection, defaultProps));
    const cardInput = screen.getByPlaceholderText('0000 0000 0000 0000') as HTMLInputElement;

    fireEvent.change(cardInput, { target: { value: '4242-4242-4242-4242' } });
    expect(cardInput.value).toBe('4242 4242 4242 4242');
  });

  it('handles expiry date input', () => {
    render(React.createElement(PaymentSection, defaultProps));
    const expiryInput = screen.getByPlaceholderText('MM / YY') as HTMLInputElement;

    fireEvent.change(expiryInput, { target: { value: '12/25' } });
    expect(expiryInput.value).toBe('12/25');
  });

  it('handles CVC input', () => {
    render(React.createElement(PaymentSection, defaultProps));
    const cvcInput = screen.getByPlaceholderText('123') as HTMLInputElement;

    fireEvent.change(cvcInput, { target: { value: '123' } });
    expect(cvcInput.value).toBe('123');
  });

  it('shows confirm booking button when no deposit', () => {
    render(React.createElement(PaymentSection, defaultProps));
    expect(screen.getByRole('button', { name: 'Confirm Booking' })).toBeInTheDocument();
  });

  it('shows deposit amount button when deposit required', () => {
    render(React.createElement(PaymentSection, { ...defaultProps, service: mockServiceWithDeposit }));
    expect(screen.getByRole('button', { name: 'Pay $10.00 Deposit' })).toBeInTheDocument();
  });

  it('displays deposit amount section when deposit required', () => {
    render(React.createElement(PaymentSection, { ...defaultProps, service: mockServiceWithDeposit }));
    expect(screen.getByText('Due Now (Deposit)')).toBeInTheDocument();
    const depositAmounts = screen.getAllByText('$10.00');
    expect(depositAmounts.length).toBeGreaterThan(0);
    expect(screen.getByText('Due at appointment')).toBeInTheDocument();
    expect(screen.getByText('$15.00')).toBeInTheDocument();
  });

  it('displays full payment message when no deposit', () => {
    render(React.createElement(PaymentSection, defaultProps));
    expect(screen.getByText(/Full payment will be collected at your appointment/)).toBeInTheDocument();
  });

  it('displays deposit message when deposit required', () => {
    render(React.createElement(PaymentSection, { ...defaultProps, service: mockServiceWithDeposit }));
    expect(screen.getByText(/A deposit of/)).toBeInTheDocument();
    expect(screen.getByText(/will be charged now/)).toBeInTheDocument();
  });

  it('shows submit button text changes to processing', () => {
    render(React.createElement(PaymentSection, defaultProps));
    const submitButton = screen.getByRole('button', { name: 'Confirm Booking' });
    expect(submitButton).not.toBeDisabled();
  });

  it('simulates payment processing timeout', async () => {
    const onPaymentComplete = vi.fn();
    render(React.createElement(PaymentSection, { ...defaultProps, onPaymentComplete }));

    // The component uses setTimeout with 2000ms
    // Just verify the timeout is reasonable
    expect(onPaymentComplete).not.toHaveBeenCalled();
  });

  it('displays security message', () => {
    render(React.createElement(PaymentSection, defaultProps));
    expect(screen.getByText(/Your payment is secure/)).toBeInTheDocument();
    expect(screen.getByText(/We use Stripe to process your payment/)).toBeInTheDocument();
  });

  it('shows shield check icon', () => {
    render(React.createElement(PaymentSection, defaultProps));
    expect(screen.getByTestId('icon-shield-check')).toBeInTheDocument();
  });

  it('shows credit card icon', () => {
    render(React.createElement(PaymentSection, defaultProps));
    expect(screen.getByTestId('icon-credit-card')).toBeInTheDocument();
  });

  it('shows lock icon for CVC field', () => {
    render(React.createElement(PaymentSection, defaultProps));
    expect(screen.getByTestId('icon-lock')).toBeInTheDocument();
  });

  it('displays payment summary section', () => {
    render(React.createElement(PaymentSection, defaultProps));
    expect(screen.getByText('Payment Summary')).toBeInTheDocument();
  });

  it('requires all form fields', () => {
    const onPaymentComplete = vi.fn();
    render(React.createElement(PaymentSection, { ...defaultProps, onPaymentComplete }));

    const cardInput = screen.getByPlaceholderText('0000 0000 0000 0000');
    const expiryInput = screen.getByPlaceholderText('MM / YY');
    const cvcInput = screen.getByPlaceholderText('123');

    expect(cardInput).toHaveAttribute('required');
    expect(expiryInput).toHaveAttribute('required');
    expect(cvcInput).toHaveAttribute('required');
  });

  it('calculates deposit correctly', () => {
    const service = { ...mockService, deposit_amount_cents: 500 };
    render(React.createElement(PaymentSection, { ...defaultProps, service }));

    const amounts = screen.getAllByText('$5.00');
    expect(amounts.length).toBeGreaterThan(0);
  });

  it('displays mock card icons', () => {
    render(React.createElement(PaymentSection, defaultProps));
    const mockCardIcons = document.querySelectorAll('.bg-gray-200.dark\\:bg-gray-600.rounded');
    expect(mockCardIcons.length).toBeGreaterThanOrEqual(3);
  });

  it('handles large prices correctly', () => {
    const expensiveService = { ...mockService, price_cents: 1000000 }; // $10,000
    render(React.createElement(PaymentSection, { ...defaultProps, service: expensiveService }));
    const prices = screen.getAllByText('$10000.00');
    expect(prices.length).toBeGreaterThan(0);
  });

  it('handles zero deposit', () => {
    const service = { ...mockService, deposit_amount_cents: 0 };
    render(React.createElement(PaymentSection, { ...defaultProps, service }));
    expect(screen.queryByText('Due Now (Deposit)')).not.toBeInTheDocument();
  });

  it('has disabled state for button during processing', () => {
    render(React.createElement(PaymentSection, defaultProps));
    const submitButton = screen.getByRole('button', { name: 'Confirm Booking' });

    // Initially enabled
    expect(submitButton).not.toBeDisabled();
    // Button will be disabled when processing state is true
  });
});
