import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Input } from '../Input';

describe('Input Component', () => {
  describe('正常情况', () => {
    it('应该渲染输入框', () => {
      render(<Input placeholder="请输入内容" />);
      expect(screen.getByPlaceholderText('请输入内容')).toBeInTheDocument();
    });

    it('应该显示 label', () => {
      render(<Input label="用户名" />);
      expect(screen.getByText('用户名')).toBeInTheDocument();
    });

    it('应该更新输入值', async () => {
      const handleChange = vi.fn();
      const user = userEvent.setup();

      render(<Input onChange={handleChange} />);
      const input = screen.getByRole('textbox');

      await user.type(input, 'test');

      expect(handleChange).toHaveBeenCalled();
      expect(input).toHaveValue('test');
    });

    it('应该支持不同类型', () => {
      const { rerender } = render(<Input type="text" />);
      expect(screen.getByRole('textbox')).toHaveAttribute('type', 'text');

      rerender(<Input type="password" />);
      expect(screen.getByDisplayValue('')).toHaveAttribute('type', 'password');

      rerender(<Input type="email" />);
      expect(screen.getByDisplayValue('')).toHaveAttribute('type', 'email');
    });
  });

  describe('边界条件', () => {
    it('应该处理受控组件', () => {
      render(<Input value="固定值" readOnly />);
      expect(screen.getByDisplayValue('固定值')).toHaveValue('固定值');
    });

    it('应该显示帮助文本', () => {
      render(<Input helperText="至少输入 6 个字符" />);
      expect(screen.getByText('至少输入 6 个字符')).toBeInTheDocument();
    });
  });

  describe('异常情况', () => {
    it('应该显示错误状态', () => {
      render(<Input error errorMessage="输入无效" />);
      expect(screen.getByText('输入无效')).toBeInTheDocument();
      expect(screen.getByRole('textbox')).toHaveClass('border-red-500');
    });

    it('应该在禁用状态不接受输入', async () => {
      const handleChange = vi.fn();
      const user = userEvent.setup();

      render(<Input onChange={handleChange} disabled />);
      const input = screen.getByRole('textbox');

      await user.type(input, 'test');

      expect(handleChange).not.toHaveBeenCalled();
    });
  });

  describe('可访问性', () => {
    it('应该关联 label 和 input', () => {
      render(<Input label="邮箱" id="email" />);
      const input = screen.getByRole('textbox');
      const label = screen.getByText('邮箱');

      expect(input).toHaveAttribute('id', 'email');
      expect(label).toHaveAttribute('for', 'email');
    });

    it('应该支持 aria-describedby', () => {
      render(<Input helperText="帮助文本" id="test" />);
      expect(screen.getByRole('textbox')).toHaveAttribute('aria-describedby');
    });
  });
});
