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

// 不模拟@tanstack/react-query，使用真实实现（符合组件模拟策略要求）
// 通过模拟rpcClient来控制API响应

// 完整的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 () => {
    console.debug('createMockResponse json() called, data:', data);
    return data || {};
  },
  text: async () => '',
  blob: async () => new Blob(),
  arrayBuffer: async () => new ArrayBuffer(0),
  formData: async () => new FormData(),
  clone: function() { return this; }
});

// 统一模拟rpcClient函数（符合API模拟规范）
const mockRpcClient = vi.hoisted(() => vi.fn((aptBaseUrl: string) => {
  console.debug('mockRpcClient called with baseUrl:', aptBaseUrl);
  const mockClient = {
    ':id': {
      $get: vi.fn((options) => {
        console.debug('mock $get called with:', options);
        return Promise.resolve(createMockResponse(200, {
          id: 1,
          name: '测试父商品',
          categoryId1: 1,
          categoryId2: 2,
          categoryId3: 3,
          goodsType: 1,
          supplierId: 1,
          merchantId: 1,
          price: 100,
          costPrice: 80,
          stock: 100,
          state: 1,
          tenantId: 1
        }));
      })
    },
    index: {
      $post: vi.fn((options) => {
        console.debug('mock $post called with:', options);
        return Promise.resolve(createMockResponse(201, { id: 100, name: '父商品 - 规格1' }));
      })
    }
  };
  return mockClient;
}));

vi.mock('@d8d/shared-ui-components/utils/hc', () => ({
  rpcClient: mockRpcClient
}));

// goodsClientManager不再需要模拟，因为它使用我们模拟的rpcClient
// 保持真实实现，通过rpcClient模拟控制API响应

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

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      retry: false,
      staleTime: 0,
      gcTime: 0, // 注意：React Query v5中cacheTime改为gcTime
      refetchOnWindowFocus: false,
      refetchOnMount: true,
      refetchOnReconnect: false,
      enabled: true, // 确保查询启用
    },
    mutations: {
      retry: false,
    },
  },
});

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

// Helper function to wait for parent goods data to load
const waitForParentGoodsLoaded = async () => {
  // 等待加载提示消失
  await waitFor(() => {
    expect(screen.queryByText('正在加载父商品信息...')).not.toBeInTheDocument();
  }, { timeout: 5000 });

  // 等待父商品ID显示
  await waitFor(() => {
    expect(screen.getByDisplayValue('1')).toBeInTheDocument(); // 父商品ID
  }, { timeout: 5000 });
};

