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 { GoodsChildSelector } from '../../src/components/GoodsChildSelector';

// Mock the goodsClientManager
vi.mock('../../src/api/goodsClient', () => ({
  goodsClientManager: {
    get: vi.fn(() => ({
      index: {
        $get: vi.fn(() => Promise.resolve({
          status: 200,
          json: () => Promise.resolve({
            data: [
              { id: 1, name: '商品A', price: 100, stock: 10, spuId: 0, spuName: null },
              { id: 2, name: '商品B', price: 200, stock: 20, spuId: 0, spuName: null },
              { id: 3, name: '商品C', price: 300, stock: 30, spuId: 1, spuName: '父商品' }, // 已经是子商品
              { id: 4, name: '商品D', price: 400, stock: 40, spuId: 0, spuName: null },
            ]
          })
        }))
      }
    }))
  }
}));

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

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

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

  it('应该正确渲染组件', () => {
    render(
      <Wrapper>
        <GoodsChildSelector />
      </Wrapper>
    );

    expect(screen.getByRole('combobox')).toBeInTheDocument();
    expect(screen.getByPlaceholderText('选择子商品...')).toBeInTheDocument();
  });

  it('应该显示自定义占位符', () => {
    render(
      <Wrapper>
        <GoodsChildSelector placeholder="请选择子商品" />
      </Wrapper>
    );

    expect(screen.getByText('请选择子商品')).toBeInTheDocument();
  });

  it('应该禁用时显示禁用状态', () => {
    render(
      <Wrapper>
        <GoodsChildSelector disabled={true} />
      </Wrapper>
    );

    const button = screen.getByRole('combobox');
    expect(button).toBeDisabled();
  });

  it('应该显示已选择的商品标签', () => {
    render(
      <Wrapper>
        <GoodsChildSelector value={[1, 2]} />
      </Wrapper>
    );

    // 等待数据加载
    waitFor(() => {
      expect(screen.getByText('商品A')).toBeInTheDocument();
      expect(screen.getByText('商品B')).toBeInTheDocument();
      expect(screen.getByText('已选择 2 个子商品')).toBeInTheDocument();
    });
  });

  it('应该打开下拉菜单并显示商品列表', async () => {
    render(
      <Wrapper>
        <GoodsChildSelector />
      </Wrapper>
    );

    const button = screen.getByRole('combobox');
    fireEvent.click(button);

    await waitFor(() => {
      expect(screen.getByPlaceholderText('搜索商品名称...')).toBeInTheDocument();
      expect(screen.getByText('商品A')).toBeInTheDocument();
      expect(screen.getByText('商品B')).toBeInTheDocument();
      expect(screen.getByText('商品D')).toBeInTheDocument();
      // 商品C不应该显示，因为它已经是子商品
      expect(screen.queryByText('商品C')).not.toBeInTheDocument();
    });
  });

  it('应该过滤掉自己（当指定parentGoodsId时）', async () => {
    render(
      <Wrapper>
        <GoodsChildSelector parentGoodsId={1} />
      </Wrapper>
    );

    const button = screen.getByRole('combobox');
    fireEvent.click(button);

    await waitFor(() => {
      // 商品A不应该显示，因为它是自己
      expect(screen.queryByText('商品A')).not.toBeInTheDocument();
      expect(screen.getByText('商品B')).toBeInTheDocument();
      expect(screen.getByText('商品D')).toBeInTheDocument();
    });
  });

  it('应该选择商品并触发onChange', async () => {
    const onChange = vi.fn();
    render(
      <Wrapper>
        <GoodsChildSelector onChange={onChange} />
      </Wrapper>
    );

    const button = screen.getByRole('combobox');
    fireEvent.click(button);

    await waitFor(() => {
      const item = screen.getByText('商品B');
      fireEvent.click(item);
    });

    expect(onChange).toHaveBeenCalledWith([2]);
  });

  it('应该移除已选择的商品', async () => {
    const onChange = vi.fn();
    render(
      <Wrapper>
        <GoodsChildSelector value={[1, 2]} onChange={onChange} />
      </Wrapper>
    );

    await waitFor(() => {
      const removeButton = screen.getAllByRole('button', { name: '' })[0];
      fireEvent.click(removeButton);
    });

    expect(onChange).toHaveBeenCalledWith([2]);
  });

  it('应该清空所有选择', async () => {
    const onChange = vi.fn();
    render(
      <Wrapper>
        <GoodsChildSelector value={[1, 2]} onChange={onChange} />
      </Wrapper>
    );

    await waitFor(() => {
      const clearButton = screen.getByText('清空选择');
      fireEvent.click(clearButton);
    });

    expect(onChange).toHaveBeenCalledWith([]);
  });

  it('应该显示租户过滤说明', () => {
    render(
      <Wrapper>
        <GoodsChildSelector tenantId={123} />
      </Wrapper>
    );

    expect(screen.getByText('• 只能选择同一租户下的商品')).toBeInTheDocument();
    expect(screen.getByText('• 不能选择自己作为子商品')).toBeInTheDocument();
    expect(screen.getByText('• 不能选择已经是子商品的商品')).toBeInTheDocument();
  });
});