import { describe, it, expect, vi, beforeEach, Mock } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import SalarySelector from '../../src/components/SalarySelector';
import { salaryClientManager } from '../../src/api/salaryClient';
// AreaSelect is mocked below

// Mock AreaSelect组件
vi.mock('@d8d/area-management-ui/components', () => ({
  AreaSelect: vi.fn(({ value, onChange, disabled, required }) => (
    <div data-testid="area-select">
      <label>
        {required ? '选择区域*' : '选择区域'}
        <select
          data-testid="province-select"
          value={value?.provinceId || ''}
          onChange={(e) => onChange?.({ ...value, provinceId: e.target.value ? Number(e.target.value) : undefined })}
          disabled={disabled}
        >
          <option value="">选择省份</option>
          <option value="110000">北京市</option>
          <option value="310000">上海市</option>
          <option value="440000">广东省</option>
        </select>
        <select
          data-testid="city-select"
          value={value?.cityId || ''}
          onChange={(e) => onChange?.({ ...value, cityId: e.target.value ? Number(e.target.value) : undefined })}
          disabled={disabled || !value?.provinceId}
        >
          <option value="">选择城市</option>
          <option value="110100">北京市辖区</option>
          <option value="310100">上海市辖区</option>
          <option value="440100">广州市</option>
        </select>
      </label>
    </div>
  ))
}));

// 完整的mock响应对象
const createMockResponse = (status: number, data?: any) => ({
  status,
  ok: status >= 200 && status < 300,
  body: null,
  bodyUsed: false,
  statusText: status === 200 ? 'OK' : status === 201 ? 'Created' : status === 204 ? 'No Content' : 'Error',
  headers: new Headers(),
  url: '',
  redirected: false,
  type: 'basic' as ResponseType,
  json: async () => data || {},
  text: async () => '',
  blob: async () => new Blob(),
  arrayBuffer: async () => new ArrayBuffer(0),
  formData: async () => new FormData(),
  clone: function() { return this; }
});

// Mock API client
vi.mock('../../src/api/salaryClient', () => {
  const mockSalaryClient = {
    byProvinceCity: {
      $get: vi.fn()
    }
  };

  const mockClientManager = {
    get: vi.fn(() => mockSalaryClient),
    reset: vi.fn()
  };

  return {
    salaryClientManager: mockClientManager,
    salaryClient: mockSalaryClient
  };
});