describe('BatchSpecCreator', () => {
  const defaultProps = {
    parentGoodsId: 1,
    parentGoodsName: '父商品',
    onSuccess: vi.fn(),
    onCancel: vi.fn()
  };

  beforeEach(() => {
    queryClient.clear();
    vi.clearAllMocks();
  });

  it('应该正确渲染组件', async () => {
    render(
      <Wrapper>
        <BatchSpecCreator {...defaultProps} />
      </Wrapper>
    );

    // 等待父商品数据加载完成
    await waitForParentGoodsLoaded();

    // 检查对话框标题
    expect(screen.getByText('批量创建子商品规格')).toBeInTheDocument();
    expect(screen.getByText('为父商品 "父商品" 批量创建多个子商品规格')).toBeInTheDocument();

    // 检查父商品信息区域
    expect(screen.getByText('父商品信息')).toBeInTheDocument();
    expect(screen.getByText('规格列表')).toBeInTheDocument();

    // 检查父商品ID和名称（从props传入）
    expect(screen.getByDisplayValue('1')).toBeInTheDocument(); // 父商品ID
    expect(screen.getByDisplayValue('父商品')).toBeInTheDocument(); // 父商品名称

    // 检查分类ID - 现在应该显示正确的值（从mock的useQuery返回）
    // 注意：由于useQuery被mock，数据会立即返回，所以分类ID应该显示1,2,3而不是0
    expect(screen.getByDisplayValue('1')).toBeInTheDocument(); // 一级分类ID
    expect(screen.getByDisplayValue('2')).toBeInTheDocument(); // 二级分类ID
    expect(screen.getByDisplayValue('3')).toBeInTheDocument(); // 三级分类ID
    expect(screen.getByDisplayValue('实物产品')).toBeInTheDocument(); // 商品类型
  });

  it('应该显示初始的2个规格行', async () => {
    render(
      <Wrapper>
        <BatchSpecCreator {...defaultProps} />
      </Wrapper>
    );

    // 等待父商品数据加载完成
    await waitFor(() => {
      expect(screen.getByDisplayValue('1')).toBeInTheDocument(); // 父商品ID
    });

    const nameInputs = screen.getAllByPlaceholderText('例如：红色、64GB、大号');
    expect(nameInputs).toHaveLength(2);

    const priceInputs = screen.getAllByPlaceholderText('0.00');
    expect(priceInputs).toHaveLength(4); // 2个规格 * 2个价格字段

    const stockInputs = screen.getAllByPlaceholderText('0');
    expect(stockInputs).toHaveLength(2);
  });

  it('应该添加新的规格行', async () => {
    render(
      <Wrapper>
        <BatchSpecCreator {...defaultProps} />
      </Wrapper>
    );

    await waitForParentGoodsLoaded();

    const addButton = screen.getByText('添加规格');
    fireEvent.click(addButton);

    const nameInputs = screen.getAllByPlaceholderText('例如：红色、64GB、大号');
    expect(nameInputs).toHaveLength(3);
  });

  it('应该删除规格行', async () => {
    render(
      <Wrapper>
        <BatchSpecCreator {...defaultProps} />
      </Wrapper>
    );

    await waitForParentGoodsLoaded();

    const deleteButtons = screen.getAllByRole('button', { name: '' });
    fireEvent.click(deleteButtons[0]); // 删除第一个规格

    const nameInputs = screen.getAllByPlaceholderText('例如：红色、64GB、大号');
    expect(nameInputs).toHaveLength(1);
  });

  it('不能删除最后一个规格行', async () => {
    render(
      <Wrapper>
        <BatchSpecCreator {...defaultProps} />
      </Wrapper>
    );

    await waitForParentGoodsLoaded();

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

    // 尝试删除最后一个
    const remainingDeleteButton = screen.getByRole('button', { name: '' });
    fireEvent.click(remainingDeleteButton);

    // 应该仍然有一个规格
    const nameInputs = screen.getAllByPlaceholderText('例如：红色、64GB、大号');
    expect(nameInputs).toHaveLength(1);
    expect(toast.error).toHaveBeenCalledWith('至少需要保留一个规格');
  });

  it('应该更新规格字段', async () => {
    render(
      <Wrapper>
        <BatchSpecCreator {...defaultProps} />
      </Wrapper>
    );

    await waitForParentGoodsLoaded();

    const nameInput = screen.getAllByPlaceholderText('例如：红色、64GB、大号')[0];
    fireEvent.change(nameInput, { target: { value: '红色' } });
    expect(nameInput).toHaveValue('红色');

    const priceInput = screen.getAllByPlaceholderText('0.00')[0];
    fireEvent.change(priceInput, { target: { value: '99.99' } });
    expect(priceInput).toHaveValue(99.99);

    const stockInput = screen.getAllByPlaceholderText('0')[0];
    fireEvent.change(stockInput, { target: { value: '50' } });
    expect(stockInput).toHaveValue(50);
  });

  it('应该验证规格名称不能为空', async () => {
    render(
      <Wrapper>
        <BatchSpecCreator {...defaultProps} />
      </Wrapper>
    );

    await waitForParentGoodsLoaded();

    const submitButton = screen.getByText('创建 2 个子商品');
    fireEvent.click(submitButton);

    await waitFor(() => {
      expect(toast.error).toHaveBeenCalledWith('规格 1 的名称不能为空');
    });
  });

  it('应该验证规格名称不能重复', async () => {
    render(
      <Wrapper>
        <BatchSpecCreator {...defaultProps} />
      </Wrapper>
    );

    await waitForParentGoodsLoaded();

    // 设置两个规格为相同的名称
    const nameInputs = screen.getAllByPlaceholderText('例如：红色、64GB、大号');
    fireEvent.change(nameInputs[0], { target: { value: '红色' } });
    fireEvent.change(nameInputs[1], { target: { value: '红色' } });

    // 设置价格和库存
    const priceInputs = screen.getAllByPlaceholderText('0.00');
    fireEvent.change(priceInputs[0], { target: { value: '100' } });
    fireEvent.change(priceInputs[2], { target: { value: '200' } });

    const stockInputs = screen.getAllByPlaceholderText('0');
    fireEvent.change(stockInputs[0], { target: { value: '10' } });
    fireEvent.change(stockInputs[1], { target: { value: '20' } });

    const submitButton = screen.getByText('创建 2 个子商品');
    fireEvent.click(submitButton);

    await waitFor(() => {
      expect(toast.error).toHaveBeenCalledWith('规格名称不能重复');
    });
  });

  it('应该验证价格不能为负数', async () => {
    render(
      <Wrapper>
        <BatchSpecCreator {...defaultProps} />
      </Wrapper>
    );

    await waitForParentGoodsLoaded();

    // 设置规格名称
    const nameInputs = screen.getAllByPlaceholderText('例如：红色、64GB、大号');
    fireEvent.change(nameInputs[0], { target: { value: '红色' } });

    // 设置负价格
    const priceInputs = screen.getAllByPlaceholderText('0.00');
    fireEvent.change(priceInputs[0], { target: { value: '-100' } });

    const submitButton = screen.getByText('创建 2 个子商品');
    fireEvent.click(submitButton);

    await waitFor(() => {
      expect(toast.error).toHaveBeenCalledWith('规格 红色 的价格不能为负数');
    });
  });

  it('应该成功提交表单', async () => {
    render(
      <Wrapper>
        <BatchSpecCreator {...defaultProps} />
      </Wrapper>
    );

    await waitForParentGoodsLoaded();

    // 设置第一个规格
    const nameInputs = screen.getAllByPlaceholderText('例如：红色、64GB、大号');
    fireEvent.change(nameInputs[0], { target: { value: '红色' } });
    fireEvent.change(nameInputs[1], { target: { value: '蓝色' } });

    // 设置价格
    const priceInputs = screen.getAllByPlaceholderText('0.00');
    fireEvent.change(priceInputs[0], { target: { value: '100' } });
    fireEvent.change(priceInputs[2], { target: { value: '200' } });

    // 设置库存
    const stockInputs = screen.getAllByPlaceholderText('0');
    fireEvent.change(stockInputs[0], { target: { value: '10' } });
    fireEvent.change(stockInputs[1], { target: { value: '20' } });

    const submitButton = screen.getByText('创建 2 个子商品');
    fireEvent.click(submitButton);

    await waitFor(() => {
      expect(toast.success).toHaveBeenCalledWith('批量创建子商品成功');
      expect(defaultProps.onSuccess).toHaveBeenCalled();
    });
  });

  it('应该处理取消操作', async () => {
    render(
      <Wrapper>
        <BatchSpecCreator {...defaultProps} />
      </Wrapper>
    );

    await waitForParentGoodsLoaded();

    const cancelButton = screen.getByText('取消');
    fireEvent.click(cancelButton);

    expect(defaultProps.onCancel).toHaveBeenCalled();
  });

  it('应该显示租户信息', async () => {
    render(
      <Wrapper>
        <BatchSpecCreator {...defaultProps} tenantId={123} />
      </Wrapper>
    );

    await waitForParentGoodsLoaded();

    expect(screen.getByText('• 所有子商品将自动关联到父商品（spuId = 1）')).toBeInTheDocument();
  });
});