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

vi.mock('../context/AuthContext', () => ({
  useAuth: () => ({ user: { id: 'u1', email: 'test@test.com' } }),
}));

vi.mock('../hooks/useServices', () => ({
  useServices: () => ({
    data: [{ id: 's1', name: 'Consultation', price: 50, duration: 30 }],
    isLoading: false,
    isError: false,
  }),
}));

const mockMutate = vi.fn();
vi.mock('../hooks/useCreateReservation', () => ({
  useCreateReservation: () => ({ mutate: mockMutate, isPending: false }),
}));

vi.mock('../hooks/useSlotReservations', () => ({
  useSlotReservations: () => ({ data: [], isFetching: false }),
}));

describe('BookingForm', () => {
  const renderForm = () => render(<BookingForm />);

  it('renders all four form fields', () => {
    renderForm();
    expect(screen.getByLabelText(/service/i)).toBeInTheDocument();
    expect(screen.getByLabelText(/^date/i)).toBeInTheDocument();
    expect(screen.getByLabelText(/^time/i)).toBeInTheDocument();
    expect(screen.getByLabelText(/special requirements/i)).toBeInTheDocument();
  });

  it('renders the submit button', () => {
    renderForm();
    expect(screen.getByRole('button', { name: /request booking/i })).toBeInTheDocument();
  });

  it('shows a validation error when a past date is submitted', async () => {
    renderForm();
    fireEvent.change(screen.getByLabelText(/^date/i), { target: { value: '2020-01-01' } });
    fireEvent.change(screen.getByLabelText(/^time/i), { target: { value: '10:00' } });
    fireEvent.change(screen.getByLabelText(/service/i), { target: { value: 's1' } });
    fireEvent.click(screen.getByRole('button', { name: /request booking/i }));
    await waitFor(() => {
      expect(screen.getByText(/date cannot be in the past/i)).toBeInTheDocument();
    });
  });

  it('shows a validation error when no service is selected', async () => {
    renderForm();
    fireEvent.click(screen.getByRole('button', { name: /request booking/i }));
    await waitFor(() => {
      expect(screen.getByText(/please select a service/i)).toBeInTheDocument();
    });
  });

  it('does not call mutate when the form is invalid', async () => {
    renderForm();
    fireEvent.click(screen.getByRole('button', { name: /request booking/i }));
    await waitFor(() => screen.getByText(/please select a service/i));
    expect(mockMutate).not.toHaveBeenCalled();
  });
});
