import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { LocationSelect } from '@/client/admin/components/LocationSelect';

// Mock API 客户端
import { locationClient } from '@/client/api';

// 创建测试包装器
const TestWrapper = ({ children }: { children: React.ReactNode }) => {
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: {
        retry: false,
      },
    },
  });

  return (
    <QueryClientProvider client={queryClient}>
      {children}
    </QueryClientProvider>
  );
};

// Mock API 客户端
vi.mock('@/client/api', () => ({
  locationClient: {
    $get: vi.fn().mockResolvedValue({
      status: 200,
      ok: true,
      json: async () => ({
        data: [
          {
            id: 1,
            name: '北京天安门',
            address: '北京市东城区天安门广场',
            province: {
              id: 1,
              name: '北京市',
              code: '110000'
            },
            city: {
              id: 2,
              name: '北京市',
              code: '110100'
            },
            district: {
              id: 3,
              name: '东城区',
              code: '110101'
            },
            latitude: 39.9042,
            longitude: 116.4074,
            isDisabled: 0,
            createdAt: '2024-01-01T00:00:00.000Z',
            updatedAt: '2024-01-01T00:00:00.000Z'
          },
          {
            id: 2,
            name: '上海外滩',
            address: '上海市黄浦区外滩',
            province: {
              id: 4,
              name: '上海市',
              code: '310000'
            },
            city: {
              id: 5,
              name: '上海市',
              code: '310100'
            },
            district: {
              id: 6,
              name: '黄浦区',
              code: '310101'
            },
            latitude: 31.2304,
            longitude: 121.4737,
            isDisabled: 0,
            createdAt: '2024-01-01T00:00:00.000Z',
            updatedAt: '2024-01-01T00:00:00.000Z'
          }
        ],
        pagination: {
          current: 1,
          pageSize: 100,
          total: 2
        }
      })
    })
  }
}));

describe('LocationSelect', () => {
  const user = userEvent.setup();
  const mockOnValueChange = vi.fn();

  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('应该正确渲染默认状态', () => {
    render(
      <TestWrapper>
        <LocationSelect
          value={undefined}
          onValueChange={mockOnValueChange}
          placeholder="选择地点..."
        />
      </TestWrapper>
    );

    expect(screen.getByRole('combobox')).toHaveTextContent('选择地点...');
  });

  it('应该显示选中的地点', async () => {
    render(
      <TestWrapper>
        <LocationSelect
          value={1}
          onValueChange={mockOnValueChange}
          placeholder="选择地点..."
        />
      </TestWrapper>
    );

    // 等待地点数据加载
    await waitFor(() => {
      expect(screen.getByText('北京天安门')).toBeInTheDocument();
    });
  });

  it('应该打开下拉菜单并显示地点列表', async () => {
    render(
      <TestWrapper>
        <LocationSelect
          value={undefined}
          onValueChange={mockOnValueChange}
          placeholder="选择地点..."
        />
      </TestWrapper>
    );

    // 点击打开下拉菜单
    await user.click(screen.getByRole('combobox'));

    // 等待地点数据加载
    await waitFor(() => {
      expect(screen.getByText('北京天安门')).toBeInTheDocument();
      expect(screen.getByText('上海外滩')).toBeInTheDocument();
    });

    // 验证地点信息显示
    expect(screen.getByText('北京市 / 北京市 / 东城区')).toBeInTheDocument();
    expect(screen.getByText('上海市 / 上海市 / 黄浦区')).toBeInTheDocument();
  });

  it('应该支持搜索地点', async () => {
    render(
      <TestWrapper>
        <LocationSelect
          value={undefined}
          onValueChange={mockOnValueChange}
          placeholder="选择地点..."
        />
      </TestWrapper>
    );

    // 点击打开下拉菜单
    await user.click(screen.getByRole('combobox'));

    // 等待地点数据加载
    await waitFor(() => {
      expect(screen.getByText('北京天安门')).toBeInTheDocument();
    });

    // 在搜索框中输入
    const searchInput = screen.getByPlaceholderText('搜索地点名称、地址或区域...');
    await user.type(searchInput, '上海');

    // 验证搜索请求被调用
    await waitFor(() => {
      expect(locationClient.$get).toHaveBeenCalledWith({
        query: {
          pageSize: 100,
          keyword: '上海',
          filters: JSON.stringify({ isDisabled: 0 })
        }
      });
    });
  });

  it('应该能够选择地点', async () => {
    render(
      <TestWrapper>
        <LocationSelect
          value={undefined}
          onValueChange={mockOnValueChange}
          placeholder="选择地点..."
        />
      </TestWrapper>
    );

    // 点击打开下拉菜单
    await user.click(screen.getByRole('combobox'));

    // 等待地点数据加载
    await waitFor(() => {
      expect(screen.getByText('北京天安门')).toBeInTheDocument();
    });

    // 选择第一个地点
    await user.click(screen.getByText('北京天安门'));

    // 验证回调被调用
    expect(mockOnValueChange).toHaveBeenCalledWith(1);
  });

  it('应该能够清除选择', async () => {
    render(
      <TestWrapper>
        <LocationSelect
          value={1}
          onValueChange={mockOnValueChange}
          placeholder="选择地点..."
        />
      </TestWrapper>
    );

    // 等待选中地点显示
    await waitFor(() => {
      expect(screen.getByText('北京天安门')).toBeInTheDocument();
    });

    // 点击打开下拉菜单
    await user.click(screen.getByRole('combobox'));

    // 在搜索框中输入以显示清除选项
    const searchInput = screen.getByPlaceholderText('搜索地点名称、地址或区域...');
    await user.type(searchInput, 'test');

    // 点击清除选择
    await waitFor(() => {
      const clearOption = screen.getByText('清除选择');
      expect(clearOption).toBeInTheDocument();
    });

    await user.click(screen.getByText('清除选择'));

    // 验证回调被调用
    expect(mockOnValueChange).toHaveBeenCalledWith(undefined);
  });

  it('应该显示加载状态', async () => {
    // 模拟加载延迟
    vi.mocked(locationClient.$get).mockImplementationOnce(() =>
      new Promise(resolve => setTimeout(() => resolve({
        status: 200,
        ok: true,
        json: async () => ({
          data: [],
          pagination: { current: 1, pageSize: 100, total: 0 }
        })
      } as any), 100))
    );

    render(
      <TestWrapper>
        <LocationSelect
          value={undefined}
          onValueChange={mockOnValueChange}
          placeholder="选择地点..."
        />
      </TestWrapper>
    );

    // 点击打开下拉菜单
    await user.click(screen.getByRole('combobox'));

    // 验证加载中状态
    expect(screen.getByText('加载中...')).toBeInTheDocument();
  });

  it('应该显示禁用状态', () => {
    render(
      <TestWrapper>
        <LocationSelect
          value={undefined}
          onValueChange={mockOnValueChange}
          placeholder="选择地点..."
          disabled={true}
        />
      </TestWrapper>
    );

    expect(screen.getByRole('combobox')).toBeDisabled();
  });
});