<template>
  <div ref="rootEl" class="relative">
    <div
      class="combobox-input input input-sm flex flex-wrap items-center gap-1 w-full cursor-text"
      @click="focusInput"
    >
      <template v-if="multiple">
        <span
          v-for="item in currentValue"
          :key="item"
          class="badge badge-sm badge-neutral gap-1"
        >
          {{ item }}
          <button type="button" class="btn btn-ghost btn-xs btn-circle" @click.stop="toggle(item)">✕</button>
        </span>
      </template>
      <input
        ref="inputEl"
        v-model="query"
        type="text"
        :placeholder="placeholder"
        class="flex-1 min-w-[4rem]"
        @input="onInput"
        @focus="open = true"
      />
    </div>

    <ul
      v-if="open"
      class="absolute z-30 mt-1 w-full max-h-64 overflow-y-auto bg-base-100 rounded-box shadow ring-1 ring-base-300"
      @mousedown.prevent
    >
      <li v-if="loading" class="px-3 py-2 text-sm text-base-content/50 flex items-center gap-2">
        <span class="loading loading-spinner loading-xs"></span> Cargando…
      </li>
      <li v-else-if="options.length === 0" class="px-3 py-2 text-sm text-base-content/50">
        {{ multiple ? "Sin opciones" : "Sin sugerencias — sigue escribiendo" }}
      </li>
      <li v-for="opt in options" :key="opt.value">
        <label
          v-if="multiple"
          class="flex items-center gap-2 px-3 py-1.5 hover:bg-base-200 cursor-pointer"
        >
          <input
            type="checkbox"
            class="checkbox checkbox-xs"
            :checked="isSelected(opt.value)"
            @change="toggle(opt.value)"
          />
          <span class="flex-1 text-sm">
            {{ opt.value }}
            <span class="text-xs text-base-content/50">({{ opt.count }})</span>
          </span>
        </label>
        <button
          v-else
          type="button"
          class="flex w-full items-center justify-between gap-2 px-3 py-1.5 text-left text-sm hover:bg-base-200"
          @click="pick(opt.value)"
        >
          <span class="truncate">{{ opt.value }}</span>
          <span class="text-xs text-base-content/50 shrink-0">({{ opt.count }})</span>
        </button>
      </li>
    </ul>
  </div>
</template>

<script setup>
import { ref, watch, onMounted, onBeforeUnmount } from "vue";
import { cachedFetch } from "../../lib/adminCache";

const props = defineProps({
  field: { type: String, required: true },
  placeholder: { type: String, default: "Escribir…" },
  multiple: { type: Boolean, default: false },
  limit: { type: Number, default: 25 },
});

const modelValue = defineModel({ type: [String, Array], default: "" });

const rootEl = ref(null);
const inputEl = ref(null);
const query = ref("");
const open = ref(false);
const loading = ref(false);
const options = ref([]);

let fetchTimer = null;
let fetchVersion = 0;

const currentValue = () => {
  const v = modelValue.value;
  return Array.isArray(v) ? v : typeof v === "string" ? v : "";
};

function focusInput() {
  inputEl.value?.focus();
}

function isSelected(v) {
  return currentValue().includes(v);
}

function toggle(v) {
  const arr = [...currentValue()];
  const i = arr.indexOf(v);
  if (i >= 0) arr.splice(i, 1);
  else arr.push(v);
  modelValue.value = arr;
  query.value = "";
  scheduleFetch();
}

function pick(v) {
  modelValue.value = v;
  query.value = v;
  open.value = false;
}

function onInput() {
  if (!props.multiple) modelValue.value = query.value;
  scheduleFetch();
}

async function fetchOptions() {
  loading.value = true;
  const version = ++fetchVersion;
  const params = new URLSearchParams();
  params.set("field", props.field);
  params.set("limit", String(props.limit));
  if (query.value.trim().length >= 2) params.set("q", query.value.trim());
  try {
    const res = await cachedFetch(`/api/admin/voluntarios/distinct?${params.toString()}`, { ttl: 300 });
    const json = await res.json();
    if (version !== fetchVersion) return;
    options.value = json.success ? json.data : [];
  } catch {
    if (version === fetchVersion) options.value = [];
  } finally {
    if (version === fetchVersion) loading.value = false;
  }
}

function scheduleFetch() {
  clearTimeout(fetchTimer);
  fetchTimer = setTimeout(fetchOptions, 250);
}

watch(
  () => modelValue.value,
  (val) => {
    if (!props.multiple && query.value !== val) query.value = typeof val === "string" ? val : "";
  }
);

function onDocClick(e) {
  if (rootEl.value && !rootEl.value.contains(e.target)) open.value = false;
}

onMounted(() => {
  document.addEventListener("mousedown", onDocClick);
  scheduleFetch();
});

onBeforeUnmount(() => {
  document.removeEventListener("mousedown", onDocClick);
  clearTimeout(fetchTimer);
});
</script>

<style scoped>
.combobox-input {
  height: auto;
  min-height: 2rem;
  padding-top: 0.125rem;
  padding-bottom: 0.125rem;
}
</style>
