<script setup>
import { computed, ref, useAttrs } from "vue";
import { useI18n } from "vue-i18n";
import tc2sc from "../../composables/tc2sc";
import useLight from "../../composables/useLight";
import { useLightInputDefaults } from "../../composables/useLightProps";
defineOptions({ inheritAttrs: false });
const { t } = useI18n();
const props = defineProps({
  showPassword: { type: Boolean, required: false },
  translate: { type: Boolean, required: false },
  required: { type: Boolean, required: false },
  name: { type: null, required: false },
  mask: { type: null, required: false },
  fillMask: { type: [Boolean, String], required: false, skipCheck: true },
  reverseFillMask: { type: Boolean, required: false, skipCheck: true },
  unmaskedValue: { type: Boolean, required: false, skipCheck: true },
  maskTokens: { type: null, required: false },
  modelValue: { type: null, required: true },
  error: { type: [Boolean, null], required: false, skipCheck: true },
  errorMessage: { type: null, required: false },
  noErrorIcon: { type: Boolean, required: false, skipCheck: true },
  rules: { type: null, required: false },
  reactiveRules: { type: Boolean, required: false, skipCheck: true },
  lazyRules: { type: [Boolean, String], required: false, skipCheck: true },
  label: { type: null, required: false },
  stackLabel: { type: Boolean, required: false, skipCheck: true, default: void 0 },
  hint: { type: null, required: false },
  hideHint: { type: Boolean, required: false, skipCheck: true },
  prefix: { type: null, required: false },
  suffix: { type: null, required: false },
  labelColor: { type: null, required: false },
  color: { type: null, required: false },
  bgColor: { type: null, required: false },
  dark: { type: [Boolean, null], required: false, skipCheck: true, default: void 0 },
  loading: { type: Boolean, required: false, skipCheck: true },
  clearable: { type: Boolean, required: false, skipCheck: true },
  clearIcon: { type: null, required: false },
  filled: { type: Boolean, required: false, skipCheck: true, default: void 0 },
  outlined: { type: Boolean, required: false, skipCheck: true, default: void 0 },
  borderless: { type: Boolean, required: false, skipCheck: true },
  standout: { type: [Boolean, String], required: false, skipCheck: true, default: void 0 },
  labelSlot: { type: Boolean, required: false, skipCheck: true },
  bottomSlots: { type: Boolean, required: false, skipCheck: true },
  hideBottomSpace: { type: Boolean, required: false, skipCheck: true, default: true },
  counter: { type: Boolean, required: false, skipCheck: true },
  rounded: { type: Boolean, required: false, skipCheck: true, default: void 0 },
  square: { type: Boolean, required: false, skipCheck: true, default: void 0 },
  dense: { type: Boolean, required: false, skipCheck: true, default: void 0 },
  itemAligned: { type: Boolean, required: false, skipCheck: true },
  disable: { type: Boolean, required: false, skipCheck: true },
  readonly: { type: Boolean, required: false, skipCheck: true },
  autofocus: { type: Boolean, required: false, skipCheck: true },
  for: { type: null, required: false },
  shadowText: { type: null, required: false },
  type: { type: null, required: false },
  debounce: { type: null, required: false },
  maxlength: { type: null, required: false },
  autogrow: { type: Boolean, required: false, skipCheck: true },
  inputClass: { type: null, required: false },
  inputStyle: { type: null, required: false },
  "onUpdate:modelValue": { type: Function, required: false },
  onFocus: { type: Function, required: false },
  onBlur: { type: Function, required: false },
  onClear: { type: Function, required: false }
});
const modelValue = defineModel({ type: null });
const attrs = useAttrs();
const L_KEYS = ["showPassword", "translate", "required"];
const computedRules = computed(() => {
  const rules = Array.isArray(props.rules) ? [...props.rules] : [];
  if (props.required) {
    rules.push((val) => !!val || t("input_required", [t(props.label ?? "")]));
  }
  if (props.type === "email") {
    rules.push((val) => {
      if (val && !val.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/))
        return t("Invalid email format");
    });
  }
  const stringRules = rules.filter((r) => typeof r === "string");
  if (stringRules.includes("containUpper"))
    rules.push((val) => val && !val.match(/[A-Z]/) ? t("Must contain at least one uppercase letter") : void 0);
  if (stringRules.includes("containLower"))
    rules.push((val) => val && !val.match(/[a-z]/) ? t("Must contain at least one lowercase letter") : void 0);
  if (stringRules.includes("containNumber"))
    rules.push((val) => val && !val.match(/[0-9]/) ? t("Must contain at least one number") : void 0);
  if (stringRules.includes("containSpecial"))
    rules.push((val) => val && !val.match(/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/) ? t("Must contain at least one symbol") : void 0);
  const minLengthRule = rules.find((r) => typeof r === "string" && r.startsWith("minLength:"));
  if (minLengthRule) {
    const min = parseInt(minLengthRule.replace("minLength:", ""));
    rules.push((val) => val && val.length < min ? t("input_min", [min]) : void 0);
  }
  return rules.filter((r) => typeof r !== "string");
});
const isShowPassword = ref(false);
const localType = computed(() => {
  if (props.type === "password" && isShowPassword.value) return "text";
  return props.type;
});
const localShowPassword = computed(
  () => props.type === "password" && !!props.showPassword && !!modelValue.value
);
const onClickTc2Sc = () => {
  modelValue.value = tc2sc(modelValue.value ?? "");
};
const base = useLightInputDefaults(props, attrs, L_KEYS);
const inputProps = computed(() => {
  const result = {
    ...base.value,
    // label/hint already translated by composable
    rules: computedRules.value,
    type: localType.value
  };
  if (props.required && result.label)
    result.label = "* " + result.label;
  return result;
});
const inputRef = ref();
defineExpose({
  validate: () => inputRef.value?.validate(),
  focus: () => inputRef.value?.focus(),
  reset: () => inputRef.value?.reset()
});
</script>

<template>
    <q-input ref="inputRef" v-model="modelValue" v-bind="inputProps">
        <template v-if="translate" #prepend>
            <q-btn icon="sym_o_translate" flat dense rounded>
                <q-menu dense>
                    <q-list>
                        <q-item clickable v-close-popup @click="onClickTc2Sc">
                            <q-item-section>繁轉簡</q-item-section>
                        </q-item>
                    </q-list>
                </q-menu>
            </q-btn>
        </template>

        <template v-for="(_, name) in $slots" #[name]="slotProps" :key="name">
            <slot :name="name" v-bind="slotProps ?? {}" />
        </template>

        <template v-if="localShowPassword" #append>
            <q-icon name="sym_o_visibility" class="cursor-pointer" @click="isShowPassword = false" v-if="isShowPassword" />
            <q-icon name="sym_o_visibility_off" class="cursor-pointer" @click="isShowPassword = true" v-else />
        </template>
    </q-input>
</template>
