import { nextTick, ref, watch, type Ref } from "vue";

/**
 * 选择器字段临时存储数据的组合式函数
 * 用于管理选择器组件的临时值、选择文本和交互逻辑
 * 
 * @template T - 值的类型
 * @param 当前值的响应式引用
 * @param 更新值的回调函数
 * @param 关闭弹窗的回调函数
 * @param 事件发射器函数
 * @param 默认的新值
 * @param 是否立即更新值
 * @param 确认前的回调函数，返回true时取消确认
 * @param 弹窗显示状态的响应式引用
 */
export function usePickerFieldTempStorageData<T>(
  value: Ref<T>, 
  updateValue: (d: T) => void,
  closePopup: () => void,
  emit: (name: string, d?: any) => void,
  defaultNewValue: T,
  shouldUpdateValueImmediately: boolean,
  beforeConfirm?: ((value: T) => Promise<boolean>) | undefined,
  popupShow?: Ref<boolean>,
) {

  let tempSelectText = '';
  let tempLastSelectText = '';
  // 临时值的响应式引用，初始值为当前值或默认新值
  const tempValue = ref(value.value ?? defaultNewValue) as Ref<T>;
  // 显示的文本的响应式引用
  const selectText = ref('');

  /**
   * 当选择文本变化时的处理函数
   * @param 新的选择文本
   * @param 是否强制更新显示的选择文本
   */
  function onSelectTextChange(t: string, forceUpdate = false) {
    tempSelectText = t;
    emit('selectTextChange', t);
    if (forceUpdate)
      selectText.value = t;
  }

  /**
   * 取消选择的处理函数
   */
  function onCancel() {
    closePopup();
    emit('cancel');
    selectText.value = tempLastSelectText;
  }

  /**
   * 确认选择的处理函数
   */
  async function onConfirm() {
    closePopup();
    // 如果有确认前回调且返回true，则取消确认
    if (beforeConfirm && await beforeConfirm(tempValue.value))
      return;
    selectText.value = tempSelectText;
    updateValue(tempValue.value);
    emit('confirm', value.value);
  }

  watch(value, (v) => {
    tempValue.value = v;
  });
  watch(tempValue, (v) => {
    emit('tempValueChange', tempValue.value);
    if (shouldUpdateValueImmediately)
      updateValue(tempValue.value);
  });

  // 如果提供了弹窗显示状态引用，则监听其变化
  if (popupShow) {
    watch(popupShow, (v) => {
      if (v) {
        // 弹窗显示时，记录当前的选择文本作为上一次的选择文本
        nextTick(() => {
          tempLastSelectText = tempSelectText;
        });
      }
    })
  }

  return {
    onSelectTextChange, // 选择文本变化处理函数
    onCancel, // 取消处理函数
    onConfirm, // 确认处理函数
    selectText, // 显示的选择文本
    tempValue, // 临时值
  }
}