import type { WatchStopHandle } from "vue";
import { ref, shallowRef } from "vue";

type EffectFn<T> = (newValue?: T, oldValue?: T) => void;

interface IStateConfig<T = any> {
  shallow?: boolean;

  effect?: EffectFn<T>;
  immediate?: boolean;
  deep?: boolean;
}

const defaultConfig: IStateConfig = {
  shallow: false,
};

export function useState<T>(initialValue: T, config = defaultConfig) {
  const { shallow, effect, immediate, deep = false } = config;
  const state = shallow ? shallowRef<T>(initialValue) : ref<T>(initialValue);
  const onUpdateState = (newValue: T) => state.value = newValue;

  let stop: WatchStopHandle | null = null;

  if (effect) {
    stop = watch(state, (newValue, oldValue) => {
      effect(newValue, oldValue);
    }, {
      immediate,
      deep,
    });
  }

  onUnmounted(() => stop && stop());

  return [state, onUpdateState] as const;
};
