<script setup>
import { ref, watch, watchEffect, nextTick, computed } from "vue";
import { VTextField } from "vuetify/components/VTextField";
import { VueDatePicker as Datepicker } from "@vuepic/vue-datepicker";
import "@vuepic/vue-datepicker/dist/main.css";
import { isArray, isString } from "lodash-es";
import { Datetime } from "../../utils/datetime";
import { useRules } from "../../composables/utils/validation";
import { th, enUS } from "date-fns/locale";
const props = defineProps({
  locale: { type: String, required: false, default: "TH" },
  format: { type: String, required: false, default: "shortDate" },
  modelValue: { type: [String, null], required: false },
  holiday: { type: null, required: false },
  minDate: { type: [Date, String], required: false },
  maxDate: { type: [Date, String], required: false },
  pickerOnly: { type: Boolean, required: false, default: false },
  flow: { type: Array, required: false, default: () => [] },
  rules: { type: null, required: false },
  defaultDate: { type: [Boolean, String], required: false, default: false }
});
const emit = defineEmits(["update:modelValue"]);
const computedRules = computed(() => {
  if (props.rules && isArray(props.rules)) {
    const ruleConfig = {
      singleModifier: ["DateFuture", "DateHappen"],
      twoPartModifier: ["DateAfter", "DateBefore", "DateEqual"]
    };
    const ruleMapping = {
      "DateFuture": useRules().DateFuture,
      "DateHappen": useRules().DateHappen,
      "DateAfter": useRules().DateAfter,
      "DateBefore": useRules().DatetimeFuture,
      "DateEqual": useRules().DateEqual
    };
    const applyRule = (ruleName, modifier) => {
      if (props.readonly) return true;
      const ruleFunc = ruleMapping[ruleName](...Object.values(modifier));
      return ruleFunc(selectedDate.value);
    };
    return props.rules.map((rule) => {
      if (isString(rule)) {
        const ruleParts = rule.split("#");
        const baseRule = ruleParts[0];
        if (ruleConfig.singleModifier.includes(baseRule)) {
          const modifiers = ruleParts.slice(1).join("#").trim() || void 0;
          return applyRule(baseRule, { modifiers });
        }
        if (ruleConfig.twoPartModifier.includes(baseRule)) {
          const [modifier1, ...modifierRest] = ruleParts.slice(1);
          const combinedModifier = modifierRest.join("#") || void 0;
          return applyRule(baseRule, { modifier1, combinedModifier });
        }
      }
      return rule;
    });
  } else {
    return props.rules;
  }
});
const selectedDate = ref(null);
const displayedDate = ref(null);
const datepickerLocale = computed(() => props.locale === "TH" ? th : enUS);
const datepickerFlow = computed(() => props.flow.length ? { steps: props.flow, partial: true } : void 0);
const isMenuOpen = ref(false);
const isTextFieldFocused = ref(false);
const hasTextFieldInput = ref(false);
function handleTextFieldFocus(event) {
  isTextFieldFocused.value = true;
  nextTick(() => {
    event.target.select();
  });
}
function handleTextFieldInput() {
  if (!hasTextFieldInput.value) {
    hasTextFieldInput.value = true;
    isMenuOpen.value = false;
  }
}
function handleTextFieldBlur() {
  if (hasTextFieldInput.value) {
    updateDate(displayedDate.value);
    hasTextFieldInput.value = false;
  }
  isTextFieldFocused.value = false;
}
function handleTextFieldEnterKey() {
  handleTextFieldBlur();
}
function updateDatePicker(dateString) {
  isMenuOpen.value = false;
  updateDate(dateString);
}
function updateDate(dateString) {
  const dateTime = Datetime().fromString(dateString, void 0, props.locale);
  if (!dateTime.luxonDateTime.isValid) {
    displayedDate.value = null;
    selectedDate.value = null;
  } else {
    selectedDate.value = dateTime.toFormat("yyyy-MM-dd", "EN");
    displayedDate.value = selectedDate.value;
  }
  if (!isTextFieldFocused.value) displayedDate.value = formatDate(displayedDate.value);
}
function formatDate(dateString) {
  if (!dateString) return null;
  const dateTime = Datetime().fromString(dateString, void 0, props.locale);
  return dateTime.toFormat(props.format, props.locale);
}
function handleTextFieldClear() {
  resetDatePicker();
}
function resetDatePicker() {
  selectedDate.value = null;
  displayedDate.value = null;
}
watchEffect(() => {
  if (!isTextFieldFocused.value && selectedDate.value) {
    const dateTime = Datetime().fromString(selectedDate.value, void 0, props.locale);
    displayedDate.value = dateTime.toFormat(props.format, props.locale);
  } else {
    displayedDate.value = selectedDate.value;
  }
});
watch(selectedDate, (newValue) => {
  emit("update:modelValue", newValue);
});
watch(() => props.modelValue, (newValue, oldValue) => {
  if (!oldValue && !newValue && props.defaultDate) {
    if (!oldValue && !newValue && props.defaultDate) {
      let defaultDate = null;
      if (props.defaultDate === true) {
        defaultDate = Datetime().now().toFormat("yyyy-MM-dd", "EN");
      } else if (typeof props.defaultDate === "string" && /^[+-]?\d+$/.test(props.defaultDate.trim())) {
        defaultDate = Datetime().now().luxonDateTime.plus({ days: Number(props.defaultDate) }).toFormat("yyyy-MM-dd");
      } else {
        const dateTime = Datetime().fromString(props.defaultDate);
        if (dateTime.luxonDateTime.isValid) defaultDate = dateTime.toFormat("yyyy-MM-dd");
      }
      updateDate(defaultDate);
    } else {
      updateDate(newValue ?? null);
    }
  } else {
    updateDate(props.modelValue || null);
  }
}, { immediate: true });
function toggleMenuOpen(trigger) {
  if (trigger === "textField" && props.pickerOnly || trigger === "icon" && !props.pickerOnly) {
    if (!props.readonly) isMenuOpen.value = true;
  }
}
const textFieldRef = ref();
function validate() {
  textFieldRef.value?.validate();
}
function resetValidation() {
  textFieldRef.value?.resetValidation();
}
defineExpose({
  reset: resetDatePicker,
  validate,
  resetValidation,
  isValid: textFieldRef.value?.isValid
});
</script>

