import React from 'react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

// Mock lucide-react icons to avoid import errors in tests
// Using partial mock to only mock icons used by the component
vi.mock('lucide-react', async () => {
  const actual = await vi.importActual('lucide-react');
  return {
    ...actual,
    Package: () => <span data-testid="package-icon">📦</span>,
    Trash2: () => <span title="删除" data-testid="trash-icon">🗑️</span>,
    Edit: () => <span title="编辑" data-testid="edit-icon">✏️</span>,
    Eye: () => <span title="查看" data-testid="eye-icon">👁️</span>,
    Loader2: () => <span data-testid="loader-icon" className="animate-spin">⏳</span>
  };
});

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

import { ChildGoodsList } from '../../src/components/ChildGoodsList';

// 创建模拟的rpcClient函数（根据API模拟规范）
// 符合测试策略文档的API模拟规范：统一模拟@d8d/shared-ui-components/utils/hc中的rpcClient函数
const mockRpcClient = vi.hoisted(() => vi.fn((aptBaseUrl: string) => {
  // 根据页面组件实际调用的RPC路径定义模拟端点
  // 符合规范：支持Hono风格的$get、$post、$put、$delete方法
  return {
    ':id': {
      children: {
        $get: vi.fn(() => Promise.resolve(createMockResponse(200, { data: [], total: 0 }))),
      },
      $put: vi.fn(() => Promise.resolve(createMockResponse(200))),
    },
  };
}));

// 模拟共享UI组件包中的rpcClient函数（统一模拟点）
// 核心API模拟规范：统一拦截所有API调用，支持跨UI包集成测试
vi.mock('@d8d/shared-ui-components/utils/hc', () => ({
  rpcClient: mockRpcClient
}));

// 完整的mock响应对象（与GoodsParentChildPanel保持一致）
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（保持向后兼容性，但实际使用上面的统一模拟）
// 符合API模拟规范：统一模拟rpcClient函数，客户端管理器使用模拟的rpcClient
vi.mock('../../src/api/goodsClient', () => {
  // 获取模拟的客户端实例（通过mockRpcClient创建）
  // 符合测试策略文档的规范：直接通过模拟的rpcClient函数创建客户端
  const mockClient = mockRpcClient('/');

  const mockGoodsClientManager = {
    get: vi.fn(() => mockClient),
  };

  return {
    goodsClientManager: mockGoodsClientManager,
    goodsClient: mockClient,
  };
});

import { goodsClientManager } from '../../src/api/goodsClient';

