<template>
  <div :class="gridColumnClass">
    <!-- Input Menu -->
    <UInputMenu
      v-if="selectSchema.selectType === 'input'"
      :model-value="resolvedModelValue"
      :items="normalizedItems"
      :multiple="selectSchema.multiple"
      :searchable="selectSchema.searchable"
      :search-input="selectSchema.searchInput"
      :creatable="selectSchema.creatable"
      :placeholder="selectSchema.placeholder"
      :option-attribute="selectSchema.optionAttribute"
      :value-attribute="selectSchema.valueAttribute"
      :by="selectSchema.compareBy"
      v-bind="selectSchema.additionalProps"
      @update:model-value="onChange"
      @update:open="emitEvent('open', $event)"
      @update:search-term="handleSearchTerm"
      @create="emitEvent('create', $event)"
      :class="[gridColumnClass, 'cursor-pointer w-full']"
      size="xl"
      dir="rtl"
      color="primary"
      highlight
      :ui="{ trailing: 'hidden' }"
    >
      <!-- Forward Slots -->
      <template
        v-for="(_, slotName) in $slots"
        :key="slotName"
        v-slot:[slotName]="slotProps"
      >
        <slot :name="slotName" v-bind="slotProps" />
      </template>

      <template #empty>
        <slot name="empty">داده‌ای پیدا نشد</slot>
      </template>

      <template #loading>
        <slot name="loading">در حال بارگذاری...</slot>
      </template>
    </UInputMenu>

    <!-- Select Menu -->
    <USelectMenu
      v-if="selectSchema.selectType === 'select'"
      :model-value="resolvedModelValue"
      :items="normalizedItems"
      :multiple="selectSchema.multiple"
      :searchable="selectSchema.searchable"
      :search-input="selectSchema.searchInput"
      :creatable="selectSchema.creatable"
      :loading="isLoading"
      :placeholder="selectSchema.placeholder"
      :option-attribute="selectSchema.optionAttribute"
      :value-attribute="selectSchema.valueAttribute"
      :by="selectSchema.compareBy"
      v-bind="selectSchema.additionalProps"
      @update:model-value="onChange"
      @update:open="emitEvent('open', $event)"
      @update:search-term="handleSearchTerm"
      @create="emitEvent('create', $event)"
      :class="[gridColumnClass, 'cursor-pointer']"
      :ui="{ wrapper: 'w-full', base: 'w-full' }"
      dir="rtl"
      color="primary"
      size="xl"
      highlight
    >
      <!-- Forward Slots -->
      <template
        v-for="(_, slotName) in $slots"
        :key="slotName"
        v-slot:[slotName]="slotProps"
      >
        <slot :name="slotName" v-bind="slotProps" />
      </template>

      <template #empty>
        <slot name="empty">داده‌ای پیدا نشد</slot>
      </template>

      <template #loading>
        <slot name="loading">در حال بارگذاری...</slot>
      </template>
    </USelectMenu>
  </div>
</template>

<script setup>
import { ref, computed } from "vue";
import { debounce } from "lodash-es";

const props = defineProps({
  dropdownSchema: { type: Object, required: true },
});

const emit = defineEmits(["dropdownSelectEvents"]);
const { $http: httpService } = useNuxtApp();

const isLoading = ref(false);
const apiItems = ref([]);

/* ---------------- SCHEMA BASE ---------------- */
const selectSchema = computed(() => {
  const i = props.dropdownSchema || {};

  return {
    fieldId: i.key || i.name || i.id || null,
    modelValue: i.modelValue ?? i.value ?? null,
    selectType: i.selectType ?? "select",
    items: Array.isArray(i.items)
      ? i.items
      : Array.isArray(i.options)
      ? i.options
      : [],
    optionAttribute: i.optionAttribute ?? "label",
    valueAttribute: i.valueAttribute ?? "value",
    multiple:
      i.multiple === true || i.multi_select === 1 || i.multi_select === true,
    searchable: i.searchable ?? true,
    searchInput: i.searchInput ?? true,
    creatable: i.creatable ?? i.allowCreate ?? false,
    loading: i.loading ?? false,
    placeholder: i.placeholder || "لطفاً انتخاب کنید...",
    compareBy: i.compareBy,
    additionalProps: i.additionalProps || i.extraProps || {},
    columnSpan: resolveColSpan(i),
    mode: i.mode || "default",
    apiConfig: i.apiConfig || {},
  };
});

/* ---------------- GRID ---------------- */
function resolveColSpan(input) {
  let span = 12;
  if (input.colSpan) span = input.colSpan;
  if (input.colClass?.includes("col-")) {
    const m = input.colClass.match(/col-(\d+)/);
    if (m) span = Number(m[1]);
  }
  return Math.min(12, Math.max(1, span));
}

const gridColumnClass = computed(
  () => `col-span-${selectSchema.value.columnSpan}`
);

