import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { vi } from 'vitest';
import { GoodsRelationshipTree } from '../../src/components/GoodsRelationshipTree';

// Mock the goodsClientManager
vi.mock('../../src/api/goodsClient', () => ({
  goodsClientManager: {
    get: vi.fn(() => ({
      ':id': {
        $get: vi.fn(({ param }: { param: { id: number } }) => {
          if (param.id === 1) {
            return Promise.resolve({
              status: 200,
              json: () => Promise.resolve({
                id: 1,
                name: '父商品',
                price: 100,
                stock: 50,
                spuId: 0,
                spuName: null,
                state: 1
              })
            });
          } else if (param.id === 2) {
            return Promise.resolve({
              status: 200,
              json: () => Promise.resolve({
                id: 2,
                name: '子商品A',
                price: 120,
                stock: 20,
                spuId: 1,
                spuName: '父商品',
                state: 1
              })
            });
          }
          return Promise.reject(new Error('商品不存在'));
        })
      },
      index: {
        $get: vi.fn(({ query }: { query: { spuId: number } }) => {
          if (query.spuId === 1) {
            return Promise.resolve({
              status: 200,
              json: () => Promise.resolve({
                data: [
                  { id: 2, name: '子商品A', price: 120, stock: 20, spuId: 1, spuName: '父商品', state: 1 },
                  { id: 3, name: '子商品B', price: 150, stock: 30, spuId: 1, spuName: '父商品', state: 1 }
                ]
              })
            });
          }
          return Promise.resolve({
            status: 200,
            json: () => Promise.resolve({ data: [] })
          });
        })
      }
    }))
  }
}));

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

const Wrapper = ({ children }: { children: React.ReactNode }) => (
  <QueryClientProvider client={queryClient}>
    {children}
  </QueryClientProvider>
);

