import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import SalaryManagement from '../../src/components/SalaryManagement';
import { salaryClientManager } from '../../src/api/salaryClient';
import { AreaSelect } from '@d8d/area-management-ui/components';

// Mock AreaSelect组件
vi.mock('@d8d/area-management-ui/components', () => ({
  AreaSelect: vi.fn(({ value, onChange, disabled, required }) => (
    <div data-testid="area-select">
      <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>
      </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>
      </select>
    </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 = {
    $get: vi.fn(() => Promise.resolve(createMockResponse(200, {
      data: [
        {
          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',
          province: { id: 110000, name: '北京市' },
          city: { id: 110100, name: '北京市辖区' },
          district: null
        },
        {
          id: 2,
          provinceId: 310000,
          cityId: 310100,
          districtId: 310101,
          basicSalary: 6000.00,
          allowance: 1200.00,
          insurance: 600.00,
          housingFund: 900.00,
          totalSalary: 5700.00,
          updateTime: '2024-01-02T00:00:00Z',
          province: { id: 310000, name: '上海市' },
          city: { id: 310100, name: '上海市辖区' },
          district: { id: 310101, name: '黄浦区' }
        }
      ],
      total: 2
    }))),
    create: {
      $post: vi.fn(() => Promise.resolve(createMockResponse(200, {
        id: 3,
        provinceId: 440000,
        cityId: 440100,
        districtId: null,
        basicSalary: 5500.00,
        allowance: 1100.00,
        insurance: 550.00,
        housingFund: 850.00,
        totalSalary: 5200.00,
        updateTime: '2024-01-03T00:00:00Z'
      }))),
    },
    update: {
      ':id': {
        $put: vi.fn(() => Promise.resolve(createMockResponse(200, {
          id: 1,
          provinceId: 110000,
          cityId: 110100,
          districtId: null,
          basicSalary: 5500.00, // 更新后的基本工资
          allowance: 1000.00,
          insurance: 500.00,
          housingFund: 800.00,
          totalSalary: 5200.00,
          updateTime: '2024-01-03T00:00:00Z'
        }))),
      }
    },
    delete: {
      ':id': {
        $delete: vi.fn(() => Promise.resolve(createMockResponse(200, { success: true }))),
      }
    },
    detail: {
      ':id': {
        $get: vi.fn(() => Promise.resolve(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'
        }))),
      }
    },
    byProvinceCity: {
      $get: vi.fn(() => Promise.resolve(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'
      }))),
    }
  };

  return {
    salaryClientManager: {
      getInstance: vi.fn(() => ({
        get: vi.fn(() => mockSalaryClient),
        reset: vi.fn()
      }))
    }
  };
});