<template>
  <v-menu
      v-model="isMenuOpen"
      :open-on-click="false"
  >
    <template #activator="{ props: activatorProps }">
      <v-text-field
          ref="textFieldRef"
          v-model="displayedDate"
          :rules="computedRules"
          v-bind="$attrs"
          @focus="handleTextFieldFocus"
          @blur="handleTextFieldBlur"
          @keydown="handleTextFieldInput"
          @keyup.enter="handleTextFieldEnterKey"
          @click:clear="handleTextFieldClear"
          @click="toggleMenuOpen('textField')"
      >
        <template #append="appendProps">
          <slot name="append" v-bind="appendProps" :toggleMenuOpen="toggleMenuOpen" :activatorProps="activatorProps">
            <v-icon
                :disabled="appendProps.isReadonly?.value || appendProps.isDisabled?.value"
                v-bind="activatorProps"
                @click="toggleMenuOpen('icon')"
            >
              fa:fa-regular fa-calendar
            </v-icon>
          </slot>
        </template>
      </v-text-field>
    </template>
    <Datepicker
        v-model="selectedDate"
        model-type="yyyy-MM-dd"
        :time-config="{ enableTimePicker: false }"
        :flow="datepickerFlow"
        :min-date="props.minDate"
        :max-date="props.maxDate"
        auto-apply
        inline
        :locale="datepickerLocale"
        @update:model-value="updateDatePicker"
    >
      <template #year="{ value }" v-if="locale == 'TH'">
        {{value + 543}}
      </template>
      <template #year-overlay-value="{ value }" v-if="locale == 'TH'">
        {{value + 543}}
      </template>
    </Datepicker>
  </v-menu>
</template>

<style scoped>
:deep(.dp__button.dp__overlay_action){display:none}
</style>
