import { ref, computed, watch } from 'vue';
/**
 * 对应 React 的 useControlledState。
 * 总是优先使用 props.value，否则使用内部状态。
 *
 * @param defaultStateValue 默认值 (对应 React 的 defaultStateValue)
 * @param value 外部传入的值 (对应 React 的 value prop)
 * @returns [当前合并值, 状态更新函数]
 */
export default function useControlledState(defaultStateValue, value) {
  // 1. 内部状态 (对应 React 的 innerValue/useState)
  // 我们需要一个真正的 ref 来存储非受控模式下的值
  const innerValue = ref(typeof defaultStateValue === 'function' ? defaultStateValue() : defaultStateValue); // 强制类型断言，确保它是 T 类型
  // 2. 合并值 (对应 React 的 mergedValue)
  // 始终优先使用外部值 (value.value)，否则使用内部值 (innerValue.value)
  const mergedValue = computed(() => {
    // 检查外部 value 是否存在且不为 undefined
    if (value && value.value !== undefined) {
      return value.value;
    }
    return innerValue.value;
  });
  // 3. 状态更新函数 (对应 React 的 setInnerValue)
  // 在 Vue 中，这个函数只负责更新内部状态 innerValue
  const setInnerValue = updater => {
    // 处理函数式更新
    if (typeof updater === 'function') {
      innerValue.value = updater(innerValue.value);
    } else {
      innerValue.value = updater;
    }
  };
  /**
   * 4. 关键同步逻辑 (对应 React 中的 useLayoutEffect)
   *
   * 在 Vue 中，当外部 props.value 变化时，
   * 即使组件是非受控模式，我们也需要**在下一次渲染前**将内部状态
   * 强制同步为外部值，以确保当外部值突然从 undefined 变为某个值时，
   * 组件能正确切换到受控模式。
   *
   * 注意：在你的 `rc-slider` 的场景中，`triggerChange` 已经确保了在受控模式下
   * 不会去修改 `mergedValue`，但这里是为了更严谨地模拟 React 行为：
   * 只要外部 value 变化了，内部状态就跟它同步，但实际当前值由 mergedValue 决定。
   */
  watch(value || ref(undefined),
  // 监听外部传入的 value ref
  // 监听外部传入的 value ref
  nextValue => {
    // 只有在 nextValue 存在（即组件进入受控状态或受控值变化）时，才同步内部值。
    // 这确保了如果组件从外部接收到值，内部状态也同步，以防它切换回非受控状态。
    if (nextValue !== undefined) {
      innerValue.value = nextValue;
    }
  });
  return [mergedValue, setInnerValue];
}