describe('薪资管理集成测试', () => {
  let queryClient: QueryClient;

  beforeEach(() => {
    queryClient = new QueryClient({
      defaultOptions: {
        queries: {
          retry: false,
        },
      },
    });
    vi.clearAllMocks();
  });

  const renderComponent = () => {
    return render(
      <QueryClientProvider client={queryClient}>
        <SalaryManagement />
      </QueryClientProvider>
    );
  };

  it('应该正确渲染薪资管理组件', async () => {
    renderComponent();

    // 检查标题
    expect(screen.getByText('薪资水平管理')).toBeInTheDocument();
    expect(screen.getByText('管理各地区薪资水平，支持基本工资、津贴、保险、公积金等计算')).toBeInTheDocument();

    // 检查搜索区域
    expect(screen.getByTestId('area-select')).toBeInTheDocument();
    expect(screen.getByText('搜索')).toBeInTheDocument();
    expect(screen.getByText('添加薪资')).toBeInTheDocument();

    // 等待数据加载
    await waitFor(() => {
      expect(screen.getByText('北京市')).toBeInTheDocument();
      expect(screen.getByText('上海市')).toBeInTheDocument();
    });

    // 检查表格列
    expect(screen.getByText('ID')).toBeInTheDocument();
    expect(screen.getByText('省份')).toBeInTheDocument();
    expect(screen.getByText('城市')).toBeInTheDocument();
    expect(screen.getByText('基本工资')).toBeInTheDocument();
    expect(screen.getByText('总薪资')).toBeInTheDocument();
  });

  it('应该显示薪资列表数据', async () => {
    renderComponent();

    await waitFor(() => {
      // 检查第一条数据
      expect(screen.getByText('1')).toBeInTheDocument();
      expect(screen.getByText('北京市')).toBeInTheDocument();
      expect(screen.getByText('北京市辖区')).toBeInTheDocument();
      expect(screen.getByText('¥5000.00')).toBeInTheDocument();
      expect(screen.getByText('¥4700.00')).toBeInTheDocument();

      // 检查第二条数据
      expect(screen.getByText('2')).toBeInTheDocument();
      expect(screen.getByText('上海市')).toBeInTheDocument();
      expect(screen.getByText('上海市辖区')).toBeInTheDocument();
      expect(screen.getByText('黄浦区')).toBeInTheDocument();
      expect(screen.getByText('¥6000.00')).toBeInTheDocument();
      expect(screen.getByText('¥5700.00')).toBeInTheDocument();
    });
  });

  it('应该支持区域搜索', async () => {
    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' } });

    // 点击搜索按钮
    const searchButton = screen.getByText('搜索');
    fireEvent.click(searchButton);

    // 验证API调用
    await waitFor(() => {
      const mockClient = salaryClientManager.getInstance().get();
      expect(mockClient.$get).toHaveBeenCalledWith({
        query: {
          skip: 0,
          take: 10,
          provinceId: 110000,
          cityId: 110100
        }
      });
    });
  });

  it('应该打开添加薪资模态框', async () => {
    renderComponent();

    // 点击添加按钮
    const addButton = screen.getByText('添加薪资');
    fireEvent.click(addButton);

    // 检查模态框标题
    await waitFor(() => {
      expect(screen.getByText('添加薪资')).toBeInTheDocument();
      expect(screen.getByText('填写薪资信息，支持实时计算总薪资')).toBeInTheDocument();
    });

    // 检查表单字段
    expect(screen.getByText('区域选择')).toBeInTheDocument();
    expect(screen.getByText('基本工资')).toBeInTheDocument();
    expect(screen.getByText('津贴补贴')).toBeInTheDocument();
    expect(screen.getByText('保险费用')).toBeInTheDocument();
    expect(screen.getByText('住房公积金')).toBeInTheDocument();
  });

  it('应该计算总薪资', async () => {
    renderComponent();

    // 打开添加模态框
    const addButton = screen.getByText('添加薪资');
    fireEvent.click(addButton);

    await waitFor(() => {
      expect(screen.getByText('添加薪资')).toBeInTheDocument();
    });

    // 填写表单数据
    const basicSalaryInput = screen.getByLabelText('基本工资');
    const allowanceInput = screen.getByLabelText('津贴补贴');
    const insuranceInput = screen.getByLabelText('保险费用');
    const housingFundInput = screen.getByLabelText('住房公积金');

    fireEvent.change(basicSalaryInput, { target: { value: '5000' } });
    fireEvent.change(allowanceInput, { target: { value: '1000' } });
    fireEvent.change(insuranceInput, { target: { value: '500' } });
    fireEvent.change(housingFundInput, { target: { value: '800' } });

    // 检查总薪资计算
    await waitFor(() => {
      expect(screen.getByText('¥4700.00')).toBeInTheDocument();
      expect(screen.getByText('计算公式：基本工资 + 津贴 - 保险 - 公积金')).toBeInTheDocument();
    });
  });

  it('应该打开编辑薪资模态框', async () => {
    renderComponent();

    await waitFor(() => {
      expect(screen.getByText('北京市')).toBeInTheDocument();
    });

    // 点击编辑按钮（第一个薪资记录的编辑按钮）
    const editButtons = screen.getAllByRole('button', { name: /编辑/i });
    fireEvent.click(editButtons[0]);

    // 检查编辑模态框
    await waitFor(() => {
      expect(screen.getByText('编辑薪资')).toBeInTheDocument();
      expect(screen.getByDisplayValue('5000')).toBeInTheDocument(); // 基本工资
    });
  });

  it('应该显示删除确认对话框', async () => {
    renderComponent();

    await waitFor(() => {
      expect(screen.getByText('北京市')).toBeInTheDocument();
    });

    // 点击删除按钮（第一个薪资记录的删除按钮）
    const deleteButtons = screen.getAllByRole('button', { name: /删除/i });
    fireEvent.click(deleteButtons[0]);

    // 检查删除确认对话框
    await waitFor(() => {
      expect(screen.getByText('确认删除')).toBeInTheDocument();
      expect(screen.getByText('确定要删除这条薪资信息吗？此操作不可撤销。')).toBeInTheDocument();
    });
  });

  it('应该处理API错误', async () => {
    // Mock API错误
    const mockClient = salaryClientManager.getInstance().get();
    mockClient.$get.mockRejectedValueOnce(new Error('获取薪资列表失败'));

    renderComponent();

    // 检查错误处理
    await waitFor(() => {
      // 表格应该为空或显示加载状态
      expect(screen.queryByText('北京市')).not.toBeInTheDocument();
    });
  });
});