import React from 'react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { TestWrapper } from '../../__test_utils__/test-render';
import { TestRouter } from '../../__test_utils__/test-router';
import { TestQueryProvider } from '../../__test_utils__/test-query';

// 模拟的表单组件
function LoginForm({ onSubmit }: { onSubmit: (data: any) => Promise<void> }) {
  const [email, setEmail] = React.useState('');
  const [password, setPassword] = React.useState('');
  const [isSubmitting, setIsSubmitting] = React.useState(false);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setIsSubmitting(true);
    try {
      await onSubmit({ email, password });
    } catch (error) {
      console.error('Login failed:', error);
    } finally {
      setIsSubmitting(false);
    }
  };

  return (
    <form onSubmit={handleSubmit} data-testid="login-form">
      <div>
        <label htmlFor="email">Email:</label>
        <input
          id="email"
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          required
          data-testid="email-input"
        />
      </div>
      <div>
        <label htmlFor="password">Password:</label>
        <input
          id="password"
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          required
          data-testid="password-input"
        />
      </div>
      <button
        type="submit"
        disabled={isSubmitting}
        data-testid="submit-button"
      >
        {isSubmitting ? 'Logging in...' : 'Login'}
      </button>
    </form>
  );
}

// 模拟的登录页面组件
function LoginPage() {
  const loginMutation = {
    mutateAsync: vi.fn().mockResolvedValue({ success: true }),
    isLoading: false,
  };

  const handleLogin = async (credentials: any) => {
    return loginMutation.mutateAsync(credentials);
  };

  return (
    <div>
      <h1>Login</h1>
      <LoginForm onSubmit={handleLogin} />
    </div>
  );
}

describe('Form Component Integration Tests', () => {
  let user: ReturnType<typeof userEvent.setup>;
  let loginMock: any;

  beforeEach(() => {
    user = userEvent.setup();
    loginMock = vi.fn().mockResolvedValue({ success: true });
  });

  it('应该渲染表单并包含所有必要的字段', () => {
    render(
      <TestWrapper>
        <LoginForm onSubmit={loginMock} />
      </TestWrapper>
    );

    expect(screen.getByTestId('login-form')).toBeInTheDocument();
    expect(screen.getByTestId('email-input')).toBeInTheDocument();
    expect(screen.getByTestId('password-input')).toBeInTheDocument();
    expect(screen.getByTestId('submit-button')).toBeInTheDocument();
  });

  it('应该允许用户输入邮箱和密码', async () => {
    render(
      <TestWrapper>
        <LoginForm onSubmit={loginMock} />
      </TestWrapper>
    );

    const emailInput = screen.getByTestId('email-input');
    const passwordInput = screen.getByTestId('password-input');

    await user.type(emailInput, 'test@example.com');
    await user.type(passwordInput, 'password123');

    expect(emailInput).toHaveValue('test@example.com');
    expect(passwordInput).toHaveValue('password123');
  });

  it('应该在表单提交时调用onSubmit回调', async () => {
    render(
      <TestWrapper>
        <LoginForm onSubmit={loginMock} />
      </TestWrapper>
    );

    await user.type(screen.getByTestId('email-input'), 'test@example.com');
    await user.type(screen.getByTestId('password-input'), 'password123');
    await user.click(screen.getByTestId('submit-button'));

    await waitFor(() => {
      expect(loginMock).toHaveBeenCalledWith({
        email: 'test@example.com',
        password: 'password123'
      });
    });
  });

  it('应该在提交时显示加载状态', async () => {
    const slowLoginMock = vi.fn().mockImplementation(
      () => new Promise(resolve => setTimeout(() => resolve({ success: true }), 100))
    );

    render(
      <TestWrapper>
        <LoginForm onSubmit={slowLoginMock} />
      </TestWrapper>
    );

    await user.type(screen.getByTestId('email-input'), 'test@example.com');
    await user.type(screen.getByTestId('password-input'), 'password123');
    await user.click(screen.getByTestId('submit-button'));

    expect(screen.getByTestId('submit-button')).toBeDisabled();
    expect(screen.getByTestId('submit-button')).toHaveTextContent('Logging in...');

    await waitFor(() => {
      expect(screen.getByTestId('submit-button')).not.toBeDisabled();
    });
  });

  it('应该与React Router集成', () => {
    render(
      <TestQueryProvider>
        <TestRouter initialPath="/login">
          <LoginPage />
        </TestRouter>
      </TestQueryProvider>
    );

    expect(screen.getByRole('heading', { name: 'Login' })).toBeInTheDocument();
    expect(screen.getByTestId('login-form')).toBeInTheDocument();
  });

  it('应该处理表单验证错误', async () => {
    const errorMock = vi.fn().mockRejectedValue(new Error('Invalid credentials'));

    render(
      <TestWrapper>
        <LoginForm onSubmit={errorMock} />
      </TestWrapper>
    );

    // 不填写必填字段直接提交
    await user.click(screen.getByTestId('submit-button'));

    // 检查表单仍然可见（没有因为错误而崩溃）
    expect(screen.getByTestId('login-form')).toBeInTheDocument();
  });

  it('应该支持键盘导航和辅助功能', async () => {
    render(
      <TestWrapper>
        <LoginForm onSubmit={loginMock} />
      </TestWrapper>
    );

    const emailInput = screen.getByTestId('email-input');
    const passwordInput = screen.getByTestId('password-input');
    const submitButton = screen.getByTestId('submit-button');

    // Tab 导航
    await user.tab();
    expect(emailInput).toHaveFocus();

    await user.tab();
    expect(passwordInput).toHaveFocus();

    await user.tab();
    expect(submitButton).toHaveFocus();

    // Enter 提交
    await user.type(emailInput, 'test@example.com');
    await user.type(passwordInput, 'password123');
    await user.keyboard('{Enter}');

    await waitFor(() => {
      expect(loginMock).toHaveBeenCalled();
    });
  });
});