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 { GoodsCategoryTreeManagement } from '../../src/components/GoodsCategoryTreeManagement';
import { goodsCategoryClient } from '../../src/api/goodsCategoryClient';

// 完整的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 goodsCategoryClient - 按照用户UI包规范
vi.mock('../../src/api/goodsCategoryClient', () => {
  const mockGoodsCategoryClient = {
    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 mockGoodsCategoryClientManager = {
    get: vi.fn(() => mockGoodsCategoryClient),
  };

  return {
    goodsCategoryClientManager: mockGoodsCategoryClientManager,
    goodsCategoryClient: mockGoodsCategoryClient,
  };
});

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

// Mock FileSelector
vi.mock('@d8d/file-management-ui-mt', () => ({
  FileSelector: ({ value, onChange }: { value?: number; onChange?: (value: number) => void }) => (
    <div data-testid="file-selector">
      <button onClick={() => onChange?.(1)}>选择文件</button>
      <span>当前文件ID: {value}</span>
    </div>
  )
}));

// 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 top level data
    (goodsCategoryClient.index.$get as any).mockResolvedValueOnce(createMockResponse(200, {
      data: [
        {
          id: 1,
          tenantId: 1,
          name: '电子产品',
          parentId: 0,
          level: 1,
          state: 1,
          imageFileId: null
        }
      ]
    }));

    render(
      <TestWrapper>
        <GoodsCategoryTreeManagement />
      </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
    (goodsCategoryClient.index.$get as any).mockImplementationOnce(() =>
      new Promise(resolve => setTimeout(() => resolve(createMockResponse(200, { data: [] })), 100))
    );

    render(
      <TestWrapper>
        <GoodsCategoryTreeManagement />
      </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
    (goodsCategoryClient.index.$get as any).mockResolvedValueOnce(createMockResponse(200, { data: [] }));

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

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

  it('应该在点击新增按钮时打开创建对话框', async () => {
    // Mock successful API response
    (goodsCategoryClient.index.$get as any).mockResolvedValueOnce(createMockResponse(200, {
      data: [
        {
          id: 1,
          tenantId: 1,
          name: '电子产品',
          parentId: 0,
          level: 1,
          state: 1,
          imageFileId: null
        }
      ]
    }));

    render(
      <TestWrapper>
        <GoodsCategoryTreeManagement />
      </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
    (goodsCategoryClient.index.$get as any).mockRejectedValueOnce(new Error('API Error'));

    render(
      <TestWrapper>
        <GoodsCategoryTreeManagement />
      </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 categories data
    const mockCategories = {
      data: [
        {
          id: 1,
          tenantId: 1,
          name: '电子产品',
          parentId: 0,
          level: 1,
          state: 1,
          imageFileId: null
        }
      ]
    };

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

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

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

    // Test create category
    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('输入分类名称');
    fireEvent.change(nameInput, { target: { value: '服装' } });

    // Mock successful creation
    (goodsCategoryClient.index.$post as any).mockResolvedValue(createMockResponse(201, { id: 2, name: '服装' }));

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

    await waitFor(() => {
      expect(goodsCategoryClient.index.$post).toHaveBeenCalledWith({
        json: {
          tenantId: 1,
          name: '服装',
          parentId: 0,
          level: 1,
          state: 1,
          imageFileId: null
        }
      });
      expect(toast.success).toHaveBeenCalledWith('商品分类创建成功');
    });

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

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

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

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

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

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

    // Mock initial data
    const mockCategories = {
      data: [
        {
          id: 1,
          tenantId: 1,
          name: '电子产品',
          parentId: 0,
          level: 1,
          state: 1,
          imageFileId: null
        }
      ]
    };

    (goodsCategoryClient.index.$get as any).mockResolvedValue(createMockResponse(200, mockCategories));

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

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

    // Test create category error
    const addButton = screen.getByText('新增顶级分类');
    fireEvent.click(addButton);

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

    const nameInput = screen.getByPlaceholderText('输入分类名称');
    fireEvent.change(nameInput, { target: { value: '服装' } });

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

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

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

  it('应该支持多级分类层级（顶级→一级→二级→三级）', async () => {
    // Mock initial data with all levels
    const mockCategories = {
      data: [
        {
          id: 1,
          tenantId: 1,
          name: '电子产品',
          parentId: 0,
          level: 1,
          state: 1,
          imageFileId: null
        },
        {
          id: 2,
          tenantId: 1,
          name: '手机',
          parentId: 1,
          level: 2,
          state: 1,
          imageFileId: null
        },
        {
          id: 3,
          tenantId: 1,
          name: '智能手机',
          parentId: 2,
          level: 3,
          state: 1,
          imageFileId: null
        },
        {
          id: 4,
          tenantId: 1,
          name: '苹果手机',
          parentId: 3,
          level: 4,
          state: 1,
          imageFileId: null
        }
      ]
    };

    (goodsCategoryClient.index.$get as any).mockResolvedValue(createMockResponse(200, mockCategories));

    render(
      <TestWrapper>
        <GoodsCategoryTreeManagement />
      </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('应该成功创建多级分类（三级分类）', async () => {
    const { toast } = await import('sonner');

    // Mock initial data with level 2 category
    const mockCategories = {
      data: [
        {
          id: 3,
          tenantId: 1,
          name: '智能手机',
          parentId: 2,
          level: 2,
          state: 1,
          imageFileId: null
        }
      ]
    };

    (goodsCategoryClient.index.$get as any).mockResolvedValue(createMockResponse(200, mockCategories));

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

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

    // Click add child button for level 2 category
    const addChildButtons = screen.getAllByRole('button', { name: '新增子分类' });
    fireEvent.click(addChildButtons[0]);

    // Check if child creation dialog opens
    await waitFor(() => {
      expect(screen.getByRole('heading', { name: '新增子分类' })).toBeInTheDocument();
      expect(screen.getByText('在分类 "智能手机" 下新增子分类')).toBeInTheDocument();
    });

    // Fill child form
    const nameInput = screen.getByPlaceholderText('输入分类名称');
    fireEvent.change(nameInput, { target: { value: '苹果手机' } });

    // Mock successful child creation
    (goodsCategoryClient.index.$post as any).mockResolvedValue(createMockResponse(201, { id: 4, name: '苹果手机' }));

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

    await waitFor(() => {
      expect(goodsCategoryClient.index.$post).toHaveBeenCalledWith({
        json: {
          tenantId: 1,
          name: '苹果手机',
          parentId: 3,
          level: 3,
          state: 1,
          imageFileId: null
        }
      });
      expect(toast.success).toHaveBeenCalledWith('商品分类创建成功');
    });
  });

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

    // Mock initial data with category
    const mockCategories = {
      data: [
        {
          id: 4,
          tenantId: 1,
          name: '苹果手机',
          parentId: 3,
          level: 3,
          state: 1,
          imageFileId: null
        }
      ]
    };

    (goodsCategoryClient.index.$get as any).mockResolvedValue(createMockResponse(200, mockCategories));

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

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

    // Click toggle status button for category
    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
    (goodsCategoryClient[':id'].$put as any).mockResolvedValue(createMockResponse(200));

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

    await waitFor(() => {
      expect(goodsCategoryClient[':id'].$put).toHaveBeenCalledWith({
        param: { id: 4 },
        json: { state: 2 }
      });
      expect(toast.success).toHaveBeenCalledWith('商品分类禁用成功');
    });
  });

  it('应该成功删除多级分类（三级分类）', async () => {
    const { toast } = await import('sonner');

    // Mock initial data with level 3 category
    const mockCategories = {
      data: [
        {
          id: 4,
          tenantId: 1,
          name: '苹果手机',
          parentId: 3,
          level: 3,
          state: 1,
          imageFileId: null
        }
      ]
    };

    (goodsCategoryClient.index.$get as any).mockResolvedValue(createMockResponse(200, mockCategories));

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

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

    // Click delete button for category
    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
    (goodsCategoryClient[':id'].$delete as any).mockResolvedValue(createMockResponse(204));

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

    await waitFor(() => {
      expect(goodsCategoryClient[':id'].$delete).toHaveBeenCalledWith({
        param: { id: 4 }
      });
      expect(toast.success).toHaveBeenCalledWith('商品分类删除成功');
    });
  });
});