import React from 'react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { BrowserRouter } from 'react-router';
import { AreaManagement } from '../../src/components/AreaManagement';
import { areaClient } from '../../src/api/areaClient';

// 完整的mock响应对象 - 按照用户UI包规范
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 areaClient - 按照用户UI包规范
vi.mock('../../src/api/areaClient', () => {
  const mockAreaClient = {
    index: {
      $get: vi.fn(() => Promise.resolve({ status: 200, body: null })),
      $post: vi.fn(() => Promise.resolve({ status: 201, body: null })),
    },
    ':id': {
      $put: vi.fn(() => Promise.resolve({ status: 200, body: null })),
      $delete: vi.fn(() => Promise.resolve({ status: 204, body: null })),
    },
  };

  const mockAreaClientManager = {
    get: vi.fn(() => mockAreaClient),
  };

  return {
    areaClientManager: mockAreaClientManager,
    areaClient: mockAreaClient,
  };
});

// Mock sonner toast
vi.mock('sonner', () => ({
  toast: {
    success: vi.fn(),
    error: vi.fn()
  }
}));

// Test wrapper component
const TestWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: {
        retry: false,
      },
    },
  });

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

describe('区域管理集成测试', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('应该渲染区域管理组件并显示标题', async () => {
    // Mock successful API response for province data
    (areaClient.index.$get as any).mockResolvedValueOnce(createMockResponse(200, {
      data: [
        {
          id: 1,
          tenantId: 1,
          name: '北京市',
          code: '110000',
          level: 1,
          parentId: null,
          isDisabled: 0
        }
      ]
    }));

    render(
      <TestWrapper>
        <AreaManagement />
      </TestWrapper>
    );

    // Check if title is rendered
    expect(screen.getByText('省市区树形管理')).toBeInTheDocument();
    expect(screen.getByText('异步加载树形结构，高效管理省市区数据')).toBeInTheDocument();

    // Wait for loading to complete
    await waitFor(() => {
      expect(screen.getByText('北京市')).toBeInTheDocument();
    });
  });

  it('应该在获取数据时显示加载状态', async () => {
    // Mock delayed API response
    (areaClient.index.$get as any).mockImplementationOnce(() =>
      new Promise(resolve => setTimeout(() => resolve(createMockResponse(200, { data: [] })), 100))
    );

    render(
      <TestWrapper>
        <AreaManagement />
      </TestWrapper>
    );

    // Check if loading state is shown
    expect(screen.getByText('加载中...')).toBeInTheDocument();

    // Wait for loading to complete
    await waitFor(() => {
      expect(screen.queryByText('加载中...')).not.toBeInTheDocument();
    });
  });

  it('应该在无数据时显示空状态', async () => {
    // Mock empty API response
    (areaClient.index.$get as any).mockResolvedValueOnce(createMockResponse(200, { data: [] }));

    render(
      <TestWrapper>
        <AreaManagement />
      </TestWrapper>
    );

    // Wait for empty state to appear
    await waitFor(() => {
      expect(screen.getByText('暂无数据')).toBeInTheDocument();
    });
  });

  it('应该在点击新增按钮时打开创建对话框', async () => {
    // Mock successful API response
    (areaClient.index.$get as any).mockResolvedValueOnce(createMockResponse(200, {
      data: [
        {
          id: 1,
          tenantId: 1,
          name: '北京市',
          code: '110000',
          level: 1,
          parentId: null,
          isDisabled: 0
        }
      ]
    }));

    render(
      <TestWrapper>
        <AreaManagement />
      </TestWrapper>
    );

    // Wait for data to load
    await waitFor(() => {
      expect(screen.getByText('北京市')).toBeInTheDocument();
    });

    // Click add button
    const addButton = screen.getByText('新增省');
    fireEvent.click(addButton);

    // Check if dialog opens
    await waitFor(() => {
      expect(screen.getByRole('heading', { name: '新增省' })).toBeInTheDocument();
      expect(screen.getByText('填写省信息')).toBeInTheDocument();
    });
  });

  it('应该优雅地处理API错误', async () => {
    // Mock API error
    (areaClient.index.$get as any).mockRejectedValueOnce(new Error('API Error'));

    render(
      <TestWrapper>
        <AreaManagement />
      </TestWrapper>
    );

    // Wait for error state
    await waitFor(() => {
      // Component should handle errors gracefully
      expect(screen.getByText('省市区树形管理')).toBeInTheDocument();
    });
  });

  it('应该完成创建和删除工作流程', async () => {
    const { toast } = await import('sonner');

    // Mock initial areas data
    const mockAreas = {
      data: [
        {
          id: 1,
          tenantId: 1,
          name: '北京市',
          code: '110000',
          level: 1,
          parentId: null,
          isDisabled: 0
        }
      ]
    };

    // Mock initial data fetch
    (areaClient.index.$get as any).mockResolvedValue(createMockResponse(200, mockAreas));

    render(
      <TestWrapper>
        <AreaManagement />
      </TestWrapper>
    );

    // Wait for initial data to load
    await waitFor(() => {
      expect(screen.getByText('北京市')).toBeInTheDocument();
    });

    // Test create area
    const addButton = screen.getByText('新增省');
    fireEvent.click(addButton);

    // Wait for create dialog
    await waitFor(() => {
      expect(screen.getByRole('heading', { name: '新增省' })).toBeInTheDocument();
    });

    // Fill create form
    const nameInput = screen.getByPlaceholderText('输入区域名称');
    const codeInput = screen.getByPlaceholderText('输入行政区划代码');

    fireEvent.change(nameInput, { target: { value: '上海市' } });
    fireEvent.change(codeInput, { target: { value: '310000' } });

    // Mock successful creation
    (areaClient.index.$post as any).mockResolvedValue(createMockResponse(201, { id: 2, name: '上海市' }));

    const submitButton = screen.getByText('创建');
    fireEvent.click(submitButton);

    await waitFor(() => {
      expect(areaClient.index.$post).toHaveBeenCalledWith({
        json: {
          tenantId: 1,
          name: '上海市',
          code: '310000',
          level: 1,
          parentId: null,
          isDisabled: 0
        }
      });
      expect(toast.success).toHaveBeenCalledWith('省市区创建成功');
    });

    // 跳过编辑操作测试，专注于创建和删除操作

    // Test delete area
    const deleteButtons = screen.getAllByRole('button', { name: '删除' });
    fireEvent.click(deleteButtons[0]);

    // Confirm deletion
    expect(screen.getByRole('heading', { name: '确认删除' })).toBeInTheDocument();

    // Mock successful deletion
    (areaClient[':id']['$delete'] as any).mockResolvedValue({
      status: 204,
    });

    // 查找删除确认按钮
    const confirmDeleteButton = screen.getByRole('button', { name: '确认删除' });
    fireEvent.click(confirmDeleteButton);

    await waitFor(() => {
      expect(areaClient[':id']['$delete']).toHaveBeenCalledWith({
        param: { id: 1 },
      });
      expect(toast.success).toHaveBeenCalledWith('省市区删除成功');
    });
  });

  it('应该处理CRUD操作中的API错误', async () => {
    const { areaClient } = await import('../../src/api/areaClient');
    const { toast } = await import('sonner');

    // Mock initial data
    const mockAreas = {
      data: [
        {
          id: 1,
          tenantId: 1,
          name: '北京市',
          code: '110000',
          level: 1,
          parentId: null,
          isDisabled: 0
        }
      ]
    };

    (areaClient.index.$get as any).mockResolvedValue(createMockResponse(200, mockAreas));

    render(
      <TestWrapper>
        <AreaManagement />
      </TestWrapper>
    );

    // Wait for data to load
    await waitFor(() => {
      expect(screen.getByText('北京市')).toBeInTheDocument();
    });

    // Test create area error
    const addButton = screen.getByText('新增省');
    fireEvent.click(addButton);

    await waitFor(() => {
      expect(screen.getByRole('heading', { name: '新增省' })).toBeInTheDocument();
    });

    const nameInput = screen.getByPlaceholderText('输入区域名称');
    const codeInput = screen.getByPlaceholderText('输入行政区划代码');

    fireEvent.change(nameInput, { target: { value: '上海市' } });
    fireEvent.change(codeInput, { target: { value: '310000' } });

    // Mock creation error
    (areaClient.index.$post as any).mockRejectedValue(new Error('Creation failed'));

    const submitButton = screen.getByText('创建');
    fireEvent.click(submitButton);

    await waitFor(() => {
      expect(toast.error).toHaveBeenCalledWith('创建失败，请重试');
    });
  });

  it('应该支持4级区域层级（省→市→区→乡镇）', async () => {
    // Mock initial data with all levels
    const mockAreas = {
      data: [
        {
          id: 1,
          tenantId: 1,
          name: '北京市',
          code: '110000',
          level: 1,
          parentId: null,
          isDisabled: 0
        },
        {
          id: 2,
          tenantId: 1,
          name: '北京市市辖区',
          code: '110100',
          level: 2,
          parentId: 1,
          isDisabled: 0
        },
        {
          id: 3,
          tenantId: 1,
          name: '朝阳区',
          code: '110105',
          level: 3,
          parentId: 2,
          isDisabled: 0
        },
        {
          id: 4,
          tenantId: 1,
          name: '建国门街道',
          code: '110105001',
          level: 4,
          parentId: 3,
          isDisabled: 0
        }
      ]
    };

    (areaClient.index.$get as any).mockResolvedValue(createMockResponse(200, mockAreas));

    render(
      <TestWrapper>
        <AreaManagement />
      </TestWrapper>
    );

    // Wait for all level data to load
    await waitFor(() => {
      expect(screen.getByText('北京市')).toBeInTheDocument();
      expect(screen.getByText('北京市市辖区')).toBeInTheDocument();
      expect(screen.getByText('朝阳区')).toBeInTheDocument();
      expect(screen.getByText('建国门街道')).toBeInTheDocument();
    });

    // Verify all levels are displayed correctly
    expect(screen.getByText('北京市')).toBeInTheDocument();
    expect(screen.getByText('北京市市辖区')).toBeInTheDocument();
    expect(screen.getByText('朝阳区')).toBeInTheDocument();
    expect(screen.getByText('建国门街道')).toBeInTheDocument();
  });

  it('应该成功创建4级区域（乡镇）', async () => {
    const { toast } = await import('sonner');

    // Mock initial data with district
    const mockAreas = {
      data: [
        {
          id: 3,
          tenantId: 1,
          name: '朝阳区',
          code: '110105',
          level: 3,
          parentId: 2,
          isDisabled: 0
        }
      ]
    };

    (areaClient.index.$get as any).mockResolvedValue(createMockResponse(200, mockAreas));

    render(
      <TestWrapper>
        <AreaManagement />
      </TestWrapper>
    );

    // Wait for data to load
    await waitFor(() => {
      expect(screen.getByText('朝阳区')).toBeInTheDocument();
    });

    // Click add child button for district
    const addChildButtons = screen.getAllByRole('button', { name: '新增乡镇' });
    fireEvent.click(addChildButtons[0]);

    // Check if town creation dialog opens
    await waitFor(() => {
      expect(screen.getByRole('heading', { name: '新增乡镇' })).toBeInTheDocument();
      expect(screen.getByText('在区县 "朝阳区" 下新增街道/乡镇')).toBeInTheDocument();
    });

    // Fill town form
    const nameInput = screen.getByPlaceholderText('输入区域名称');
    const codeInput = screen.getByPlaceholderText('输入行政区划代码');

    fireEvent.change(nameInput, { target: { value: '建国门街道' } });
    fireEvent.change(codeInput, { target: { value: '110105001' } });

    // Mock successful town creation
    (areaClient.index.$post as any).mockResolvedValue(createMockResponse(201, { id: 4, name: '建国门街道' }));

    const submitButton = screen.getByText('创建');
    fireEvent.click(submitButton);

    await waitFor(() => {
      expect(areaClient.index.$post).toHaveBeenCalledWith({
        json: {
          tenantId: 1,
          name: '建国门街道',
          code: '110105001',
          level: 4,
          parentId: 3,
          isDisabled: 0
        }
      });
      expect(toast.success).toHaveBeenCalledWith('省市区创建成功');
    });
  });

  it('应该处理4级区域状态切换', async () => {
    const { toast } = await import('sonner');

    // Mock initial data with town
    const mockAreas = {
      data: [
        {
          id: 4,
          tenantId: 1,
          name: '建国门街道',
          code: '110105001',
          level: 4,
          parentId: 3,
          isDisabled: 0
        }
      ]
    };

    (areaClient.index.$get as any).mockResolvedValue(createMockResponse(200, mockAreas));

    render(
      <TestWrapper>
        <AreaManagement />
      </TestWrapper>
    );

    // Wait for data to load
    await waitFor(() => {
      expect(screen.getByText('建国门街道')).toBeInTheDocument();
    });

    // Click toggle status button for town
    const toggleButtons = screen.getAllByRole('button', { name: '禁用' });
    fireEvent.click(toggleButtons[0]);

    // Check if status toggle dialog opens
    await waitFor(() => {
      expect(screen.getByRole('heading', { name: '禁用确认' })).toBeInTheDocument();
      expect(screen.getByText('确定要禁用省市区 "建国门街道" 吗？')).toBeInTheDocument();
    });

    // Mock successful status toggle
    (areaClient[':id'].$put as any).mockResolvedValue(createMockResponse(200));

    const confirmButton = screen.getByRole('button', { name: '确认' });
    fireEvent.click(confirmButton);

    await waitFor(() => {
      expect(areaClient[':id'].$put).toHaveBeenCalledWith({
        param: { id: 4 },
        json: { isDisabled: 1 }
      });
      expect(toast.success).toHaveBeenCalledWith('省市区禁用成功');
    });
  });

  it('应该成功删除4级区域（乡镇）', async () => {
    const { toast } = await import('sonner');

    // Mock initial data with town
    const mockAreas = {
      data: [
        {
          id: 4,
          tenantId: 1,
          name: '建国门街道',
          code: '110105001',
          level: 4,
          parentId: 3,
          isDisabled: 0
        }
      ]
    };

    (areaClient.index.$get as any).mockResolvedValue(createMockResponse(200, mockAreas));

    render(
      <TestWrapper>
        <AreaManagement />
      </TestWrapper>
    );

    // Wait for data to load
    await waitFor(() => {
      expect(screen.getByText('建国门街道')).toBeInTheDocument();
    });

    // Click delete button for town
    const deleteButtons = screen.getAllByRole('button', { name: '删除' });
    fireEvent.click(deleteButtons[0]);

    // Check if delete confirmation dialog opens
    await waitFor(() => {
      expect(screen.getByRole('heading', { name: '确认删除' })).toBeInTheDocument();
      expect(screen.getByText('确定要删除省市区 "建国门街道" 吗？此操作不可恢复。')).toBeInTheDocument();
    });

    // Mock successful deletion
    (areaClient[':id'].$delete as any).mockResolvedValue(createMockResponse(204));

    const confirmDeleteButton = screen.getByRole('button', { name: '确认删除' });
    fireEvent.click(confirmDeleteButton);

    await waitFor(() => {
      expect(areaClient[':id'].$delete).toHaveBeenCalledWith({
        param: { id: 4 }
      });
      expect(toast.success).toHaveBeenCalledWith('省市区删除成功');
    });
  });
});