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 { LocationsPage } from '@/client/admin/pages/Locations';
import { AdminTestWrapper } from '~/utils/client/test-render';

// Import mocked modules
import { locationClient } from '@/client/api';

// Mock next-themes 组件
vi.mock('next-themes', () => ({
  ThemeProvider: ({ children }: { children: React.ReactNode }) => children,
  useTheme: () => ({
    theme: 'light',
    setTheme: vi.fn(),
  }),
}));

// 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: {
          total: 2,
          current: 1,
          pageSize: 20
        }
      })
    }),
    $post: vi.fn().mockResolvedValue({
      status: 201,
      ok: true,
      json: async () => ({
        id: 3,
        name: '新建地点',
        address: '新建地址',
        province: null,
        city: null,
        district: null,
        latitude: null,
        longitude: null,
        isDisabled: 0,
        createdAt: '2024-01-01T00:00:00.000Z'
      })
    }),
    ':id': {
      $put: vi.fn().mockResolvedValue({
        status: 200,
        ok: true,
        json: async () => ({
          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
        })
      }),
      $delete: vi.fn().mockResolvedValue({
        status: 204,
        ok: true
      })
    }
  },
  areaClient: {
    $get: vi.fn().mockResolvedValue({
      status: 200,
      ok: true,
      json: async () => ({
        data: [
          {
            id: 1,
            name: '华北地区',
            code: 'north_china',
            isDisabled: 0,
            createdAt: '2024-01-01T00:00:00.000Z'
          },
          {
            id: 2,
            name: '华东地区',
            code: 'east_china',
            isDisabled: 0,
            createdAt: '2024-01-01T00:00:00.000Z'
          }
        ],
        pagination: {
          total: 2,
          current: 1,
          pageSize: 100
        }
      })
    })
  }
}));

