<template>
  <div>
    <div
      class="field has-addons"
      :id="$id()"
    >
      <div :class="['control has-icons-left has-icons-right is-expanded', isLoading && 'is-loading']">
        <div
          :class="['dropdown', pos, { 'is-active': focused }]"
          style="width: 100%"
        >
          <div
            class="dropdown-trigger"
            style="width: 100%"
          >
            <input
              :class="[
                'input',
                {
                  'has-text-dark': disabled,
                },
              ]"
              :disabled="disabled"
              type="text"
              @focus="setFocus"
              @blur="lostFocus"
              @keyup.enter="pressEnter"
              @keyup.esc="lostFocus"
              @input="debouncedGetSuggestions($event.target.value)"
              v-model="value"
              :placeholder="placeholder"
            />
            <span class="icon is-left">
              <Icon
                name="material-symbols:search"
                :size="20"
              />
            </span>
            <span class="icon is-right">
              <Icon
                name="material-symbols:keyboard-arrow-down-rounded"
                :size="20"
              />
            </span>
          </div>
          <div
            class="dropdown-menu"
            style="min-width: 100%"
            role="menu"
          >
            <div
              class="dropdown-content"
              style="min-width: 100%"
            >
              <ScrollBox
                v-if="suggestions.length > 0"
                v-bind="{
                  data: suggestions,
                  name: field,
                  fontsize: 14,
                  maxHeight: '200px',
                }"
                @selected="choose"
              />
              <p
                v-else
                class="has-text-grey px-2 py-1"
              >
                Không có giá trị thoả mãn
              </p>
            </div>
          </div>
        </div>
      </div>
      <div
        v-if="clearable && value"
        class="control"
      >
        <button
          class="button is-light"
          @click="clearValue"
          style="height: 100%"
          type="button"
        >
          <span class="icon">
            <Icon
              name="material-symbols:close-rounded"
              :size="16"
            />
          </span>
        </button>
      </div>
      <div
        v-if="viewaddon"
        class="control"
      >
        <button
          class="button is-primary is-light"
          @click="viewInfo"
          style="height: 100%"
          type="button"
        >
          <span class="icon">
            <Icon
              name="material-symbols:visibility-rounded"
              :size="20"
            />
          </span>
        </button>
      </div>
      <div
        v-if="addon"
        class="control"
      >
        <button
          class="button is-success is-light"
          @click="addNew"
          style="height: 100%"
          type="button"
        >
          <span class="icon">
            <Icon
              name="material-symbols:add-rounded"
              :size="18"
            />
          </span>
        </button>
      </div>
    </div>
    <Modal
      v-if="showmodal"
      v-bind="showmodal"
      @dataevent="dataevent"
      @close="showmodal = undefined"
    />
  </div>
</template>

<script setup>
import ScrollBox from "@/components/datatable/ScrollBox.vue";
import { debounce } from "es-toolkit";

const props = defineProps({
  api: String,
  field: String,
  column: Array,
  first: Boolean,
  optionid: String,
  filter: Object,
  addon: Object,
  viewaddon: Object,
  position: String,
  disabled: Boolean,
  vdata: Array,
  clearable: Boolean,
  placeholder: String,
  searchfield: Array,
});

const { $copy, $dialog, $empty, $find, $findapi, $findIndex, $getdata, $id, $nonAccent, $store } = useNuxtApp();
const emit = defineEmits(["option", "modalevent"]);
const suggestions = ref([]);
const isLoading = ref(false);
const value = ref();
const selected = ref();
const showmodal = ref();
const params = ref(props.api && $findapi(props.api).params);
const orgdata = ref();
const focused = ref(false);
const pos = computed(() => {
  switch (props.position) {
    case "is-top-left":
      return "is-up is-left";
    case "is-top-right":
      return "is-up is-right";
    case "is-bottom-left":
      return "is-right";
    case "is-bottom-right":
      return "is-right";
  }
});

if (props.vdata) {
  orgdata.value = props.vdata;
  orgdata.value.forEach((v) => (v.search = $nonAccent(v[props.field])));
}
if (props.first) {
  suggestions.value = orgdata.value ? $copy(orgdata.value) : await getData();
  if (props.optionid) {
    let f = {};
    f[props.field] = props.optionid;
    if (props.optionid > 0) f = { id: props.optionid };
    selected.value = $find(suggestions.value, f);
    if (selected.value && props.vdata) {
      value.value = selected.value[props.field];
    }
  }
} else if (props.optionid) {
  selected.value = await $getdata(props.api, {
    filter: { id: props.optionid },
    first: true,
  });
}
if (selected.value) doSelect(selected.value);