/* ---------------- NORMALIZE ITEMS ---------------- */
const normalizedItems = computed(() => {
  const { optionAttribute, valueAttribute, mode } = selectSchema.value;
  const sourceItems =
    mode === "api" ? apiItems.value : selectSchema.value.items;

  return sourceItems.map((item) => {
    if (typeof item !== "object") {
      return {
        [optionAttribute]: String(item),
        [valueAttribute]: item,
        raw: item,
      };
    }
    return { ...item, raw: item };
  });
});

/* ---------------- RESOLVED MODEL VALUE ---------------- */
const resolvedModelValue = computed(() => {
  const { modelValue, multiple } = selectSchema.value;

  if (multiple && Array.isArray(modelValue)) {
    return modelValue.map(resolveSingleValue).filter(Boolean);
  }
  return resolveSingleValue(modelValue);
});

function resolveSingleValue(val) {
  if (val === null || val === undefined) return null;
  if (typeof val === "object") return val;

  let item = normalizedItems.value.find(
    (i) => i?.[selectSchema.value.valueAttribute] === val
  );

  // اگر پیدا نشد و mode API است → آیتم موقت اضافه کن
  if (!item && selectSchema.value.mode === "api") {
    item = {
      [selectSchema.value.optionAttribute]: val,
      [selectSchema.value.valueAttribute]: val,
      raw: val,
      __temp: true,
    };
    apiItems.value.push(item);
  }

  return item || null;
}

/* ---------------- EMIT HANDLERS ---------------- */
function emitEvent(action, payload) {
  emit("dropdownSelectEvents", {
    action,
    payload,
    fieldId: selectSchema.value.fieldId,
    timestamp: Date.now(),
  });
}

function onChange(val) {
  // اضافه کردن به apiItems اگر وجود ندارد
  if (selectSchema.value.mode === "api") {
    const values = Array.isArray(val) ? val : [val];
    values.forEach((v) => {
      const valueKey =
        typeof v === "object" ? v[selectSchema.value.valueAttribute] : v;
      if (
        !apiItems.value.find(
          (i) => i[selectSchema.value.valueAttribute] === valueKey
        )
      ) {
        apiItems.value.push(
          typeof v === "object"
            ? v
            : {
                [selectSchema.value.optionAttribute]: valueKey,
                [selectSchema.value.valueAttribute]: valueKey,
                raw: v,
              }
        );
      }
    });
  }
  props.dropdownSchema.modelValue = val;
  emitEvent("change", val);
}
watch(
  () => normalizedItems.value.length,
  (len) => {
    if (!len) return;

    const { multiple, modelValue, selectType } = selectSchema.value;
    if (selectType !== "select") return;

    if (
      (multiple && Array.isArray(modelValue) && modelValue.length) ||
      (!multiple && modelValue != null)
    )
      return;

    onChange(multiple ? [normalizedItems.value[0]] : normalizedItems.value[0]);
  },
  { immediate: true }
);
/* ---------------- SEARCH WITH DEBOUNCE ---------------- */
const debouncedFetch = debounce(
  async (searchText, url, crud = "GET", payload = "") => {
    if (!searchText) {
      apiItems.value = [];
      isLoading.value = false;
      return;
    }

    const { searchField = "name" } = selectSchema.value.apiConfig;
    url = url.replace("{{filter}}", searchText);
    payload = payload?.replace("{{filter}}", searchText);

    isLoading.value = true;

    if (crud === "GET") {
      httpService
        .getRequest(url)
        .then((res) => {
          const mapped = res
            .filter((item) =>
              String(item?.[searchField] || "")
                .toLowerCase()
                .includes(searchText.toLowerCase())
            )
            .map((item) => ({
              [selectSchema.value.optionAttribute]: item[searchField],
              [selectSchema.value.valueAttribute]: item.id ?? item[searchField],
              raw: item,
            }));

          // جایگزینی آیتم موقت با آیتم واقعی
          apiItems.value = apiItems.value.map((existing) =>
            existing.__temp
              ? mapped.find(
                  (m) =>
                    m[selectSchema.value.valueAttribute] ===
                    existing[selectSchema.value.valueAttribute]
                ) || existing
              : existing
          );

          // اضافه کردن آیتم‌های جدید
          mapped.forEach((m) => {
            if (
              !apiItems.value.find(
                (i) =>
                  i[selectSchema.value.valueAttribute] ===
                  m[selectSchema.value.valueAttribute]
              )
            ) {
              apiItems.value.push(m);
            }
          });
        })
        .catch((error) =>
          console.error("Remote search API error:", crud, error)
        )
        .finally(() => (isLoading.value = false));
    } else if (crud === "POST") {
      let payload_obj = payload ? JSON.parse(payload) : {};
      httpService
        .postRequest(url, payload_obj)
        .then((res) => {
          apiItems.value = res.data;
        })
        .catch((error) =>
          console.error("Remote search API error:", crud, error)
        )
        .finally(() => (isLoading.value = false));
    }
  },
  300
);

function handleSearchTerm(searchText) {
  emitEvent("search", searchText);

  const { mode, apiConfig } = selectSchema.value;
  if (mode === "api" && apiConfig?.url) {
    debouncedFetch(
      searchText,
      apiConfig.url,
      apiConfig.crud,
      apiConfig.payload
    );
  }
}
</script>
