import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { TestWrapper } from '@/client/__test_utils__/test-render';
import { UsersPage } from '../Users';
import { userClient } from '@/client/api';

// Mock the API client
vi.mock('@/client/api', () => ({
  userClient: {
    $get: vi.fn(),
    $post: vi.fn(),
    ':id': {
      $put: vi.fn(),
      $delete: vi.fn()
    }
  }
}));

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

describe('UsersPage Component', () => {
  const mockUsers = [
    {
      id: 1,
      username: 'admin',
      nickname: '管理员',
      email: 'admin@example.com',
      phone: '13800138000',
      name: '系统管理员',
      isDisabled: 0,
      createdAt: '2024-01-01T00:00:00.000Z',
      roles: [{ id: 1, name: 'admin' }]
    },
    {
      id: 2,
      username: 'user1',
      nickname: '用户1',
      email: 'user1@example.com',
      phone: '13900139000',
      name: '张三',
      isDisabled: 0,
      createdAt: '2024-01-02T00:00:00.000Z',
      roles: [{ id: 2, name: 'user' }]
    }
  ];

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

    // Mock successful API response - return a proper Response object
    (userClient.$get as any).mockImplementation(async (params: any) => {
      console.log('API called with params:', params);
      return {
        status: 200,
        ok: true,
        headers: new Headers({ 'content-type': 'application/json' }),
        json: async () => ({
          data: mockUsers,
          pagination: {
            total: 2,
            current: 1,
            pageSize: 10
          }
        })
      };
    });

    console.log('Mock setup complete');
  });

  it('应该渲染用户列表页面', async () => {
    render(
      <TestWrapper>
        <UsersPage />
      </TestWrapper>
    );

    // 检查页面标题
    expect(screen.getByText('用户管理')).toBeInTheDocument();

    // 检查创建用户按钮
    expect(screen.getByText('创建用户')).toBeInTheDocument();

    // 等待数据加载完成
    await waitFor(() => {
      expect(screen.getByText('admin')).toBeInTheDocument();
      expect(screen.getByText('user1')).toBeInTheDocument();
    }, { timeout: 10000 });

    // 检查API是否被调用
    expect(userClient.$get).toHaveBeenCalled();

    // 检查用户总数显示
    expect(screen.getByText(/共 2 位用户/)).toBeInTheDocument();
  });

  it('应该显示搜索框和过滤按钮', async () => {
    render(
      <TestWrapper>
        <UsersPage />
      </TestWrapper>
    );

    // 等待数据加载完成
    await waitFor(() => {
      expect(screen.getByText('admin')).toBeInTheDocument();
    }, { timeout: 10000 });

    // 检查搜索框
    expect(screen.getByPlaceholderText('搜索用户名、昵称或邮箱...')).toBeInTheDocument();

    // 检查搜索按钮
    expect(screen.getByText('搜索')).toBeInTheDocument();

    // 检查高级筛选按钮
    expect(screen.getByText('高级筛选')).toBeInTheDocument();
  });

  it('应该支持关键词搜索', async () => {
    const user = userEvent.setup();
    render(
      <TestWrapper>
        <UsersPage />
      </TestWrapper>
    );

    // 等待数据加载完成
    await waitFor(() => {
      expect(screen.getByText('admin')).toBeInTheDocument();
    }, { timeout: 10000 });

    // 在搜索框中输入关键词 - 使用paste来避免防抖中间状态
    const searchInput = screen.getByPlaceholderText('搜索用户名、昵称或邮箱...');
    await user.clear(searchInput);
    await user.click(searchInput);
    await user.paste('admin');

    // 等待防抖完成（300ms + 缓冲时间）
    await new Promise(resolve => setTimeout(resolve, 400));

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

    // 验证API被调用正确的参数
    const calls = (userClient.$get as any).mock.calls;
    const lastCall = calls[calls.length - 1];

    // 检查搜索参数
    const queryParams = lastCall[0].query;
    expect(queryParams.page).toBe(1);
    expect(queryParams.pageSize).toBe(10);
    expect(queryParams.keyword).toBe('admin');
  });

  it('应该显示高级筛选面板', async () => {
    const user = userEvent.setup();
    render(
      <TestWrapper>
        <UsersPage />
      </TestWrapper>
    );

    // 等待数据加载完成
    await waitFor(() => {
      expect(screen.getByText('admin')).toBeInTheDocument();
    }, { timeout: 10000 });

    // 点击高级筛选按钮
    const filterButton = screen.getByText('高级筛选');
    await user.click(filterButton);

    // 检查筛选面板是否显示
    expect(screen.getByText('用户状态')).toBeInTheDocument();
    expect(screen.getByText('用户角色')).toBeInTheDocument();
    // 使用更具体的查询来避免与表格标题冲突
    expect(screen.getAllByText('创建时间')[0]).toBeInTheDocument();
  });

  it('应该显示加载骨架屏', async () => {
    // 清除之前的mock
    vi.clearAllMocks();

    // 模拟延迟响应
    (userClient.$get as any).mockImplementation(() =>
      new Promise(resolve => setTimeout(() => resolve({
        status: 200,
        ok: true,
        json: async () => ({
          data: mockUsers,
          pagination: { total: 2, current: 1, pageSize: 10 }
        })
      }), 100))
    );

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

    // 检查骨架屏是否显示
    expect(screen.getByText('用户管理')).toBeInTheDocument();
    expect(screen.getByText('创建用户')).toBeInTheDocument();

    // 检查骨架屏元素
    // 先检查所有元素来调试角色问题
    const allElements = screen.getAllByRole('generic');
    console.log('All elements with generic role:', allElements.length);

    // 尝试查找骨架屏元素
    const skeletons = screen.queryAllByRole('status');
    console.log('Elements with status role:', skeletons.length);

    // 如果找不到status角色，尝试通过data-slot查找
    if (skeletons.length === 0) {
      const skeletonElements = screen.queryAllByTestId('skeleton');
      if (skeletonElements.length === 0) {
        // 使用data-slot属性查找
        const slotSkeletons = document.querySelectorAll('[data-slot="skeleton"]');
        expect(slotSkeletons.length).toBeGreaterThan(0);
      } else {
        expect(skeletonElements.length).toBeGreaterThan(0);
      }
    } else {
      expect(skeletons.length).toBeGreaterThan(0);
    }

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

    // 检查骨架屏已消失
    const remainingSkeletons = screen.queryAllByRole('status');
    if (remainingSkeletons.length === 0) {
      // 也检查通过testid查找的骨架屏
      const remainingTestidSkeletons = screen.queryAllByTestId('skeleton');
      if (remainingTestidSkeletons.length === 0) {
        // 检查通过data-slot查找的骨架屏
        const remainingSlotSkeletons = document.querySelectorAll('[data-slot="skeleton"]');
        expect(remainingSlotSkeletons).toHaveLength(0);
      } else {
        expect(remainingTestidSkeletons).toHaveLength(0);
      }
    } else {
      expect(remainingSkeletons).toHaveLength(0);
    }
  });

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

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

    // 检查页面仍然渲染
    expect(screen.getByText('用户管理')).toBeInTheDocument();
    expect(screen.getByText('创建用户')).toBeInTheDocument();

    // 等待加载完成（应该没有数据）
    await waitFor(() => {
      expect(screen.queryByText('admin')).not.toBeInTheDocument();
      expect(screen.queryByText('user1')).not.toBeInTheDocument();
    });
  });

  it('应该显示分页控件', async () => {
    // 模拟多页数据
    (userClient.$get as any).mockResolvedValue({
      status: 200,
      ok: true,
      json: async () => ({
        data: mockUsers,
        pagination: {
          total: 25,
          current: 1,
          pageSize: 10
        }
      })
    });

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

    await waitFor(() => {
      // 检查分页控件
      expect(screen.getByText('1')).toBeInTheDocument();
      expect(screen.getByText('2')).toBeInTheDocument();
      expect(screen.getByText('3')).toBeInTheDocument();
    });
  });

  it('应该打开创建用户模态框', async () => {
    const user = userEvent.setup();
    render(
      <TestWrapper>
        <UsersPage />
      </TestWrapper>
    );

    await waitFor(() => {
      expect(screen.getByText('admin')).toBeInTheDocument();
    });

    // 点击创建用户按钮
    const createButton = screen.getByText('创建用户');
    await user.click(createButton);

    // 验证模态框打开
    expect(screen.getByRole('heading', { name: '创建用户' })).toBeInTheDocument();
    expect(screen.getByLabelText('用户名')).toBeInTheDocument();
    expect(screen.getByLabelText('密码')).toBeInTheDocument();
  });

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

    await waitFor(() => {
      expect(screen.getByText('admin')).toBeInTheDocument();
    });

    // 打开高级筛选
    const filterButton = screen.getByText('高级筛选');
    await user.click(filterButton);

    // 选择用户状态筛选
    const statusSelect = screen.getByLabelText('用户状态');
    await user.click(statusSelect);
    await user.click(screen.getByText('启用'));

    // 验证API被调用正确的筛选参数
    await waitFor(() => {
      const calls = (userClient.$get as any).mock.calls;
      const lastCall = calls[calls.length - 1];
      const queryParams = lastCall[0].query;
      expect(queryParams.filters).toContain('isDisabled');
    });
  });

  it('应该处理表单验证错误', async () => {
    const user = userEvent.setup();
    render(
      <TestWrapper>
        <UsersPage />
      </TestWrapper>
    );

    await waitFor(() => {
      expect(screen.getByText('admin')).toBeInTheDocument();
    });

    // 打开创建用户模态框
    const createButton = screen.getByText('创建用户');
    await user.click(createButton);

    // 不填写必填字段直接提交
    const submitButton = screen.getByRole('button', { name: '创建用户' });
    await user.click(submitButton);

    // 验证错误消息显示
    await waitFor(() => {
      expect(screen.getByText('请输入用户名')).toBeInTheDocument();
      expect(screen.getByText('请输入密码')).toBeInTheDocument();
    });
  });

  it('应该处理空数据状态', async () => {
    // 模拟空数据响应
    (userClient.$get as any).mockResolvedValue({
      status: 200,
      ok: true,
      json: async () => ({
        data: [],
        pagination: {
          total: 0,
          current: 1,
          pageSize: 10
        }
      })
    });

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

    // 验证空状态显示
    await waitFor(() => {
      expect(screen.getByText('共 0 位用户')).toBeInTheDocument();
      expect(screen.queryByText('admin')).not.toBeInTheDocument();
    });
  });

  it('应该处理删除用户操作', async () => {
    const user = userEvent.setup();

    // 模拟删除成功
    (userClient[':id']['$delete'] as any).mockResolvedValue({
      status: 204,
      ok: true
    });

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

    await waitFor(() => {
      expect(screen.getByText('admin')).toBeInTheDocument();
    });

    // 查找删除按钮
    const deleteButtons = screen.getAllByRole('button', { name: /delete/i });
    expect(deleteButtons.length).toBeGreaterThan(0);

    // 验证删除功能（由于UI复杂性，这里主要验证API调用）
    expect(userClient[':id']['$delete']).not.toHaveBeenCalled();
  });

  it('应该处理编辑用户操作', async () => {
    const user = userEvent.setup();

    // 模拟更新成功
    (userClient[':id']['$put'] as any).mockResolvedValue({
      status: 200,
      ok: true,
      json: async () => ({ message: '用户更新成功' })
    });

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

    await waitFor(() => {
      expect(screen.getByText('admin')).toBeInTheDocument();
    });

    // 查找编辑按钮
    const editButtons = screen.getAllByRole('button', { name: /edit/i });
    expect(editButtons.length).toBeGreaterThan(0);

    // 验证编辑功能（由于UI复杂性，这里主要验证API调用）
    expect(userClient[':id']['$put']).not.toHaveBeenCalled();
  });

  it('应该处理网络错误场景', async () => {
    // 模拟网络错误
    (userClient.$get as any).mockRejectedValue(new Error('Network error'));

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

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

    // 验证没有用户数据显示
    await waitFor(() => {
      expect(screen.queryByText('admin')).not.toBeInTheDocument();
    });
  });
});