describe('ChildGoodsList', () => {
  let queryClient: QueryClient;
  const mockGoodsClient = goodsClientManager.get() as any;

  beforeEach(() => {
    queryClient = new QueryClient({
      defaultOptions: {
        queries: {
          retry: false,
        },
      },
    });

    vi.clearAllMocks();
  });

  const renderComponent = (props = {}) => {
    return render(
      <QueryClientProvider client={queryClient}>
        <ChildGoodsList parentGoodsId={1} {...props} />
      </QueryClientProvider>
    );
  };

  it('应该显示加载状态', () => {
    mockGoodsClient[':id'].children.$get.mockImplementation(() =>
      new Promise(() => {}) // Never resolves to keep loading
    );

    renderComponent();

    expect(screen.getByText('子商品列表')).toBeInTheDocument();
    expect(screen.getByText('加载中...')).toBeInTheDocument();
  });

  it('应该显示空状态', async () => {
    mockGoodsClient[':id'].children.$get.mockResolvedValue(
      createMockResponse(200, { data: [], total: 0 })
    );

    renderComponent();

    await waitFor(() => {
      expect(screen.getByText('暂无子商品')).toBeInTheDocument();
      expect(screen.getByText('可以批量创建子商品规格')).toBeInTheDocument();
    });
  });

  it('应该显示子商品列表', async () => {
    const mockChildren = [
      {
        id: 1,
        name: '子商品1 - 红色',
        price: 100.00,
        costPrice: 80.00,
        stock: 50,
        sort: 1,
        state: 1,
        createdAt: '2025-12-09T10:00:00Z'
      },
      {
        id: 2,
        name: '子商品2 - 蓝色',
        price: 110.00,
        costPrice: 85.00,
        stock: 30,
        sort: 2,
        state: 1,
        createdAt: '2025-12-09T11:00:00Z'
      },
      {
        id: 3,
        name: '子商品3 - 不可用',
        price: 120.00,
        costPrice: 90.00,
        stock: 0,
        sort: 3,
        state: 0,
        createdAt: '2025-12-09T12:00:00Z'
      }
    ];

    mockGoodsClient[':id'].children.$get.mockResolvedValue(
      createMockResponse(200, { data: mockChildren, total: 3 })
    );

    renderComponent();

    await waitFor(() => {
      expect(screen.getByText('子商品列表')).toBeInTheDocument();
      expect(screen.getByText('共 3 个子商品规格')).toBeInTheDocument();

      // 检查商品名称
      expect(screen.getByText('子商品1 - 红色')).toBeInTheDocument();
      expect(screen.getByText('子商品2 - 蓝色')).toBeInTheDocument();
      expect(screen.getByText('子商品3 - 不可用')).toBeInTheDocument();

      // 检查价格（可能有多个相同价格的元素，如统计信息）
      expect(screen.getAllByText('¥100.00').length).toBeGreaterThan(0);
      expect(screen.getAllByText('¥110.00').length).toBeGreaterThan(0);
      expect(screen.getAllByText('¥120.00').length).toBeGreaterThan(0);

      // 检查库存（可能有多个相同库存的元素）
      expect(screen.getAllByText('50').length).toBeGreaterThan(0);
      expect(screen.getAllByText('30').length).toBeGreaterThan(0);
      expect(screen.getAllByText('0').length).toBeGreaterThan(0);

      // 检查状态标签
      expect(screen.getAllByText('可用')).toHaveLength(2);
      expect(screen.getByText('不可用')).toBeInTheDocument();
    });
  });

  it('应该显示统计信息', async () => {
    const mockChildren = [
      {
        id: 1,
        name: '商品1',
        price: 100,
        costPrice: 80,
        stock: 10,
        sort: 1,
        state: 1,
        createdAt: '2025-12-09T10:00:00Z'
      },
      {
        id: 2,
        name: '商品2',
        price: 200,
        costPrice: 150,
        stock: 20,
        sort: 2,
        state: 1,
        createdAt: '2025-12-09T11:00:00Z'
      }
    ];

    mockGoodsClient[':id'].children.$get.mockResolvedValue(
      createMockResponse(200, { data: mockChildren, total: 2 })
    );

    renderComponent();

    await waitFor(() => {
      // 检查统计信息
      expect(screen.getByText('总库存')).toBeInTheDocument();
      expect(screen.getAllByText('30').length).toBeGreaterThan(0); // 10 + 20

      expect(screen.getByText('平均价格')).toBeInTheDocument();
      expect(screen.getAllByText('¥150.00').length).toBeGreaterThan(0); // (100+200)/2

      expect(screen.getByText('可用商品')).toBeInTheDocument();
      expect(screen.getByText('2 / 2')).toBeInTheDocument();
    });
  });

  it('应该处理API错误', async () => {
    mockGoodsClient[':id'].children.$get.mockResolvedValue(
      createMockResponse(500, { error: '服务器错误' })
    );

    renderComponent();

    await waitFor(() => {
      // 应该显示空状态而不是崩溃
      expect(screen.getByText('暂无子商品')).toBeInTheDocument();
    });
  });

  it('应该支持禁用操作按钮', async () => {
    const mockChildren = [
      {
        id: 1,
        name: '测试商品',
        price: 100,
        costPrice: 80,
        stock: 10,
        sort: 1,
        state: 1,
        createdAt: '2025-12-09T10:00:00Z'
      }
    ];

    mockGoodsClient[':id'].children.$get.mockResolvedValue(
      createMockResponse(200, { data: mockChildren, total: 1 })
    );

    renderComponent({ showActions: false });

    await waitFor(() => {
      expect(screen.getByText('测试商品')).toBeInTheDocument();
      // 不应该显示操作列
      expect(screen.queryByText('操作')).not.toBeInTheDocument();
    });
  });

  it('应该调用回调函数', async () => {
    const mockChildren = [
      {
        id: 1,
        name: '测试商品',
        price: 100,
        costPrice: 80,
        stock: 10,
        sort: 1,
        state: 1,
        createdAt: '2025-12-09T10:00:00Z'
      }
    ];

    mockGoodsClient[':id'].children.$get.mockResolvedValue(
      createMockResponse(200, { data: mockChildren, total: 1 })
    );

    const onEditChild = vi.fn();
    const onDeleteChild = vi.fn();
    const onViewChild = vi.fn();

    renderComponent({
      onEditChild,
      onDeleteChild,
      onViewChild
    });

    await waitFor(() => {
      expect(screen.getByText('测试商品')).toBeInTheDocument();
    });

    // 点击删除按钮（可能有多个，点击第一个）
    const deleteButtons = screen.getAllByTitle('删除');
    expect(deleteButtons.length).toBeGreaterThan(0);
    await userEvent.click(deleteButtons[0]);

    // 验证onDeleteChild回调被调用，并传递正确的子商品ID
    expect(onDeleteChild).toHaveBeenCalledTimes(1);
    expect(onDeleteChild).toHaveBeenCalledWith(1);
  });

  it('应该在删除期间显示加载状态并禁用按钮', async () => {
    const mockChildren = [
      {
        id: 1,
        name: '测试商品',
        price: 100,
        costPrice: 80,
        stock: 10,
        sort: 1,
        state: 1,
        createdAt: '2025-12-09T10:00:00Z'
      }
    ];

    mockGoodsClient[':id'].children.$get.mockResolvedValue(
      createMockResponse(200, { data: mockChildren, total: 1 })
    );

    const onDeleteChild = vi.fn();

    renderComponent({
      onDeleteChild,
      deletingChildId: 1,
      isDeleting: true
    });

    await waitFor(() => {
      expect(screen.getByText('测试商品')).toBeInTheDocument();
    });

    // 删除按钮应该被禁用（可能有多个，检查第一个）
    const deleteButtons = screen.getAllByTitle('删除');
    expect(deleteButtons.length).toBeGreaterThan(0);
    expect(deleteButtons[0]).toBeDisabled();

    // 应该显示加载旋转器而不是垃圾桶图标
    // Loader2图标有animate-spin类
    const loaderIcon = deleteButtons[0].querySelector('.animate-spin');
    expect(loaderIcon).toBeInTheDocument();
  });

  describe('行内编辑功能', () => {
    const mockChild = {
      id: 1,
      name: '测试商品',
      price: 100.00,
      costPrice: 80.00,
      stock: 10,
      sort: 1,
      state: 1,
      createdAt: '2025-12-09T10:00:00Z'
    };

    beforeEach(() => {
      mockGoodsClient[':id'].children.$get.mockResolvedValue(
        createMockResponse(200, { data: [mockChild], total: 1 })
      );
    });

    it('应该显示编辑按钮', async () => {
      renderComponent();

      await waitFor(() => {
        expect(screen.getByText('测试商品')).toBeInTheDocument();
      });

      // 应该显示编辑按钮（可能有多个，检查至少存在一个）
      const editButtons = screen.getAllByTitle('编辑');
      expect(editButtons.length).toBeGreaterThan(0);
      expect(editButtons[0]).toBeInTheDocument();
    });

    it('点击编辑按钮应该触发行内编辑模式', async () => {
      renderComponent();

      await waitFor(() => {
        expect(screen.getByText('测试商品')).toBeInTheDocument();
      });

      // 点击编辑按钮（可能有多个，点击第一个）
      const editButtons = screen.getAllByTitle('编辑');
      expect(editButtons.length).toBeGreaterThan(0);
      await userEvent.click(editButtons[0]);

      // 应该显示行内编辑表单
      expect(screen.getByLabelText('商品名称')).toBeInTheDocument();
      expect(screen.getByLabelText('价格')).toBeInTheDocument();
      expect(screen.getByLabelText('库存')).toBeInTheDocument();
      expect(screen.getByText('保存')).toBeInTheDocument();
      expect(screen.getByText('取消')).toBeInTheDocument();
    });

    it('点击取消按钮应该退出编辑模式', async () => {
      renderComponent();

      await waitFor(() => {
        expect(screen.getByText('测试商品')).toBeInTheDocument();
      });

      // 进入编辑模式（可能有多个编辑按钮，点击第一个）
      const editButtons = screen.getAllByTitle('编辑');
      expect(editButtons.length).toBeGreaterThan(0);
      await userEvent.click(editButtons[0]);

      // 点击取消按钮
      const cancelButton = screen.getByText('取消');
      await userEvent.click(cancelButton);

      // 应该退出编辑模式，显示正常行
      expect(screen.queryByLabelText('商品名称')).not.toBeInTheDocument();
      expect(screen.getByText('测试商品')).toBeInTheDocument();
    });

    it('应该成功保存编辑', async () => {
      // Mock 更新API成功响应
      mockGoodsClient[':id'].$put.mockResolvedValue(
        createMockResponse(200, { success: true })
      );

      renderComponent();

      await waitFor(() => {
        expect(screen.getByText('测试商品')).toBeInTheDocument();
      });

      // 进入编辑模式（可能有多个编辑按钮，点击第一个）
      const editButtons = screen.getAllByTitle('编辑');
      expect(editButtons.length).toBeGreaterThan(0);
      await userEvent.click(editButtons[0]);

      // 修改商品名称
      const nameInput = screen.getByLabelText('商品名称');
      await userEvent.clear(nameInput);
      await userEvent.type(nameInput, '修改后的商品名称');

      // 点击保存按钮
      const saveButton = screen.getByText('保存');
      await userEvent.click(saveButton);

      // 应该调用更新API
      await waitFor(() => {
        expect(mockGoodsClient[':id'].$put).toHaveBeenCalledWith({
          param: { id: 1 },
          json: expect.objectContaining({
            name: '修改后的商品名称',
            price: 100,
            stock: 10
          })
        });
      });

      // 应该刷新列表
      await waitFor(() => {
        expect(mockGoodsClient[':id'].children.$get).toHaveBeenCalledTimes(2);
      });
    });

    it('应该处理保存失败', async () => {
      // Mock 更新API失败响应
      mockGoodsClient[':id'].$put.mockResolvedValue(
        createMockResponse(400, { error: '验证失败' })
      );

      renderComponent();

      await waitFor(() => {
        expect(screen.getByText('测试商品')).toBeInTheDocument();
      });

      // 进入编辑模式（可能有多个编辑按钮，点击第一个）
      const editButtons = screen.getAllByTitle('编辑');
      expect(editButtons.length).toBeGreaterThan(0);
      await userEvent.click(editButtons[0]);

      // 点击保存按钮
      const saveButton = screen.getByText('保存');
      await userEvent.click(saveButton);

      // 应该调用更新API
      await waitFor(() => {
        expect(mockGoodsClient[':id'].$put).toHaveBeenCalled();
      });

      // 应该仍然在编辑模式（因为保存失败）
      expect(screen.getByLabelText('商品名称')).toBeInTheDocument();
    });

    it('表单验证应该工作', async () => {
      renderComponent();

      await waitFor(() => {
        expect(screen.getByText('测试商品')).toBeInTheDocument();
      });

      // 进入编辑模式（可能有多个编辑按钮，点击第一个）
      const editButtons = screen.getAllByTitle('编辑');
      expect(editButtons.length).toBeGreaterThan(0);
      await userEvent.click(editButtons[0]);

      // 清空商品名称
      const nameInput = screen.getByLabelText('商品名称');
      fireEvent.change(nameInput, { target: { value: '' } });
      fireEvent.blur(nameInput);

      // 设置负价格
      const priceInput = screen.getByLabelText('价格');
      fireEvent.change(priceInput, { target: { value: '-10' } });
      fireEvent.blur(priceInput);

      // 点击保存按钮
      const saveButton = screen.getByText('保存');
      await userEvent.click(saveButton);

      // 应该显示验证错误
      await waitFor(() => {
        expect(screen.getByText('商品名称不能为空')).toBeInTheDocument();
        expect(screen.getByText('价格不能为负数')).toBeInTheDocument();
      });

      // 不应该调用API
      expect(mockGoodsClient[':id'].$put).not.toHaveBeenCalled();
    });
  });
});