describe('GoodsRelationshipTree', () => {
  beforeEach(() => {
    queryClient.clear();
    vi.clearAllMocks();
  });

  it('应该正确渲染父商品关系树', async () => {
    render(
      <Wrapper>
        <GoodsRelationshipTree goodsId={1} />
      </Wrapper>
    );

    // 等待数据加载
    await waitFor(() => {
      expect(screen.getByText('商品关系树')).toBeInTheDocument();
      expect(screen.getByText('父商品及其子商品关系')).toBeInTheDocument();
      expect(screen.getByText('父商品')).toBeInTheDocument();
      expect(screen.getByText('当前商品')).toBeInTheDocument();
      expect(screen.getByText('子商品 (2)')).toBeInTheDocument();
      expect(screen.getByText('子商品A')).toBeInTheDocument();
      expect(screen.getByText('子商品B')).toBeInTheDocument();
    });

    // 检查商品状态标签
    expect(screen.getAllByText('父商品')).toHaveLength(2); // 一个在标题，一个在标签
    expect(screen.getAllByText('子商品')).toHaveLength(2); // 两个子商品
    expect(screen.getAllByText('可用')).toHaveLength(3); // 父商品 + 两个子商品
  });

  it('应该正确渲染子商品关系树', async () => {
    render(
      <Wrapper>
        <GoodsRelationshipTree goodsId={2} />
      </Wrapper>
    );

    await waitFor(() => {
      expect(screen.getByText('商品关系树')).toBeInTheDocument();
      expect(screen.getByText('子商品及其父商品关系')).toBeInTheDocument();
      expect(screen.getByText('父商品')).toBeInTheDocument();
      expect(screen.getByText('当前商品')).toBeInTheDocument();
      expect(screen.getByText('子商品A')).toBeInTheDocument();
    });

    // 检查父商品信息
    expect(screen.getByText('父商品: 父商品')).toBeInTheDocument();
  });

  it('应该显示加载状态', () => {
    render(
      <Wrapper>
        <GoodsRelationshipTree goodsId={1} />
      </Wrapper>
    );

    expect(screen.getByText('加载中...')).toBeInTheDocument();
    expect(screen.getAllByTestId('skeleton')).toBeTruthy();
  });

  it('应该显示空状态（父商品没有子商品）', async () => {
    // 模拟没有子商品的情况
    const mockGoodsClientManager = require('../../src/api/goodsClient').goodsClientManager;
    mockGoodsClientManager.get.mockImplementation(() => ({
      ':id': {
        $get: vi.fn(() => Promise.resolve({
          status: 200,
          json: () => Promise.resolve({
            id: 4,
            name: '单规格商品',
            price: 100,
            stock: 50,
            spuId: 0,
            spuName: null,
            state: 1
          })
        }))
      },
      index: {
        $get: vi.fn(() => Promise.resolve({
          status: 200,
          json: () => Promise.resolve({ data: [] })
        }))
      }
    }));

    render(
      <Wrapper>
        <GoodsRelationshipTree goodsId={4} />
      </Wrapper>
    );

    await waitFor(() => {
      expect(screen.getByText('此商品没有子商品')).toBeInTheDocument();
      expect(screen.getByText('可以点击"批量创建子商品"按钮添加子商品规格')).toBeInTheDocument();
    });
  });

  it('应该展开和收起子商品节点', async () => {
    render(
      <Wrapper>
        <GoodsRelationshipTree goodsId={1} />
      </Wrapper>
    );

    await waitFor(() => {
      expect(screen.getByText('子商品A')).toBeInTheDocument();
      expect(screen.getByText('子商品B')).toBeInTheDocument();
    });

    // 找到展开/收起按钮
    const expandButtons = screen.getAllByRole('button', { name: '' });
    const parentExpandButton = expandButtons[0]; // 父商品的展开按钮

    // 初始应该是展开的
    expect(screen.getByText('子商品A')).toBeVisible();
    expect(screen.getByText('子商品B')).toBeVisible();

    // 点击收起
    fireEvent.click(parentExpandButton);

    // 子商品应该不可见
    await waitFor(() => {
      expect(screen.queryByText('子商品A')).not.toBeVisible();
      expect(screen.queryByText('子商品B')).not.toBeVisible();
    });

    // 再次点击展开
    fireEvent.click(parentExpandButton);

    await waitFor(() => {
      expect(screen.getByText('子商品A')).toBeVisible();
      expect(screen.getByText('子商品B')).toBeVisible();
    });
  });

  it('应该显示商品价格和库存信息', async () => {
    render(
      <Wrapper>
        <GoodsRelationshipTree goodsId={1} />
      </Wrapper>
    );

    await waitFor(() => {
      expect(screen.getByText('¥100.00')).toBeInTheDocument();
      expect(screen.getByText('库存: 50')).toBeInTheDocument();
      expect(screen.getByText('¥120.00')).toBeInTheDocument();
      expect(screen.getByText('库存: 20')).toBeInTheDocument();
      expect(screen.getByText('¥150.00')).toBeInTheDocument();
      expect(screen.getByText('库存: 30')).toBeInTheDocument();
    });
  });

  it('应该显示关系说明', async () => {
    render(
      <Wrapper>
        <GoodsRelationshipTree goodsId={1} />
      </Wrapper>
    );

    await waitFor(() => {
      expect(screen.getByText('spuId = 0，可以有多个子商品')).toBeInTheDocument();
      expect(screen.getByText('spuId > 0，关联到父商品，表示不同规格')).toBeInTheDocument();
      expect(screen.getByText('• 父子商品必须在同一租户下')).toBeInTheDocument();
      expect(screen.getByText('• 子商品不能有自己的子商品')).toBeInTheDocument();
      expect(screen.getByText('• 一个商品不能同时是父商品和子商品')).toBeInTheDocument();
    });
  });

  it('应该处理商品不存在的错误', async () => {
    const mockGoodsClientManager = require('../../src/api/goodsClient').goodsClientManager;
    mockGoodsClientManager.get.mockImplementation(() => ({
      ':id': {
        $get: vi.fn(() => Promise.reject(new Error('商品不存在')))
      },
      index: {
        $get: vi.fn(() => Promise.resolve({
          status: 200,
          json: () => Promise.resolve({ data: [] })
        }))
      }
    }));

    render(
      <Wrapper>
        <GoodsRelationshipTree goodsId={999} />
      </Wrapper>
    );

    await waitFor(() => {
      expect(screen.getByText('未找到商品信息')).toBeInTheDocument();
      expect(screen.getByText('无法加载商品关系信息')).toBeInTheDocument();
    });
  });

  it('应该支持租户过滤', async () => {
    render(
      <Wrapper>
        <GoodsRelationshipTree goodsId={1} tenantId={123} />
      </Wrapper>
    );

    await waitFor(() => {
      expect(screen.getByText('商品关系树')).toBeInTheDocument();
    });
  });
});