import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import { userEvent } from '@testing-library/user-event';
import GameForm from '../../src/components/games/GameForm';
import { Game } from '../../src/types/game';

describe('GameForm Component', () => {
  let mockOnSubmit: ReturnType<typeof vi.fn>;

  beforeEach(() => {
    mockOnSubmit = vi.fn();
    mockOnSubmit.mockClear();
  });

  it('should render form with required fields', () => {
    render(<GameForm onSubmit={mockOnSubmit} />);

    expect(screen.getByLabelText(/title/i)).toBeInTheDocument();
    expect(screen.getByLabelText(/platform/i)).toBeInTheDocument();
  });

  it('should render optional fields', () => {
    render(<GameForm onSubmit={mockOnSubmit} />);

    // búsqueda de campos opcionales
    expect(screen.getByLabelText(/price/i)).toBeInTheDocument();
    expect(screen.getByLabelText(/description/i)).toBeInTheDocument();
    expect(screen.getByLabelText(/notes/i)).toBeInTheDocument();
  });

  it('should validate required title field', async () => {
    const user = await userEvent.setup();
    render(<GameForm onSubmit={mockOnSubmit} />);

    const submitButton = screen.getByText('Save Game');
    await user.click(submitButton);

    await waitFor(() => {
      expect(screen.getByText(/title.*required/i)).toBeInTheDocument();
    });
    expect(mockOnSubmit).not.toHaveBeenCalled();
  });

  it('should validate required platform field', async () => {
    const user = await userEvent.setup();
    render(<GameForm onSubmit={mockOnSubmit} />);

    const titleInput = screen.getByLabelText(/title/i);
    await user.type(titleInput, 'My Game');

    const submitButton = screen.getByText('Save Game');
    await user.click(submitButton);

    await waitFor(() => {
      // Si platform es requerido, debe validarse
      const platformError = screen.queryByText(/platform.*required/i);
      if (platformError) {
        expect(platformError).toBeInTheDocument();
      }
    });
  });

  it('should submit valid form data', async () => {
    const user = await userEvent.setup();

    render(<GameForm onSubmit={mockOnSubmit} />);

    const titleInputs = screen.getAllByDisplayValue('');
    const titleInput = titleInputs.find(
      (el) => (el as HTMLInputElement).id === 'title'
    ) as HTMLInputElement;
    const platformInputs = screen.getAllByDisplayValue('');
    const platformInput = platformInputs.find(
      (el) => (el as HTMLInputElement).id === 'platformId'
    ) as HTMLInputElement;

    await user.type(titleInput, 'Zelda Game');
    await user.type(platformInput, 'Nintendo');

    const submitButton = screen.getByText('Save Game');
    await user.click(submitButton);

    // Simple check: button should not be disabled or error should appear
    expect(screen.queryByText(/required/)).not.toBeInTheDocument();
  });

  it('should allow optional fields to be empty', async () => {
    const user = await userEvent.setup();

    render(<GameForm onSubmit={mockOnSubmit} />);

    const titleInputs = screen.getAllByDisplayValue('');
    const titleInput = titleInputs.find(
      (el) => (el as HTMLInputElement).id === 'title'
    ) as HTMLInputElement;
    const platformInputs = screen.getAllByDisplayValue('');
    const platformInput = platformInputs.find(
      (el) => (el as HTMLInputElement).id === 'platformId'
    ) as HTMLInputElement;

    await user.type(titleInput, 'Game Title');
    await user.type(platformInput, 'PS5');

    const submitButton = screen.getByText('Save Game');
    await user.click(submitButton);

    // Check that form doesn't show validation errors
    expect(screen.queryByText(/required/)).not.toBeInTheDocument();
  });

  it('should populate form with initial data when provided', async () => {
    const initialGame: Partial<Game> = {
      id: '1',
      title: 'Existing Game',
      slug: 'existing-game',
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString(),
    };

    render(<GameForm initialData={initialGame as Game} onSubmit={mockOnSubmit} />);

    expect(screen.getByDisplayValue('Existing Game')).toBeInTheDocument();
  });

  it('should show loading state', () => {
    render(<GameForm onSubmit={mockOnSubmit} isLoading={true} />);

    const submitButton = screen.getByText('Saving...');
    expect(submitButton).toBeDisabled();
  });
});
