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 { OrderManagement } from '../../src/components/OrderManagement';
import { adminOrderClient } from '../../src/api/orderClient';

// 完整的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/orderClient', () => {
  const mockAdminOrderClient = {
    $get: vi.fn(() => Promise.resolve({ status: 200, body: null })),
    ':id': {
      $put: vi.fn(() => Promise.resolve({ status: 200, body: null })),
    },
  };

  const mockOrderClientManager = {
    getAdminOrderClient: vi.fn(() => mockAdminOrderClient),
  };

  return {
    orderClientManager: mockOrderClientManager,
    adminOrderClient: mockAdminOrderClient,
  };
});

// 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('应该加载订单列表并显示数据', async () => {
    const mockOrders = {
      data: [
        {
          id: 1,
          orderNo: 'ORDER001',
          user: { username: 'testuser' },
          userPhone: '13800138000',
          recevierName: '张三',
          receiverMobile: '13800138001',
          amount: 100.00,
          payAmount: 100.00,
          freightAmount: 0.00,
          state: 0,
          payState: 2,
          orderType: 1,
          payType: 1,
          address: '北京市朝阳区',
          remark: '测试订单',
          createdAt: '2024-01-01T00:00:00Z',
        },
      ],
      pagination: {
        total: 1,
        page: 1,
        pageSize: 10,
      },
    };

    // Mock initial order list
    (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders));

    renderWithProviders(<OrderManagement />);

    // Wait for initial data to load
    await waitFor(() => {
      expect(screen.getByText('ORDER001')).toBeInTheDocument();
      expect(screen.getByText('testuser')).toBeInTheDocument();
      expect(screen.getByText('张三')).toBeInTheDocument();
      // Use getAllByText for amount since there are multiple elements with the same text
      const amountElements = screen.getAllByText('¥100.00');
      expect(amountElements.length).toBeGreaterThan(0);
    });

    // Verify API was called with correct parameters
    expect(adminOrderClient.$get).toHaveBeenCalledWith({
      query: {
        page: 1,
        pageSize: 10,
        keyword: '',
        filters: undefined,
      },
    });
  });

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

    (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders));

    renderWithProviders(<OrderManagement />);

    // Wait for search elements to be available (search area is always available even during loading)
    await waitFor(() => {
      expect(screen.getByTestId('order-search-input')).toBeInTheDocument();
      expect(screen.getByTestId('order-search-button')).toBeInTheDocument();
    });

    // Test search
    const searchInput = screen.getByTestId('order-search-input');
    fireEvent.change(searchInput, { target: { value: 'ORDER001' } });

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

    await waitFor(() => {
      expect(adminOrderClient.$get).toHaveBeenCalledWith({
        query: {
          page: 1,
          pageSize: 10,
          keyword: 'ORDER001',
          filters: undefined,
        },
      });
    });
  });

  it('应该处理订单状态过滤', async () => {
    const mockOrders = {
      data: [],
      pagination: { total: 0, page: 1, pageSize: 10 },
    };

    (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders));

    renderWithProviders(<OrderManagement />);

    // Wait for component to load
    await waitFor(() => {
      expect(screen.getByTestId('order-status-select')).toBeInTheDocument();
    });

    // Test status filter
    const statusSelect = screen.getByTestId('order-status-select');
    fireEvent.click(statusSelect);

    const statusOption = screen.getByText('已发货');
    fireEvent.click(statusOption);

    await waitFor(() => {
      expect(adminOrderClient.$get).toHaveBeenCalledWith({
        query: {
          page: 1,
          pageSize: 10,
          keyword: '',
          filters: expect.stringContaining('"state":1'),
        },
      });
    });
  });

  it('应该处理支付状态过滤', async () => {
    const mockOrders = {
      data: [],
      pagination: { total: 0, page: 1, pageSize: 10 },
    };

    (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders));

    renderWithProviders(<OrderManagement />);

    // Wait for component to load
    await waitFor(() => {
      expect(screen.getByTestId('order-pay-status-select')).toBeInTheDocument();
    });

    // Test pay status filter
    const payStatusSelect = screen.getByTestId('order-pay-status-select');
    fireEvent.click(payStatusSelect);

    const payStatusOption = screen.getByText('支付成功');
    fireEvent.click(payStatusOption);

    await waitFor(() => {
      expect(adminOrderClient.$get).toHaveBeenCalledWith({
        query: {
          page: 1,
          pageSize: 10,
          keyword: '',
          filters: expect.stringContaining('"payState":2'),
        },
      });
    });
  });

  it('应该处理订单编辑功能', async () => {
    const { toast } = await import('sonner');
    const mockOrders = {
      data: [
        {
          id: 1,
          orderNo: 'ORDER001',
          state: 0,
          payState: 2,
          remark: '原始备注',
          user: { username: 'testuser' },
          userPhone: '13800138000',
          recevierName: '张三',
          receiverMobile: '13800138001',
          amount: 100.00,
          payAmount: 100.00,
          freightAmount: 0.00,
          orderType: 1,
          payType: 1,
          address: '北京市朝阳区',
          createdAt: '2024-01-01T00:00:00Z',
        },
      ],
      pagination: {
        total: 1,
        page: 1,
        pageSize: 10,
      },
    };

    (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders));

    renderWithProviders(<OrderManagement />);

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

    // Click edit button using test ID
    const editButtons = screen.getAllByTestId('order-edit-button');
    fireEvent.click(editButtons[0]);

    // Wait for edit modal to open and form elements to be available
    await waitFor(() => {
      expect(screen.getByText('编辑订单')).toBeInTheDocument();
      expect(screen.getByTestId('edit-order-status-select')).toBeInTheDocument();
      expect(screen.getByTestId('edit-remark-textarea')).toBeInTheDocument();
    }, { timeout: 5000 });

    // Change order status
    const statusSelect = screen.getByTestId('edit-order-status-select');
    fireEvent.click(statusSelect);

    // Use getAllByText and select the first option
    const newStatusOptions = screen.getAllByText('已发货');
    fireEvent.click(newStatusOptions[0]);

    // Change remark
    const remarkTextarea = screen.getByTestId('edit-remark-textarea');
    fireEvent.change(remarkTextarea, { target: { value: '更新后的备注' } });

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

    // Submit form using test ID
    const saveButton = screen.getByTestId('order-save-button');
    fireEvent.click(saveButton);

    await waitFor(() => {
      expect(adminOrderClient[':id']['$put']).toHaveBeenCalledWith({
        param: { id: '1' },
        json: {
          state: 0,
          payState: 2,
          remark: '更新后的备注',
        },
      });
      expect(toast.success).toHaveBeenCalledWith('订单更新成功');
    });
  });

  it('应该处理订单详情查看', async () => {
    const mockOrders = {
      data: [
        {
          id: 1,
          orderNo: 'ORDER001',
          state: 0,
          payState: 2,
          remark: '测试订单',
          user: { username: 'testuser' },
          userPhone: '13800138000',
          recevierName: '张三',
          receiverMobile: '13800138001',
          amount: 100.00,
          payAmount: 100.00,
          freightAmount: 0.00,
          orderType: 1,
          payType: 1,
          address: '北京市朝阳区',
          createdAt: '2024-01-01T00:00:00Z',
        },
      ],
      pagination: {
        total: 1,
        page: 1,
        pageSize: 10,
      },
    };

    (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders));

    renderWithProviders(<OrderManagement />);

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

    // Click view details button using test ID
    const viewButtons = screen.getAllByTestId('order-view-button');
    fireEvent.click(viewButtons[0]);

    // Wait for detail modal to open
    await waitFor(() => {
      expect(screen.getByText('订单详情')).toBeInTheDocument();
    }, { timeout: 5000 });

    // Check modal content
    expect(screen.getByText('订单详情')).toBeInTheDocument();
    // Use getAllByText for ORDER001 since there are multiple elements with the same text
    const orderNoElements = screen.getAllByText('ORDER001');
    expect(orderNoElements.length).toBeGreaterThan(0);
    // Use getAllByText for 实物订单 since there are multiple elements with the same text
    const orderTypeElements = screen.getAllByText('实物订单');
    expect(orderTypeElements.length).toBeGreaterThan(0);
    // Use getAllByText for amount since there are multiple elements with the same text
    const amountElements = screen.getAllByText('¥100.00');
    expect(amountElements.length).toBeGreaterThan(0);
    expect(screen.getByText('测试订单')).toBeInTheDocument();
  });

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

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

    renderWithProviders(<OrderManagement />);

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

    // Test edit error scenario
    const mockOrders = {
      data: [
        {
          id: 1,
          orderNo: 'ORDER001',
          state: 0,
          payState: 2,
          remark: '测试订单',
          user: { username: 'testuser' },
          userPhone: '13800138000',
          recevierName: '张三',
          receiverMobile: '13800138001',
          amount: 100.00,
          payAmount: 100.00,
          freightAmount: 0.00,
          orderType: 1,
          payType: 1,
          address: '北京市朝阳区',
          createdAt: '2024-01-01T00:00:00Z',
        },
      ],
      pagination: {
        total: 1,
        page: 1,
        pageSize: 10,
      },
    };

    // Mock successful data load
    (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders));

    // Re-render with data
    renderWithProviders(<OrderManagement />);

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

    // Click edit button using test ID
    const editButtons = screen.getAllByTestId('order-edit-button');
    fireEvent.click(editButtons[0]);

    await waitFor(() => {
      expect(screen.getByText('编辑订单')).toBeInTheDocument();
    });

    // Mock update error
    (adminOrderClient[':id']['$put'] as any).mockRejectedValue(new Error('Update failed'));

    // Submit form using test ID
    const saveButton = screen.getByTestId('order-save-button');
    fireEvent.click(saveButton);

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