<template>
  <div class="w-full">
    <Combobox v-model="selected" :disabled="disabled">
      <ComboboxLabel>{{ title }}</ComboboxLabel>
      <div class="relative mt-1">
        <ComboboxInput
          class="rounded-md shadow-xs relative block w-full px-3 py-2 border border-gray-300 focus:border-primary placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-hidden focus:ring-0 focus:z-10 sm:text-sm resize-none"
          :displayValue="() => chosen?.title ?? ''"
          @input="query = $event.target.value"
        />
        <ComboboxButton class="absolute inset-y-0 right-0 flex items-center pr-2">
          <ChevronUpDownIcon class="h-5 w-5 text-gray-400" aria-hidden="true" />
        </ComboboxButton>
        <TransitionRoot
          leave="transition ease-in duration-100"
          leaveFrom="opacity-100"
          leaveTo="opacity-0"
          @after-leave="query = ''"
        >
          <ComboboxOptions
            class="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-md ring-1 ring-black/5 focus:outline-hidden sm:text-sm z-10"
          >
            <ComboboxOption v-if="loading || deferingSearch" as="template" disabled>
              <li class="flex flex-row gap-2 text-text relative cursor-default select-none py-2 pl-3 pr-4">
                <Spinner />
                <span class="font-normal block truncate">suche</span>
              </li>
            </ComboboxOption>
            <ComboboxOption v-else-if="filtered.length === 0 && query == ''" as="template" disabled>
              <li class="text-text relative cursor-default select-none py-2 pl-3 pr-4">
                <span class="font-normal block truncate">tippe, um zu suchen...</span>
              </li>
            </ComboboxOption>
            <ComboboxOption v-else-if="filtered.length === 0" as="template" disabled>
              <li class="text-text relative cursor-default select-none py-2 pl-3 pr-4">
                <span class="font-normal block truncate">Keine Auswahl gefunden.</span>
              </li>
            </ComboboxOption>

            <ComboboxOption
              v-if="!(loading || deferingSearch)"
              v-for="inspectionPlan in filtered"
              as="template"
              :key="inspectionPlan.id"
              :value="inspectionPlan.id"
              v-slot="{ selected, active }"
            >
              <li
                class="relative cursor-default select-none py-2 pl-10 pr-4"
                :class="{
                  'bg-primary text-white': active,
                  'text-gray-900': !active,
                }"
              >
                <span class="block truncate" :class="{ 'font-medium': selected, 'font-normal': !selected }">
                  {{ inspectionPlan.title }}
                </span>
                <span
                  v-if="selected"
                  class="absolute inset-y-0 left-0 flex items-center pl-3"
                  :class="{ 'text-white': active, 'text-primary': !active }"
                >
                  <CheckIcon class="h-5 w-5" aria-hidden="true" />
                </span>
              </li>
            </ComboboxOption>
          </ComboboxOptions>
        </TransitionRoot>
      </div>
    </Combobox>
  </div>
</template>

<script setup lang="ts">
import { defineComponent, type PropType } from "vue";
import { mapState, mapActions } from "pinia";
import {
  Combobox,
  ComboboxLabel,
  ComboboxInput,
  ComboboxButton,
  ComboboxOptions,
  ComboboxOption,
  TransitionRoot,
} from "@headlessui/vue";
import { CheckIcon, ChevronUpDownIcon } from "@heroicons/vue/20/solid";
import Spinner from "../Spinner.vue";
import { useInspectionPlanStore } from "@/stores/admin/unit/inspectionPlan/inspectionPlan";
import type { InspectionPlanViewModel } from "@/viewmodels/admin/unit/inspectionPlan/inspectionPlan.models";
</script>

<script lang="ts">
export default defineComponent({
  props: {
    modelValue: {
      type: String,
      default: "",
    },
    title: String,
    disabled: {
      type: Boolean,
      default: false,
    },
    type: {
      type: String as PropType<"vehicle" | "equipment">,
      default: "equipment",
    },
  },
  emits: ["update:model-value"],
  watch: {
    modelValue() {
      if (this.initialLoaded) return;
      this.initialLoaded = true;
      this.loadInspectionPlanInitial();
    },
    query() {
      this.deferingSearch = true;
      clearTimeout(this.timer);
      this.timer = setTimeout(() => {
        this.deferingSearch = false;
        this.search();
      }, 600);
    },
  },
  data() {
    return {
      initialLoaded: false as boolean,
      loading: false as boolean,
      deferingSearch: false as boolean,
      timer: undefined as any,
      query: "" as string,
      filtered: [] as Array<InspectionPlanViewModel>,
      chosen: undefined as undefined | InspectionPlanViewModel,
    };
  },
  computed: {
    selected: {
      get() {
        return this.modelValue;
      },
      set(val: string) {
        this.chosen = this.getInspectionPlanFromSearch(val);
        this.$emit("update:model-value", val);
      },
    },
  },
  mounted() {
    this.loadInspectionPlanInitial();
  },
  methods: {
    ...mapActions(useInspectionPlanStore, ["searchInspectionPlans", "fetchInspectionPlanById"]),
    search() {
      this.filtered = [];
      if (this.query == "") return;
      this.loading = true;
      this.searchInspectionPlans(this.query)
        .then((res) => {
          this.filtered = res.data;
        })
        .catch((err) => {})
        .finally(() => {
          this.loading = false;
        });
    },
    getInspectionPlanFromSearch(id: string) {
      return this.filtered.find((f) => f.id == id);
    },
    loadInspectionPlanInitial() {
      if (this.modelValue == "") return;
      this.fetchInspectionPlanById(this.modelValue)
        .then((res) => {
          this.chosen = res.data;
        })
        .catch(() => {});
    },
  },
});
</script>
