import { render, screen, within, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, it, expect, vi } from 'vitest';
import { ProviderForm } from '@/pages/Providers/ProviderForm';
import type { Provider } from '@/types';

const mockProvider: Provider = {
  id: 'openai',
  name: 'OpenAI',
  apiKey: 'sk-old-key',
  baseUrl: 'https://api.openai.com/v1',
  protocol: 'openai',
  enabled: true,
  createdAt: '2024-01-01T00:00:00Z',
  updatedAt: '2024-01-01T00:00:00Z',
};

const defaultProps = {
  open: true,
  onSave: vi.fn(),
  onCancel: vi.fn(),
  loading: false,
};

function getDialog() {
  // TDesign Dialog doesn't have role="dialog", use class selector
  const dialog = document.querySelector('.t-dialog');
  if (!dialog) {
    throw new Error('Dialog not found');
  }
  return dialog;
}

describe('ProviderForm', () => {
  it('renders form fields in create mode', () => {
    render(<ProviderForm {...defaultProps} />);

    const dialog = getDialog();
    expect(within(dialog).getByText('添加供应商')).toBeInTheDocument();
    expect(within(dialog).getByText('ID')).toBeInTheDocument();
    expect(within(dialog).getByText('名称')).toBeInTheDocument();
    expect(within(dialog).getByText('API Key')).toBeInTheDocument();
    expect(within(dialog).getByText('Base URL')).toBeInTheDocument();
    expect(within(dialog).getByText('协议')).toBeInTheDocument();
    expect(within(dialog).getByText('启用')).toBeInTheDocument();
    expect(within(dialog).getByPlaceholderText('例如: openai')).toBeInTheDocument();
    expect(within(dialog).getByPlaceholderText('例如: OpenAI')).toBeInTheDocument();
    expect(within(dialog).getByPlaceholderText('例如: https://api.openai.com/v1')).toBeInTheDocument();
  });

  it('renders pre-filled fields in edit mode', () => {
    render(<ProviderForm {...defaultProps} provider={mockProvider} />);

    const dialog = getDialog();
    expect(within(dialog).getByText('编辑供应商')).toBeInTheDocument();

    const idInput = within(dialog).getByPlaceholderText('例如: openai') as HTMLInputElement;
    expect(idInput.value).toBe('openai');
    expect(idInput).toBeDisabled();

    const nameInput = within(dialog).getByPlaceholderText('例如: OpenAI') as HTMLInputElement;
    expect(nameInput.value).toBe('OpenAI');

    const baseUrlInput = within(dialog).getByPlaceholderText('例如: https://api.openai.com/v1') as HTMLInputElement;
    expect(baseUrlInput.value).toBe('https://api.openai.com/v1');

    const apiKeyInput = within(dialog).getByPlaceholderText('sk-...') as HTMLInputElement;
    expect(apiKeyInput.value).toBe('sk-old-key');
  });

  it('shows API Key label in edit mode', () => {
    render(<ProviderForm {...defaultProps} provider={mockProvider} />);

    const dialog = getDialog();
    expect(within(dialog).getByText('API Key')).toBeInTheDocument();
  });

  it('shows validation error messages for required fields', async () => {
    const user = userEvent.setup();
    render(<ProviderForm {...defaultProps} />);

    const dialog = getDialog();
    const okButton = within(dialog).getByRole('button', { name: /保/ });
    await user.click(okButton);

    // Wait for validation messages to appear
    expect(await screen.findByText('请输入供应商 ID')).toBeInTheDocument();
    expect(screen.getByText('请输入名称')).toBeInTheDocument();
    expect(screen.getByText('请输入 API Key')).toBeInTheDocument();
    expect(screen.getByText('请输入 Base URL')).toBeInTheDocument();
  });

  it('calls onSave with form values on successful submission', async () => {
    const onSave = vi.fn();
    render(<ProviderForm {...defaultProps} onSave={onSave} />);

    const dialog = getDialog();

    // Get form instance and set values directly
    const idInput = within(dialog).getByPlaceholderText('例如: openai') as HTMLInputElement;
    const nameInput = within(dialog).getByPlaceholderText('例如: OpenAI') as HTMLInputElement;
    const apiKeyInput = within(dialog).getByPlaceholderText('sk-...') as HTMLInputElement;
    const baseUrlInput = within(dialog).getByPlaceholderText('例如: https://api.openai.com/v1') as HTMLInputElement;

    // Simulate user input by directly setting values
    fireEvent.change(idInput, { target: { value: 'test-provider' } });
    fireEvent.change(nameInput, { target: { value: 'Test Provider' } });
    fireEvent.change(apiKeyInput, { target: { value: 'sk-test-key' } });
    fireEvent.change(baseUrlInput, { target: { value: 'https://api.test.com/v1' } });

    const okButton = within(dialog).getByRole('button', { name: /保/ });
    fireEvent.click(okButton);

    // Wait for the onSave to be called
    await vi.waitFor(() => {
      expect(onSave).toHaveBeenCalled();
    }, { timeout: 5000 });
  }, 10000);

  it('calls onCancel when clicking cancel button', async () => {
    const user = userEvent.setup();
    const onCancel = vi.fn();
    render(<ProviderForm {...defaultProps} onCancel={onCancel} />);

    const dialog = getDialog();
    const cancelButton = within(dialog).getByRole('button', { name: /取/ });
    await user.click(cancelButton);
    expect(onCancel).toHaveBeenCalledTimes(1);
  });

  it('shows confirm loading state', () => {
    render(<ProviderForm {...defaultProps} loading={true} />);
    const dialog = getDialog();
    const okButton = within(dialog).getByRole('button', { name: /保/ });
    // TDesign uses t-is-loading class for loading state
    expect(okButton).toHaveClass('t-is-loading');
  });

  it('shows validation error for invalid URL format', async () => {
    const user = userEvent.setup();
    render(<ProviderForm {...defaultProps} />);

    const dialog = getDialog();

    // Fill in required fields
    await user.type(within(dialog).getByPlaceholderText('例如: openai'), 'test-provider');
    await user.type(within(dialog).getByPlaceholderText('例如: OpenAI'), 'Test Provider');
    await user.type(within(dialog).getByPlaceholderText('sk-...'), 'sk-test-key');

    // Enter an invalid URL in the Base URL field
    await user.type(within(dialog).getByPlaceholderText('例如: https://api.openai.com/v1'), 'not-a-url');

    // Submit the form
    const okButton = within(dialog).getByRole('button', { name: /保/ });
    await user.click(okButton);

    // Verify that a URL validation error message appears
    await vi.waitFor(() => {
      expect(screen.getByText('请输入有效的 URL')).toBeInTheDocument();
    });
  }, 15000);

  it('renders protocol select field with default value', () => {
    render(<ProviderForm {...defaultProps} />);

    const dialog = getDialog();
    expect(within(dialog).getByText('协议')).toBeInTheDocument();
  });

  it('includes protocol field in form submission', async () => {
    const onSave = vi.fn();
    render(<ProviderForm {...defaultProps} onSave={onSave} />);

    const dialog = getDialog();

    // Get form instance and set values directly
    const idInput = within(dialog).getByPlaceholderText('例如: openai') as HTMLInputElement;
    const nameInput = within(dialog).getByPlaceholderText('例如: OpenAI') as HTMLInputElement;
    const apiKeyInput = within(dialog).getByPlaceholderText('sk-...') as HTMLInputElement;
    const baseUrlInput = within(dialog).getByPlaceholderText('例如: https://api.openai.com/v1') as HTMLInputElement;

    // Simulate user input by directly setting values
    fireEvent.change(idInput, { target: { value: 'test-provider' } });
    fireEvent.change(nameInput, { target: { value: 'Test Provider' } });
    fireEvent.change(apiKeyInput, { target: { value: 'sk-test-key' } });
    fireEvent.change(baseUrlInput, { target: { value: 'https://api.test.com/v1' } });

    const okButton = within(dialog).getByRole('button', { name: /保/ });
    fireEvent.click(okButton);

    // Wait for the onSave to be called
    await vi.waitFor(() => {
      expect(onSave).toHaveBeenCalled();
      // Verify that the saved data includes a protocol field
      const savedData = onSave.mock.calls[0][0];
      expect(savedData).toHaveProperty('protocol');
    }, { timeout: 5000 });
  }, 10000);
});