watch(
  () => props.optionid,
  () => {
    if (props.optionid) selected.value = $find(suggestions.value, { id: props.optionid });
    if (selected.value) doSelect(selected.value);
    else value.value = undefined;
  },
);

watch(
  () => props.filter,
  async () => {
    suggestions.value = await getData();
  },
);

watch(
  () => props.vdata,
  (newVal) => {
    if (newVal) {
      orgdata.value = $copy(props.vdata);
      orgdata.value.forEach((v) => (v.search = $nonAccent(v[props.field])));
      suggestions.value = $copy(orgdata.value);
      selected.value = undefined;
      value.value = undefined;
      if (props.optionid) selected.value = $find(suggestions.value, { id: props.optionid });
      if (selected.value) doSelect(selected.value);
    }
  },
);

function choose(v) {
  focused.value = false;
  doSelect(v);
}

function setFocus() {
  focused.value = true;
}

function lostFocus() {
  setTimeout(() => {
    if (focused.value) focused.value = false;
  }, 200);
}

function pressEnter() {
  if (suggestions.value.length === 0) return;
  choose(suggestions.value[0]);
}

function doSelect(option) {
  if ($empty(option)) return;
  emit("option", option);
  emit("modalevent", { name: "option", data: option });
  selected.value = option;
  value.value = selected.value[props.field];
}

function clearValue() {
  value.value = undefined;
  selected.value = undefined;
  emit("option", null);
  emit("modalevent", { name: "option", data: null });
}

watch(value, (newVal) => {
  if (newVal === "") clearValue();
});

function findObject(val) {
  const rows = $copy(orgdata.value);
  if ($empty(val)) suggestions.value = rows;
  else {
    const text = $nonAccent(val);
    suggestions.value = rows.filter((v) => v.search.toLowerCase().indexOf(text.toLowerCase()) >= 0);
  }
}

async function getData() {
  isLoading.value = true;
  params.value.filter = props.filter;
  const data = await $getdata(props.api, { params: params.value });
  isLoading.value = false;
  return data;
}

async function getSuggestions(val) {
  if (props.vdata) return findObject(val);
  const text = val ? val.toLowerCase() : "";
  const filter_or = {};

  // Sử dụng searchfield nếu có, nếu không thì dùng column
  const fieldsToSearch = props.searchfield || props.column;

  fieldsToSearch.forEach((v) => {
    filter_or[`${v}__icontains`] = text;
  });
  params.value.filter_or = filter_or;
  if (props.filter) params.value.filter = $copy(props.filter);
  isLoading.value = true;
  suggestions.value = await $getdata(props.api, { params: params.value });
  isLoading.value = false;
}

const debouncedGetSuggestions = debounce(getSuggestions, 200);

function addNew() {
  showmodal.value = props.addon;
}

function dataevent(v) {
  console.log("SearchBox received dataevent:", v); // Debug log

  if (!v || !v.id) {
    console.error("Invalid data received in SearchBox:", v);
    return;
  }

  // Tìm và cập nhật trong danh sách
  const idx = $findIndex(suggestions.value, { id: v.id });
  if (idx < 0) {
    // Nếu chưa có trong danh sách, thêm vào đầu
    suggestions.value.unshift(v);
    console.log("Added new item to data:", v);
  } else {
    // Nếu đã có, cập nhật
    suggestions.value[idx] = v;
    console.log("Updated existing item in data:", v);
  }

  // Cập nhật orgdata nếu có
  if (orgdata.value) {
    let orgIdx = $findIndex(orgdata.value, { id: v.id });
    if (orgIdx < 0) {
      orgdata.value.unshift(v);
      // Thêm search field cho orgdata
      if (props.field && v[props.field]) {
        v.search = $nonAccent(v[props.field]);
      }
    } else {
      orgdata.value[orgIdx] = v;
      if (props.field && v[props.field]) {
        orgdata.value[orgIdx].search = $nonAccent(v[props.field]);
      }
    }
  }

  // **Tự động select item vừa tạo/cập nhật**
  doSelect(v);

  // Đóng modal
  showmodal.value = undefined;
}

function viewInfo() {
  if (!selected.value)
    return $dialog(
      $store.lang === "vi" ? "Vui lòng lựa chọn trước khi xem thông tin." : "Please select before viewing",
      $store.lang === "vi" ? "Thông báo" : "Notice",
    );
  showmodal.value = {
    ...props.viewaddon,
    vbind: { row: selected.value },
  };
}
</script>
<style scoped>
.control.is-loading::after {
  inset-inline-end: 2.75em;
}

.field:not(:last-child) {
  margin-bottom: 0;
}

.button.is-success {
  &.is-light {
    --bulma-button-background-l: 89%;
  }

  &:hover,
  &.is-hovered {
    --bulma-button-background-l-delta: -10%;
  }
}
</style>