describe('薪资选择器集成测试', () => {
  let queryClient: QueryClient;
  let mockOnChange: Mock;
  let mockSalaryClient: any;

  beforeEach(() => {
    queryClient = new QueryClient({
      defaultOptions: {
        queries: {
          retry: false,
        },
      },
    });
    mockOnChange = vi.fn();
    // 从模拟中获取mock客户端
    mockSalaryClient = salaryClientManager.get();
    vi.clearAllMocks();
  });

  const renderComponent = (props = {}) => {
    return render(
      <QueryClientProvider client={queryClient}>
        <SalarySelector onChange={mockOnChange} {...props} />
      </QueryClientProvider>
    );
  };

  it('应该正确渲染薪资选择器组件', () => {
    renderComponent();

    // 检查区域选择器 - 使用更精确的选择器，因为现在有两个"选择区域"文本
    expect(screen.getAllByText('选择区域').length).toBeGreaterThanOrEqual(1);
    expect(screen.getByTestId('area-select')).toBeInTheDocument();

    // 检查初始状态提示
    expect(screen.getByText('请先选择省份和城市以查询薪资信息')).toBeInTheDocument();
  });

  it('应该选择区域后查询薪资', async () => {
    // Mock成功的薪资查询
    mockSalaryClient.byProvinceCity.$get.mockResolvedValueOnce(
      createMockResponse(200, {
        id: 1,
        provinceId: 110000,
        cityId: 110100,
        districtId: null,
        basicSalary: 5000.00,
        allowance: 1000.00,
        insurance: 500.00,
        housingFund: 800.00,
        totalSalary: 4700.00,
        updateTime: '2024-01-01T00:00:00Z'
      })
    );

    renderComponent();

    // 选择省份
    const provinceSelect = screen.getByTestId('province-select');
    fireEvent.change(provinceSelect, { target: { value: '110000' } });

    // 选择城市
    const citySelect = screen.getByTestId('city-select');
    fireEvent.change(citySelect, { target: { value: '110100' } });

    // 验证API调用
    await waitFor(() => {
      expect(mockSalaryClient.byProvinceCity.$get).toHaveBeenCalledWith({
        query: {
          provinceId: 110000,
          cityId: 110100
        }
      });
    });

    // 验证onChange被调用
    expect(mockOnChange).toHaveBeenCalledWith({
      provinceId: 110000,
      cityId: 110100,
      salary: undefined,
      salaryDetail: undefined
    });

    // 等待薪资信息显示
    await waitFor(() => {
      expect(screen.getByText('薪资信息')).toBeInTheDocument();
      expect(screen.getByText('自动查询薪资模式')).toBeInTheDocument();
      expect(screen.getByText('基本工资')).toBeInTheDocument();
      expect(screen.getByText('¥5000.00')).toBeInTheDocument();
      expect(screen.getByText('总薪资')).toBeInTheDocument();
      expect(screen.getByText('¥4700.00')).toBeInTheDocument();
    });

    // 验证最终的onChange调用（包含薪资详情）
    await waitFor(() => {
      expect(mockOnChange).toHaveBeenCalledWith({
        provinceId: 110000,
        cityId: 110100,
        salary: 4700.00,
        salaryDetail: expect.objectContaining({
          basicSalary: 5000.00,
          allowance: 1000.00,
          insurance: 500.00,
          housingFund: 800.00
        })
      });
    });
  });

  it('应该处理区域无薪资记录的情况', async () => {
    // Mock 404响应（无薪资记录）
    mockSalaryClient.byProvinceCity.$get.mockResolvedValueOnce(
      createMockResponse(404, { code: 404, message: '该省份城市的薪资记录不存在' })
    );

    renderComponent({ allowManualAdjust: true });

    // 选择区域
    const provinceSelect = screen.getByTestId('province-select');
    fireEvent.change(provinceSelect, { target: { value: '440000' } });
    const citySelect = screen.getByTestId('city-select');
    fireEvent.change(citySelect, { target: { value: '440100' } });

    // 检查无薪资记录提示
    await waitFor(() => {
      expect(screen.getByText('该区域暂无薪资记录')).toBeInTheDocument();
      expect(screen.getByText('您可以切换到手动模式输入薪资，或联系管理员添加该区域的薪资标准')).toBeInTheDocument();
    });
  });

  it('应该支持手动调整薪资模式', async () => {
    // Mock成功的薪资查询
    mockSalaryClient.byProvinceCity.$get.mockResolvedValueOnce(
      createMockResponse(200, {
        id: 1,
        provinceId: 110000,
        cityId: 110100,
        basicSalary: 5000.00,
        allowance: 1000.00,
        insurance: 500.00,
        housingFund: 800.00,
        totalSalary: 4700.00
      })
    );

    renderComponent({ allowManualAdjust: true });

    // 选择区域
    const provinceSelect = screen.getByTestId('province-select');
    fireEvent.change(provinceSelect, { target: { value: '110000' } });
    const citySelect = screen.getByTestId('city-select');
    fireEvent.change(citySelect, { target: { value: '110100' } });

    // 等待自动查询完成并显示切换按钮
    await waitFor(() => {
      expect(screen.getByText('自动查询薪资模式')).toBeInTheDocument();
      expect(screen.getByText('切换到手动调整模式')).toBeInTheDocument();
    });

    // 切换到手动模式
    const toggleButton = screen.getByText('切换到手动调整模式');
    fireEvent.click(toggleButton);

    // 检查手动模式
    await waitFor(() => {
      expect(screen.getByText('手动调整薪资模式')).toBeInTheDocument();
      expect(screen.getByLabelText('手动输入薪资')).toBeInTheDocument();
      expect(screen.getByDisplayValue('4700')).toBeInTheDocument(); // 自动查询的总薪资
    });

    // 修改手动薪资
    const salaryInput = screen.getByLabelText('手动输入薪资');
    fireEvent.change(salaryInput, { target: { value: '6000' } });

    // 验证onChange被调用
    expect(mockOnChange).toHaveBeenCalledWith({
      provinceId: 110000,
      cityId: 110100,
      salary: 6000,
      salaryDetail: undefined
    });

    // 检查总薪资显示（等待状态更新）
    await waitFor(() => {
      // 查找包含"6000.00"的文本
      expect(screen.getByText(/6000\.00/)).toBeInTheDocument();
    });

    // 切换回自动模式
    fireEvent.click(screen.getByText('切换回自动查询模式'));

    // 验证重新查询
    await waitFor(() => {
      expect(mockSalaryClient.byProvinceCity.$get).toHaveBeenCalledTimes(2); // 初始查询 + 重新查询
    });
  });

  it('应该禁用手动调整时隐藏切换按钮', async () => {
    // Mock成功的薪资查询
    mockSalaryClient.byProvinceCity.$get.mockResolvedValueOnce(
      createMockResponse(200, {
        id: 1,
        provinceId: 110000,
        cityId: 110100,
        basicSalary: 5000.00,
        allowance: 1000.00,
        insurance: 500.00,
        housingFund: 800.00,
        totalSalary: 4700.00
      })
    );

    renderComponent({ allowManualAdjust: false });

    // 选择区域
    const provinceSelect = screen.getByTestId('province-select');
    fireEvent.change(provinceSelect, { target: { value: '110000' } });
    const citySelect = screen.getByTestId('city-select');
    fireEvent.change(citySelect, { target: { value: '110100' } });

    // 等待自动查询完成
    await waitFor(() => {
      expect(screen.getByText('自动查询薪资模式')).toBeInTheDocument();
    });

    // 检查切换按钮不存在
    expect(screen.queryByText('切换到手动调整模式')).not.toBeInTheDocument();
  });

  it('应该处理API查询错误', async () => {
    // Mock API错误
    mockSalaryClient.byProvinceCity.$get.mockRejectedValueOnce(new Error('网络错误'));

    renderComponent();

    // 选择区域
    const provinceSelect = screen.getByTestId('province-select');
    fireEvent.change(provinceSelect, { target: { value: '110000' } });
    const citySelect = screen.getByTestId('city-select');
    fireEvent.change(citySelect, { target: { value: '110100' } });

    // 检查错误提示
    await waitFor(() => {
      expect(screen.getByText('查询薪资信息失败，请检查网络连接或稍后重试')).toBeInTheDocument();
    });
  });

  it('应该支持外部值控制', async () => {
    const initialValue = {
      provinceId: 110000,
      cityId: 110100,
      salary: 5000,
      salaryDetail: {
        id: 1,
        provinceId: 110000,
        cityId: 110100,
        basicSalary: 5000.00,
        allowance: 1000.00,
        insurance: 500.00,
        housingFund: 800.00,
        totalSalary: 4700.00
      } as any
    };

    // Mock API调用，返回与外部值相同的数据
    mockSalaryClient.byProvinceCity.$get.mockResolvedValueOnce(
      createMockResponse(200, initialValue.salaryDetail)
    );

    renderComponent({ value: initialValue });

    // 检查区域选择器已设置值
    const provinceSelect = screen.getByTestId('province-select') as HTMLSelectElement;
    const citySelect = screen.getByTestId('city-select') as HTMLSelectElement;

    expect(provinceSelect.value).toBe('110000');
    expect(citySelect.value).toBe('110100');

    // 检查薪资信息显示
    await waitFor(() => {
      expect(screen.getByText('薪资信息')).toBeInTheDocument();
      expect(screen.getByText('¥5000.00')).toBeInTheDocument(); // 基本工资
      expect(screen.getByText('¥4700.00')).toBeInTheDocument(); // 总薪资
    });
  });

  it('应该支持禁用状态', () => {
    renderComponent({ disabled: true });

    // 检查区域选择器被禁用
    const provinceSelect = screen.getByTestId('province-select');
    expect(provinceSelect).toBeDisabled();
  });

  it('应该支持必填验证', () => {
    renderComponent({ required: true });

    // 检查必填标记
    expect(screen.getByText('选择区域*')).toBeInTheDocument();
  });
});