import { computed, ref } from 'vue';

export interface PickerSelectionOptions {
  multiple: boolean;
}

export function usePickerSelection(options: () => PickerSelectionOptions) {
  const multiSet = ref<Set<string>>(new Set());
  const singleId = ref<string | null>(null);

  const multiple = computed(() => options().multiple);

  function has(userId: string): boolean {
    if (multiple.value) return multiSet.value.has(userId);
    return singleId.value === userId;
  }

  function toggle(userId: string) {
    if (multiple.value) {
      if (multiSet.value.has(userId)) multiSet.value.delete(userId);
      else multiSet.value.add(userId);
      multiSet.value = new Set(multiSet.value);
    } else {
      singleId.value = singleId.value === userId ? null : userId;
    }
  }

  function addMany(userIds: readonly string[]) {
    if (!multiple.value) {
      singleId.value = userIds[0] ?? singleId.value;
      return;
    }
    for (const id of userIds) multiSet.value.add(id);
    multiSet.value = new Set(multiSet.value);
  }

  function removeMany(userIds: readonly string[]) {
    if (!multiple.value) {
      if (singleId.value && userIds.includes(singleId.value)) singleId.value = null;
      return;
    }
    for (const id of userIds) multiSet.value.delete(id);
    multiSet.value = new Set(multiSet.value);
  }

  function clear(preserveIds?: readonly string[]) {
    const keep = new Set((preserveIds ?? []).map(String));
    if (multiple.value) {
      const next = new Set<string>();
      for (const id of multiSet.value) {
        if (keep.has(id)) next.add(id);
      }
      multiSet.value = next;
    } else if (singleId.value && !keep.has(singleId.value)) singleId.value = null;
  }

  function reset(initial: string | string[] | null | undefined) {
    if (multiple.value) {
      const ids = Array.isArray(initial) ? initial.map(String) : [];
      multiSet.value = new Set(ids);
    } else {
      singleId.value = typeof initial === 'string' ? initial : null;
    }
  }

  const selectedIds = computed<string[]>(() => {
    if (multiple.value) return [...multiSet.value];
    return singleId.value ? [singleId.value] : [];
  });

  const size = computed(() => selectedIds.value.length);

  function commit(): string | string[] | null {
    if (multiple.value) return [...multiSet.value];
    return singleId.value;
  }

  return {
    selectedIds,
    size,
    has,
    toggle,
    addMany,
    removeMany,
    clear,
    reset,
    commit
  };
}
