/**
 * Radix UI Select组件的测试工具函数
 * 用于在测试中处理Radix UI Select组件的交互
 *
 * 注意：这个文件应该只在测试环境中使用，不要在生产代码中导入
 */

import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

/**
 * 查找Radix UI Select组件的隐藏select元素
 * Radix UI Select组件在DOM中会创建一个隐藏的select元素用于表单提交
 * 这个函数帮助我们在测试中找到这个隐藏的select元素
 *
 * @param selectButton - Select组件的触发按钮元素
 * @returns 隐藏的select元素，如果找不到则返回null
 */
export function findHiddenSelectElement(selectButton: HTMLElement): HTMLSelectElement | null {
  // 在按钮的父元素或附近查找隐藏的select
  // 优先在按钮附近查找，如果找不到再全局查找
  const hiddenSelect = selectButton.closest('div')?.querySelector('select[data-radix-select-viewport]') ||
                      selectButton.closest('div')?.querySelector('select[aria-hidden="true"]') ||
                      selectButton.closest('div')?.querySelector('select[hidden]') ||
                      document.querySelector('select[data-radix-select-viewport]') ||
                      document.querySelector('select[aria-hidden="true"]') ||
                      document.querySelector('select[hidden]');

  return hiddenSelect as HTMLSelectElement | null;
}

/**
 * 选择Radix UI Select组件的选项
 * 这个函数封装了查找隐藏select元素并选择选项的逻辑
 *
 * @param selectButton - Select组件的触发按钮元素
 * @param optionValue - 要选择的选项值
 * @returns 如果成功选择了选项返回true，否则返回false
 */
export async function selectRadixOption(selectButton: HTMLElement, optionValue: string): Promise<boolean> {
  const hiddenSelect = findHiddenSelectElement(selectButton);

  if (hiddenSelect) {
    // 如果有隐藏的select，使用userEvent.selectOptions
    await userEvent.selectOptions(hiddenSelect, optionValue);
    return true;
  }

  return false;
}

/**
 * 通过test ID查找并选择Radix UI Select组件的选项
 * 这个函数封装了完整的查找、点击、选择流程
 *
 * @param testId - Select组件的test ID
 * @param optionValue - 要选择的选项值
 * @param user - userEvent实例（可选）
 * @returns 如果成功选择了选项返回true，否则返回false
 */
export async function selectRadixOptionByTestId(
  testId: string,
  optionValue: string,
  user = userEvent
): Promise<boolean> {
  // 获取Select组件的触发按钮
  const selectButton = screen.getByTestId(testId);

  // 点击打开下拉菜单
  await user.click(selectButton);

  // 查找并选择选项
  return await selectRadixOption(selectButton, optionValue);
}

/**
 * 等待Radix UI Select组件启用
 * 有些Select组件在数据加载完成前是禁用的
 *
 * @param testId - Select组件的test ID
 * @param timeout - 超时时间（毫秒），默认5000ms
 */
export async function waitForRadixSelectEnabled(testId: string, timeout = 5000): Promise<void> {
  const startTime = Date.now();

  while (Date.now() - startTime < timeout) {
    try {
      const selectElement = screen.getByTestId(testId);
      if (!selectElement.hasAttribute('disabled') && selectElement.getAttribute('aria-disabled') !== 'true') {
        return;
      }
    } catch (error) {
      // 元素可能还没渲染出来，继续等待
    }

    // 等待一小段时间再检查
    await new Promise(resolve => setTimeout(resolve, 100));
  }

  throw new Error(`Radix Select with testId "${testId}" did not become enabled within ${timeout}ms`);
}

/**
 * 完整的Radix UI Select选择流程
 * 包含等待启用、点击打开、选择选项的完整流程
 *
 * @param testId - Select组件的test ID
 * @param optionValue - 要选择的选项值
 * @param options - 配置选项
 * @param options.useFireEvent - 是否使用fireEvent而不是userEvent.click（默认为false）
 * @param options.user - userEvent实例（可选）
 */
export async function completeRadixSelectFlow(
  testId: string,
  optionValue: string,
  options: {
    useFireEvent?: boolean;
    user?: typeof userEvent;
  } = {}
): Promise<void> {
  const { useFireEvent = false, user = userEvent } = options;

  // 1. 等待Select组件启用
  await waitForRadixSelectEnabled(testId);

  // 2. 获取Select按钮
  const selectButton = screen.getByTestId(testId);

  // 3. 点击打开下拉菜单
  if (useFireEvent) {
    // 有些Radix UI Select组件需要使用fireEvent而不是userEvent
    const { fireEvent } = await import('@testing-library/react');
    fireEvent.click(selectButton);
  } else {
    await user.click(selectButton);
  }

  // 4. 查找并选择选项
  const success = await selectRadixOption(selectButton, optionValue);

  if (!success) {
    // 如果通过隐藏select找不到，尝试直接点击选项文本
    // 注意：这里假设选项文本已经在DOM中渲染
    throw new Error(`Failed to select option "${optionValue}" for Radix Select with testId "${testId}". Make sure the dropdown is open and options are rendered.`);
  }
}