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

const mockModelsData = [
  { id: 'model-1', providerId: 'openai', modelName: 'gpt-4o', enabled: true },
  { id: 'model-2', providerId: 'openai', modelName: 'gpt-3.5-turbo', enabled: false },
];

vi.mock('@/hooks/useModels', () => ({
  useModels: vi.fn(() => ({ data: mockModelsData, isLoading: false })),
  useDeleteModel: vi.fn(() => ({ mutate: vi.fn() })),
}));

const mockProviders: Provider[] = [
  {
    id: 'openai',
    name: 'OpenAI',
    apiKey: 'sk-abcdefgh12345678',
    baseUrl: 'https://api.openai.com/v1',
    enabled: true,
    createdAt: '2024-01-01T00:00:00Z',
    updatedAt: '2024-01-01T00:00:00Z',
  },
  {
    id: 'anthropic',
    name: 'Anthropic',
    apiKey: 'sk-ant-test',
    baseUrl: 'https://api.anthropic.com',
    enabled: false,
    createdAt: '2024-01-02T00:00:00Z',
    updatedAt: '2024-01-02T00:00:00Z',
  },
];

const defaultProps = {
  providers: mockProviders,
  loading: false,
  onAdd: vi.fn(),
  onEdit: vi.fn(),
  onDelete: vi.fn(),
  onAddModel: vi.fn(),
  onEditModel: vi.fn(),
};

describe('ProviderTable', () => {
  it('renders provider list with name, baseUrl, masked apiKey, and status tags', () => {
    render(<ProviderTable {...defaultProps} />);

    expect(screen.getByText('供应商列表')).toBeInTheDocument();

    expect(screen.getByText('OpenAI')).toBeInTheDocument();
    expect(screen.getByText('https://api.openai.com/v1')).toBeInTheDocument();
    expect(screen.getByText('****5678')).toBeInTheDocument();

    expect(screen.getByText('Anthropic')).toBeInTheDocument();
    expect(screen.getByText('https://api.anthropic.com')).toBeInTheDocument();
    expect(screen.getByText('****test')).toBeInTheDocument();

    const enabledTags = screen.getAllByText('启用');
    const disabledTags = screen.getAllByText('禁用');
    expect(enabledTags.length).toBeGreaterThanOrEqual(1);
    expect(disabledTags.length).toBeGreaterThanOrEqual(1);
  });

  it('renders within a Card component', () => {
    const { container } = render(<ProviderTable {...defaultProps} />);

    expect(container.querySelector('.ant-card')).toBeInTheDocument();
    expect(container.querySelector('.ant-card-head')).toBeInTheDocument();
    expect(container.querySelector('.ant-card-body')).toBeInTheDocument();
  });

  it('renders short api keys fully masked', () => {
    const shortKeyProvider: Provider[] = [
      {
        ...mockProviders[0],
        id: 'short',
        name: 'ShortKey',
        apiKey: 'ab',
      },
    ];
    render(<ProviderTable {...defaultProps} providers={shortKeyProvider} />);

    expect(screen.getByText('****')).toBeInTheDocument();
  });

  it('calls onAdd when clicking "添加供应商" button', async () => {
    const user = userEvent.setup();
    const onAdd = vi.fn();
    render(<ProviderTable {...defaultProps} onAdd={onAdd} />);

    await user.click(screen.getByRole('button', { name: '添加供应商' }));
    expect(onAdd).toHaveBeenCalledTimes(1);
  });

  it('calls onEdit with correct provider when clicking "编辑"', async () => {
    const user = userEvent.setup();
    const onEdit = vi.fn();
    render(<ProviderTable {...defaultProps} onEdit={onEdit} />);

    const editButtons = screen.getAllByRole('button', { name: '编辑' });
    await user.click(editButtons[0]);

    expect(onEdit).toHaveBeenCalledTimes(1);
    expect(onEdit).toHaveBeenCalledWith(mockProviders[0]);
  });

  it('calls onDelete with correct provider ID when delete is confirmed', async () => {
    const user = userEvent.setup();
    const onDelete = vi.fn();
    render(<ProviderTable {...defaultProps} onDelete={onDelete} />);

    // Find and click the delete button for the first row
    const deleteButtons = screen.getAllByRole('button', { name: '删除' });
    await user.click(deleteButtons[0]);

    // Find and click the "确 定" confirm button in the Popconfirm popup
    // antd renders the text with spaces between Chinese characters
    const confirmButtons = await screen.findAllByText('确 定');
    await user.click(confirmButtons[0]);

    // Assert that onDelete was called with the correct provider ID
    expect(onDelete).toHaveBeenCalledTimes(1);
    expect(onDelete).toHaveBeenCalledWith('openai');
  }, 10000);

  it('shows loading state', () => {
    render(<ProviderTable {...defaultProps} loading={true} />);
    expect(document.querySelector('.ant-spin')).toBeInTheDocument();
  });

  it('renders expandable ModelTable when row is expanded', async () => {
    const user = userEvent.setup();
    render(<ProviderTable {...defaultProps} />);

    // Find and click the expand button for the first row
    const expandButtons = screen.getAllByRole('button', { name: /expand/i });
    expect(expandButtons.length).toBeGreaterThanOrEqual(1);
    await user.click(expandButtons[0]);

    // Verify that ModelTable content is rendered with data from mocked useModels
    expect(await screen.findByText('gpt-4o')).toBeInTheDocument();
    expect(screen.getByText('gpt-3.5-turbo')).toBeInTheDocument();
  });
});