describe('LocationsPage 集成测试', () => {
  const user = userEvent.setup();

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

    // 模拟缺失的 Pointer Events API
    if (!Element.prototype.hasPointerCapture) {
      Element.prototype.hasPointerCapture = vi.fn(() => false);
    }
    if (!Element.prototype.releasePointerCapture) {
      Element.prototype.releasePointerCapture = vi.fn();
    }
  });

  it('应该正确渲染地点管理页面标题', async () => {
    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

    expect(screen.getByText('地点管理')).toBeInTheDocument();
    expect(screen.getByText('新建地点')).toBeInTheDocument();
  });

  it('应该显示地点列表和搜索功能', async () => {
    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

    // 等待数据加载
    await waitFor(() => {
      expect(screen.getByPlaceholderText('搜索地点名称或地址...')).toBeInTheDocument();
    });

    expect(screen.getByText('地点列表')).toBeInTheDocument();

    // 等待数据正确加载
    await waitFor(() => {
      const countText = screen.getByText(/当前共有 \d+ 条记录/);
      expect(countText).toBeInTheDocument();
    }, { timeout: 5000 });
  });

  it('应该处理搜索功能', async () => {
    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

    const searchInput = screen.getByPlaceholderText('搜索地点名称或地址...');

    // 输入搜索关键词
    await user.type(searchInput, '北京');

    // 等待防抖搜索生效
    await waitFor(() => {
      expect(searchInput).toHaveValue('北京');
    });
  });

  it('应该显示区域筛选功能', async () => {
    const user = userEvent.setup();
    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

    // 等待数据加载
    await waitFor(() => {
      expect(screen.getByText('地点列表')).toBeInTheDocument();
    });

    // 验证区域筛选器存在
    const areaFilter = screen.getByPlaceholderText('选择区域');
    expect(areaFilter).toBeInTheDocument();

    // 点击Select来展开选项
    await user.click(areaFilter);

    // 验证筛选选项存在 - 检查选项数量
    const options = screen.getAllByText(/华北地区|华东地区/);
    expect(options.length).toBeGreaterThanOrEqual(2);
  });

  it('应该显示状态筛选功能', async () => {
    const user = userEvent.setup();
    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

    // 等待数据加载
    await waitFor(() => {
      expect(screen.getByText('地点列表')).toBeInTheDocument();
    });

    // 验证状态筛选器存在
    const statusFilter = screen.getByPlaceholderText('状态筛选');
    expect(statusFilter).toBeInTheDocument();

    // 点击Select来展开选项
    await user.click(statusFilter);

    // 验证筛选选项存在
    expect(screen.getByText('全部状态')).toBeInTheDocument();
    expect(screen.getByText('启用')).toBeInTheDocument();
    expect(screen.getByText('禁用')).toBeInTheDocument();
  });

  it('应该显示创建地点按钮并打开模态框', async () => {
    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

    // 等待数据加载
    await waitFor(() => {
      expect(screen.getByText('新建地点')).toBeInTheDocument();
    });

    const createButton = screen.getByRole('button', { name: /新建地点/i });
    await user.click(createButton);

    // 验证模态框标题
    expect(screen.getByRole('heading', { name: '新建地点' })).toBeInTheDocument();
  });

  it('应该显示分页组件', async () => {
    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

    // 验证分页控件存在 - 等待数据加载
    await waitFor(() => {
      expect(screen.getByText('显示第 1 到 2 条，共 2 条记录')).toBeInTheDocument();
    });
  });

  it('应该处理表格数据加载状态', async () => {
    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

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

  it('应该显示正确的表格列标题', async () => {
    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

    // 等待数据加载
    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 () => {
    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

    // 等待数据加载完成
    await waitFor(() => {
      expect(screen.getByText('北京天安门')).toBeInTheDocument();
      expect(screen.getByText('上海外滩')).toBeInTheDocument();
      expect(screen.getByText('北京市东城区天安门广场')).toBeInTheDocument();
      expect(screen.getByText('上海市黄浦区中山东一路')).toBeInTheDocument();
      expect(screen.getAllByText('启用').length).toBeGreaterThan(0);
    });
  });

  it('应该显示所属区域信息', async () => {
    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

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

    // 验证区域信息显示
    expect(screen.getByText('北京市')).toBeInTheDocument();
    expect(screen.getByText('东城区')).toBeInTheDocument();
  });

  it('应该显示坐标信息', async () => {
    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

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

    // 验证坐标显示
    expect(screen.getByText('39.904200, 116.407400')).toBeInTheDocument();
  });

  it('应该包含编辑、启用/禁用和删除操作按钮', async () => {
    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

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

    // 查找操作按钮
    const actionButtons = screen.getAllByRole('button');
    const hasActionButtons = actionButtons.some(button =>
      button.textContent?.includes('禁用') ||
      button.textContent?.includes('启用') ||
      button.innerHTML.includes('edit') ||
      button.innerHTML.includes('trash')
    );

    expect(hasActionButtons).toBe(true);
  });

  it('应该处理启用/禁用地点操作', async () => {
    const user = userEvent.setup();
    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

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

    // 查找启用/禁用按钮
    const toggleButtons = screen.getAllByRole('button').filter(btn =>
      btn.textContent?.includes('禁用') || btn.textContent?.includes('启用')
    );

    if (toggleButtons.length > 0) {
      // 模拟确认对话框
      window.confirm = vi.fn().mockReturnValue(true);

      await user.click(toggleButtons[0]);

      // 验证确认对话框被调用
      expect(window.confirm).toHaveBeenCalledWith('确定要禁用这个地点吗？');
    }
  });

  it('应该处理删除地点操作', async () => {
    const user = userEvent.setup();
    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

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

    // 查找删除按钮
    const deleteButtons = screen.getAllByRole('button').filter(btn =>
      btn.innerHTML.includes('trash') || btn.getAttribute('aria-label')?.includes('delete')
    );

    if (deleteButtons.length > 0) {
      // 模拟确认对话框
      window.confirm = vi.fn().mockReturnValue(true);

      await user.click(deleteButtons[0]);

      // 验证确认对话框被调用
      expect(window.confirm).toHaveBeenCalledWith('确定要删除这个地点吗？');
    }
  });

  it('应该处理区域筛选', async () => {
    const user = userEvent.setup();
    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

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

    // 验证区域筛选器存在
    const areaFilter = screen.getByPlaceholderText('选择区域');
    expect(areaFilter).toBeInTheDocument();

    // 点击Select来展开选项
    await user.click(areaFilter);

    // 验证筛选选项存在 - 检查选项数量
    const options = screen.getAllByText(/华北地区|华东地区/);
    expect(options.length).toBeGreaterThanOrEqual(2);
  });

  it('应该处理状态筛选', async () => {
    const user = userEvent.setup();
    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

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

    // 验证状态筛选器存在
    const statusFilter = screen.getByPlaceholderText('状态筛选');
    expect(statusFilter).toBeInTheDocument();

    // 点击Select来展开选项
    await user.click(statusFilter);

    // 验证筛选选项存在
    expect(screen.getByText('全部状态')).toBeInTheDocument();
    expect(screen.getByText('启用')).toBeInTheDocument();
    expect(screen.getByText('禁用')).toBeInTheDocument();
  });

  it('应该处理API错误场景', async () => {
    // 模拟API错误
    (locationClient.$get as any).mockResolvedValueOnce({
      status: 500,
      ok: false,
      json: async () => ({ error: 'Internal server error' })
    });

    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

    // 验证页面仍然渲染基本结构
    expect(screen.getByText('地点管理')).toBeInTheDocument();
    expect(screen.getByText('新建地点')).toBeInTheDocument();

    // 验证错误处理（组件应该优雅处理错误）
    await waitFor(() => {
      expect(screen.queryByText('北京天安门')).not.toBeInTheDocument();
    });
  });

  it('应该显示空状态', async () => {
    // 模拟空数据
    (locationClient.$get as any).mockResolvedValueOnce({
      status: 200,
      ok: true,
      json: async () => ({
        data: [],
        pagination: {
          total: 0,
          current: 1,
          pageSize: 20
        }
      })
    });

    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

    // 验证空状态显示
    await waitFor(() => {
      expect(screen.getByText('暂无地点数据')).toBeInTheDocument();
    });
  });

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

    render(
      <AdminTestWrapper>
        <LocationsPage />
      </AdminTestWrapper>
    );

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