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 { MerchantManagement } from '../../src/components/MerchantManagement';
import { merchantClientManager } from '../../src/api/merchantClient';

// 完整的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/merchantClient', () => {
  const mockMerchantClient = {
    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 mockMerchantClientManager = {
    get: vi.fn(() => mockMerchantClient),
  };

  return {
    merchantClientManager: mockMerchantClientManager,
    merchantClient: mockMerchantClient,
  };
});

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

const createTestQueryClient = () =>
  new QueryClient({
    defaultOptions: {
      queries: {
        retry: false,
      },
    },
  });

const renderWithProviders = (component: React.ReactElement) => {
  const queryClient = createTestQueryClient();
  return render(
    <QueryClientProvider client={queryClient}>
      {component as any}
    </QueryClientProvider>
  );
};

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

  it('应该完成完整的商户CRUD流程', async () => {
    const mockMerchants = {
      data: [
        {
          id: 1,
          name: '测试商户',
          username: 'testmerchant',
          realname: '张三',
          phone: '13800138000',
          state: 1,
          loginNum: 5,
          createdAt: '2024-01-01T00:00:00Z',
          updatedAt: '2024-01-01T00:00:00Z',
          lastLoginTime: 1704067200,
          lastLoginIp: '192.168.1.1',
          rsaPublicKey: '',
          aesKey: '',
        },
      ],
      pagination: {
        total: 1,
        page: 1,
        pageSize: 10,
      },
    };

    const { toast } = await import('sonner');

    // Mock initial merchant list
    (merchantClientManager.get().index.$get as any).mockResolvedValue(createMockResponse(200, mockMerchants));

    renderWithProviders(<MerchantManagement />);

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

    // Test create merchant
    const createButton = screen.getByTestId('create-merchant-button');
    fireEvent.click(createButton);

    // Fill create form
    const nameInput = screen.getByPlaceholderText('请输入商户名称');
    const usernameInput = screen.getByPlaceholderText('请输入用户名');
    const passwordInput = screen.getByPlaceholderText('请输入密码');
    const phoneInput = screen.getByPlaceholderText('请输入手机号');

    fireEvent.change(nameInput, { target: { value: '新商户' } });
    fireEvent.change(usernameInput, { target: { value: 'newmerchant' } });
    fireEvent.change(passwordInput, { target: { value: 'password123' } });
    fireEvent.change(phoneInput, { target: { value: '13800138000' } });

    // Mock successful creation
    (merchantClientManager.get().index.$post as any).mockResolvedValue(createMockResponse(201, { id: 2, username: 'newmerchant' }));

    const submitButton = screen.getByTestId('create-submit-button');
    fireEvent.click(submitButton);

    await waitFor(() => {
      expect(merchantClientManager.get().index.$post).toHaveBeenCalledWith({
        json: {
          name: '新商户',
          username: 'newmerchant',
          password: 'password123',
          phone: '13800138000',
          realname: '',
          state: 2,
          rsaPublicKey: '',
          aesKey: '',
        },
      });
      expect(toast.success).toHaveBeenCalledWith('商户创建成功');
    });

    // Test edit merchant
    const editButtons = screen.getAllByTestId('edit-button-1');
    fireEvent.click(editButtons[0]);

    // Verify edit form is populated
    await waitFor(() => {
      expect(screen.getByDisplayValue('测试商户')).toBeInTheDocument();
    });

    // Update merchant
    const updateNameInput = screen.getByDisplayValue('测试商户');
    fireEvent.change(updateNameInput, { target: { value: '更新商户' } });

    // Mock successful update
    (merchantClientManager.get()[':id']['$put'] as any).mockResolvedValue(createMockResponse(200));

    const updateButton = screen.getByTestId('update-submit-button');
    fireEvent.click(updateButton);

    await waitFor(() => {
      expect(merchantClientManager.get()[':id']['$put']).toHaveBeenCalledWith({
        param: { id: 1 },
        json: {
          name: '更新商户',
          username: 'testmerchant',
          phone: '13800138000',
          realname: '张三',
          password: undefined,
          state: 1,
          rsaPublicKey: '',
          aesKey: '',
        },
      });
      expect(toast.success).toHaveBeenCalledWith('商户更新成功');
    });

    // Test delete merchant
    const deleteButtons = screen.getAllByTestId('delete-button-1');
    fireEvent.click(deleteButtons[0]);

    // Confirm deletion
    expect(screen.getByText('确认删除')).toBeInTheDocument();

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

    const confirmDeleteButton = screen.getByText('删除');
    fireEvent.click(confirmDeleteButton);

    await waitFor(() => {
      expect(merchantClientManager.get()[':id']['$delete']).toHaveBeenCalledWith({
        param: { id: 1 },
      });
      expect(toast.success).toHaveBeenCalledWith('商户删除成功');
    });
  });

  it('应该优雅处理API错误', async () => {
    const { toast } = await import('sonner');

    // Mock API error
    (merchantClientManager.get().index.$get as any).mockRejectedValue(new Error('API Error'));

    renderWithProviders(<MerchantManagement />);

    // Should handle error without crashing
    await waitFor(() => {
      expect(screen.getByText('商户管理')).toBeInTheDocument();
    });

    // Test create merchant error
    const createButton = screen.getByTestId('create-merchant-button');
    fireEvent.click(createButton);

    // 等待对话框打开
    await waitFor(() => {
      expect(screen.getByRole('dialog')).toBeInTheDocument();
    });

    // 填写必填字段
    const nameInput = screen.getByPlaceholderText('请输入商户名称');
    const usernameInput = screen.getByPlaceholderText('请输入用户名');
    const passwordInput = screen.getByPlaceholderText('请输入密码');
    const phoneInput = screen.getByPlaceholderText('请输入手机号');

    fireEvent.change(nameInput, { target: { value: '测试商户' } });
    fireEvent.change(usernameInput, { target: { value: 'testmerchant' } });
    fireEvent.change(passwordInput, { target: { value: 'password123' } });
    fireEvent.change(phoneInput, { target: { value: '13800138000' } });

    // Mock creation error
    (merchantClientManager.get().index.$post as any).mockRejectedValue(new Error('创建商户失败'));

    const submitButton = screen.getByTestId('create-submit-button');
    fireEvent.click(submitButton);

    await waitFor(() => {
      expect(toast.error).toHaveBeenCalledWith('创建商户失败');
    });
  });

  it('应该处理搜索功能', async () => {
    const mockMerchants = {
      data: [],
      pagination: { total: 0, page: 1, pageSize: 10 },
    };

    (merchantClientManager.get().index.$get as any).mockResolvedValue(createMockResponse(200, mockMerchants));

    renderWithProviders(<MerchantManagement />);

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

    // Test search
    const searchInput = screen.getByPlaceholderText('搜索商户名称、用户名、手机号...');
    fireEvent.change(searchInput, { target: { value: '搜索关键词' } });

    const searchButton = screen.getByTestId('search-button');
    fireEvent.click(searchButton);

    await waitFor(() => {
      expect(merchantClientManager.get().index.$get).toHaveBeenCalledWith({
        query: {
          page: 1,
          pageSize: 10,
          keyword: '搜索关键词',
        },
      });
    });
  });

  it('应该显示商户详情', async () => {
    const mockMerchants = {
      data: [
        {
          id: 1,
          name: '测试商户',
          username: 'testmerchant',
          realname: '张三',
          phone: '13800138000',
          state: 1,
          loginNum: 5,
          createdAt: '2024-01-01T00:00:00Z',
          updatedAt: '2024-01-01T00:00:00Z',
          lastLoginTime: 1704067200,
          lastLoginIp: '192.168.1.1',
          rsaPublicKey: '',
          aesKey: '',
        },
      ],
      pagination: {
        total: 1,
        page: 1,
        pageSize: 10,
      },
    };

    (merchantClientManager.get().index.$get as any).mockResolvedValue(createMockResponse(200, mockMerchants));

    renderWithProviders(<MerchantManagement />);

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

    // Test view details
    const viewButtons = screen.getAllByTestId('view-detail-button-1');
    fireEvent.click(viewButtons[0]);

    // Verify detail dialog appears
    await waitFor(() => {
      expect(screen.getByText('商户详情')).toBeInTheDocument();
    });

    // 验证详情内容 - 只验证对话框标题
    expect(screen.getByText('商户详情')).toBeInTheDocument();
  });

  it('应该正确处理分页', async () => {
    const mockMerchantsPage1 = {
      data: [
        { id: '1', name: '商户1', username: 'merchant1', phone: '13800000001', status: 'active', createdAt: '2024-01-01T00:00:00Z' },
        { id: '2', name: '商户2', username: 'merchant2', phone: '13800000002', status: 'active', createdAt: '2024-01-01T00:00:00Z' }
      ],
      pagination: { total: 25, page: 1, pageSize: 10 },
    };

    const mockMerchantsPage2 = {
      data: [
        { id: '3', name: '商户3', username: 'merchant3', phone: '13800000003', status: 'active', createdAt: '2024-01-01T00:00:00Z' },
        { id: '4', name: '商户4', username: 'merchant4', phone: '13800000004', status: 'active', createdAt: '2024-01-01T00:00:00Z' }
      ],
      pagination: { total: 25, page: 2, pageSize: 10 },
    };

    // 设置 mock 响应 - 先只用一个响应
    (merchantClientManager.get().index.$get as any)
      .mockResolvedValue(createMockResponse(200, mockMerchantsPage1));

    renderWithProviders(<MerchantManagement />);

    // Wait for data to load
    await waitFor(() => {
      expect(screen.getByText('商户列表')).toBeInTheDocument();
    });

    // Debug: Check if merchants are displayed
    const merchantNames = screen.queryAllByText(/商户[0-9]/);
    console.log('Merchant names found:', merchantNames.length);
    console.log('Merchant names:', merchantNames.map(el => el.textContent));

    // Debug: Check what pagination elements are rendered
    const allLinks = screen.getAllByRole('link');
    console.log('All links:', allLinks.map(link => ({
      text: link.textContent,
      ariaLabel: link.getAttribute('aria-label'),
      ariaDisabled: link.getAttribute('aria-disabled')
    })));

    // Debug: Check if pagination info is displayed
    const paginationInfo = screen.queryByText(/共.*条记录/);
    console.log('Pagination info:', paginationInfo?.textContent);

    // Test pagination - click next page
    const nextPageButton = screen.getByLabelText(/next/i);
    fireEvent.click(nextPageButton);

    // 等待分页请求完成 - 增加等待时间
    await waitFor(() => {
      expect(merchantClientManager.get().index.$get).toHaveBeenCalledTimes(2);
    }, { timeout: 5000 });

    // 验证第二次调用的参数
    const calls = (merchantClientManager.get().index.$get as any).mock.calls;
    expect(calls[1][0]).toEqual({
      query: {
        page: 2,
        pageSize: 10,
        keyword: '',
      },
    });
  });
});