<script setup lang="ts">
import { onMounted, watch, reactive, ref } from 'vue';
import useAddressStore, {
  District,
  Province,
  SubDistrict,
} from 'stores/address';
import { selectFilterOptionRefMod } from 'stores/utils';
import { QSelect } from 'quasar';

defineProps<{
  title?: string;
  addressTitle?: string;
  addressTitleEN?: string;
  dense?: boolean;
  outlined?: boolean;
  readonly?: boolean;
  separator?: boolean;
  employee?: boolean;
  disabledRule?: boolean;
  indexId?: number;
  prefixId: string;
  hideTitle?: boolean;
}>();

const adrressStore = useAddressStore();
const address = defineModel('address', { default: '' });
const addressEN = defineModel('addressEN', { default: '' });
const provinceId = defineModel<string | null | undefined>('provinceId');
const districtId = defineModel<string | null | undefined>('districtId');
const subDistrictId = defineModel<string | null | undefined>('subDistrictId');
const zipCode = defineModel<string | null | undefined>('zipCode');
const sameWithEmployer = defineModel<boolean>('sameWithEmployer');

const addrOptions = reactive<{
  provinceOps: Province[];
  districtOps: District[];
  subDistrictOps: SubDistrict[];
}>({
  provinceOps: [],
  districtOps: [],
  subDistrictOps: [],
});

async function fetchProvince() {
  const result = await adrressStore.fetchProvince();

  if (result) addrOptions.provinceOps = result;

  provinceFilter = selectFilterOptionRefMod(
    ref(addrOptions.provinceOps),
    provinceOptions,
    'name',
  );

  provinceEnFilter = selectFilterOptionRefMod(
    ref(addrOptions.provinceOps),
    provinceOptions,
    'nameEN',
  );
}

async function fetchDistrict() {
  if (!provinceId.value) return;

  const result = await adrressStore.fetchDistrictByProvinceId(provinceId.value);
  if (result) addrOptions.districtOps = result;

  districtFilter = selectFilterOptionRefMod(
    ref(addrOptions.districtOps),
    districtOptions,
    'name',
  );

  districtEnFilter = selectFilterOptionRefMod(
    ref(addrOptions.districtOps),
    districtOptions,
    'nameEN',
  );
}

async function fetchSubDistrict() {
  if (!districtId.value) return;
  const result = await adrressStore.fetchSubDistrictByProvinceId(
    districtId.value,
  );
  if (result) addrOptions.subDistrictOps = result;

  subDistrictFilter = selectFilterOptionRefMod(
    ref(addrOptions.subDistrictOps),
    subDistrictOptions,
    'name',
  );

  subDistrictEnFilter = selectFilterOptionRefMod(
    ref(addrOptions.subDistrictOps),
    subDistrictOptions,
    'nameEN',
  );
}

async function selectSubDistrict(id: string) {
  if (!id) return;
  zipCode.value =
    addrOptions.subDistrictOps
      ?.filter((x) => x.id === id)
      .map((x) => x.zipCode)[0] ?? '';
}

const provinceOptions = ref<Record<string, unknown>[]>([]);
let provinceFilter: (
  value: string,
  update: (callbackFn: () => void, afterFn?: (ref: QSelect) => void) => void,
) => void;
let provinceEnFilter: (
  value: string,
  update: (callbackFn: () => void, afterFn?: (ref: QSelect) => void) => void,
) => void;

const districtOptions = ref<Record<string, unknown>[]>([]);
let districtFilter: (
  value: string,
  update: (callbackFn: () => void, afterFn?: (ref: QSelect) => void) => void,
) => void;
let districtEnFilter: (
  value: string,
  update: (callbackFn: () => void, afterFn?: (ref: QSelect) => void) => void,
) => void;

const subDistrictOptions = ref<Record<string, unknown>[]>([]);
let subDistrictFilter: (
  value: string,
  update: (callbackFn: () => void, afterFn?: (ref: QSelect) => void) => void,
) => void;
let subDistrictEnFilter: (
  value: string,
  update: (callbackFn: () => void, afterFn?: (ref: QSelect) => void) => void,
) => void;

onMounted(async () => {
  await fetchProvince();
  await fetchDistrict();
  await fetchSubDistrict();
});

watch(provinceId, fetchDistrict);
watch(districtId, fetchSubDistrict);
</script>
<template>
  <div class="col-12">
    <div
      v-if="!hideTitle"
      class="col-12 q-pb-sm text-weight-bold text-body1 row items-center"
    >
      <q-icon
        size="xs"
        class="q-pa-sm rounded q-mr-xs"
        color="info"
        name="mdi-map-marker-radius-outline"
        style="background-color: var(--surface-3)"
      />

      {{ title || $t('formDialogTitlePersonnelAddress') }}

      <div
        v-if="employee"
        class="surface-3 q-px-sm q-py-xs row text-caption q-ml-md app-text-muted"
        style="border-radius: var(--radius-3)"
      >
        <span
          :id="`${prefixId}-same`"
          class="q-px-sm q-mr-lg rounded cursor-pointer"
          :class="{
            dark: $q.dark.isActive,
            'active-addr': sameWithEmployer,
            'cursor-not-allowed': readonly,
          }"
          @click="readonly ? '' : (sameWithEmployer = true)"
        >
          {{ $t('formDialogToggleSameAddress') }}
        </span>
        <span
          :id="`${prefixId}-custom`"
          class="q-px-sm rounded cursor-pointer"
          :class="{
            dark: $q.dark.isActive,
            'active-addr': !sameWithEmployer,
            'cursor-not-allowed': readonly,
          }"
          @click="readonly ? '' : (sameWithEmployer = false)"
        >
          {{ $t('formDialogToggleCustomAddress') }}
        </span>
      </div>
    </div>

    <div class="col-12 row q-col-gutter-y-md">
      <div class="col-12 app-text-muted-2">
        <q-icon size="xs" class="q-mr-xs" name="mdi-map-marker-outline" />
        {{ addressTitle || $t('formDialogTitleAddressPure') }}
      </div>
      <div class="col-12 row q-col-gutter-sm">
        <q-input
          outlined
          hide-bottom-space
          class="col-12"
          v-model="address"
          lazy-rules="ondemand"
          :dense="dense"
          :label="$t('address')"
          :readonly="readonly || sameWithEmployer"
          :for="`${prefixId}-${indexId !== undefined ? `input-address-${indexId}` : 'input-address'}`"
          :rules="
            disabledRule
              ? []
              : [
                  (val) =>
                    (val && val.length > 0) ||
                    $t('formDialogInputAddressValidate'),
                ]
          "
        />
        <q-select
          autocomplete="off"
          outlined
          clearable
          use-input
          fill-input
          emit-value
          map-options
          hide-selected
          hide-bottom-space
          option-value="id"
          input-debounce="0"
          option-label="name"
          v-model="provinceId"
          lazy-rules="ondemand"
          class="col-md-3 col-6"
          :dense="dense"
          :label="$t('province')"
          :options="provinceOptions"
          :readonly="readonly || sameWithEmployer"
          :hide-dropdown-icon="readonly || sameWithEmployer"
          :for="`${prefixId}-${indexId !== undefined ? `select-province-${indexId}` : 'select-province'}`"
          :rules="
            disabledRule
              ? []
              : [
                  (val) =>
                    (val && val.length > 0) ||
                    $t('formDialogInputProvinceValidate'),
                ]
          "
          @filter="provinceFilter"
          @update:model-value="districtId = subDistrictId = zipCode = null"
        >
          <template v-slot:no-option>
            <q-item>
              <q-item-section class="text-grey">
                {{ $t('noResults') }}
              </q-item-section>
            </q-item>
          </template>
        </q-select>

        <q-select
          autocomplete="off"
          outlined
          clearable
          use-input
          fill-input
          emit-value
          map-options
          hide-selected
          hide-bottom-space
          option-value="id"
          input-debounce="0"
          option-label="name"
          v-model="districtId"
          lazy-rules="ondemand"
          class="col-md-3 col-6"
          :dense="dense"
          :label="$t('district')"
          :options="districtOptions"
          :readonly="readonly || sameWithEmployer"
          :hide-dropdown-icon="readonly || sameWithEmployer"
          :for="`${prefixId}-${indexId !== undefined ? `select-district-${indexId}` : 'select-district'}`"
          :rules="
            disabledRule
              ? []
              : [
                  (val) =>
                    (val && val.length > 0) ||
                    $t('formDialogInputDistrictValidate'),
                ]
          "
          @filter="districtFilter"
          @update:model-value="subDistrictId = zipCode = null"
        >
          <template v-slot:no-option>
            <q-item>
              <q-item-section class="text-grey">
                {{ $t('noResults') }}
              </q-item-section>
            </q-item>
          </template>
        </q-select>
        <q-select
          autocomplete="off"
          outlined
          clearable
          use-input
          fill-input
          emit-value
          map-options
          hide-selected
          hide-bottom-space
          option-value="id"
          input-debounce="0"
          option-label="name"
          lazy-rules="ondemand"
          class="col-md-3 col-6"
          v-model="subDistrictId"
          :dense="dense"
          :label="$t('subDistrict')"
          :options="subDistrictOptions"
          :readonly="readonly || sameWithEmployer"
          :hide-dropdown-icon="readonly || sameWithEmployer"
          :for="`${prefixId}-${indexId !== undefined ? `select-sub-district-${indexId}` : 'select-sub-district'}`"
          :rules="
            disabledRule
              ? []
              : [
                  (val) =>
                    (val && val.length > 0) ||
                    $t('formDialogInputSubDistrictValidate'),
                ]
          "
          @update:model-value="(v: string) => selectSubDistrict(v)"
          @filter="subDistrictFilter"
        >
          <template v-slot:no-option>
            <q-item>
              <q-item-section class="text-grey">
                {{ $t('noResults') }}
              </q-item-section>
            </q-item>
          </template>
        </q-select>
        <q-input
          lazy-rules="ondemand"
          :for="`${prefixId}-${indexId !== undefined ? `input-zip-code-${indexId}` : 'input-zip-code'}`"
          :dense="dense"
          outlined
          :disable="!readonly"
          readonly
          :label="$t('zipCode')"
          class="col-md-2 col-6"
          v-model="zipCode"
        />
      </div>

      <div class="col-12 app-text-muted-2">
        <q-icon size="xs" class="q-mr-xs" name="mdi-map-marker-outline" />
        {{ addressTitleEN || $t('formDialogTitleAddressPureEN') }}
      </div>
      <div class="col-12 row q-col-gutter-sm">
        <q-input
          lazy-rules="ondemand"
          :for="`${prefixId}-${indexId !== undefined ? `input-address-en-${indexId}` : 'input-address-en'}`"
          :dense="dense"
          :readonly="readonly || sameWithEmployer"
          outlined
          hide-bottom-space
          :label="$t('address')"
          class="col-12"
          v-model="addressEN"
          :rules="
            disabledRule
              ? []
              : [
                  (val) =>
                    (val && val.length > 0) ||
                    $t('formDialogInputAddressValidate'),
                ]
          "
        />
        <q-select
          autocomplete="off"
          outlined
          clearable
          use-input
          fill-input
          emit-value
          map-options
          hide-selected
          hide-bottom-space
          option-value="id"
          input-debounce="0"
          v-model="provinceId"
          lazy-rules="ondemand"
          option-label="nameEN"
          class="col-md-3 col-6"
          :dense="dense"
          :label="$t('province')"
          :options="provinceOptions"
          :readonly="readonly || sameWithEmployer"
          :hide-dropdown-icon="readonly || sameWithEmployer"
          :for="`${prefixId}-${indexId !== undefined ? `select-province-en-${indexId}` : 'select-province-en'}`"
          :rules="
            disabledRule
              ? []
              : [
                  (val) =>
                    (val && val.length > 0) ||
                    $t('formDialogInputProvinceValidate'),
                ]
          "
          @update:model-value="districtId = subDistrictId = zipCode = null"
          @filter="provinceEnFilter"
        >
          <template v-slot:no-option>
            <q-item>
              <q-item-section class="text-grey">
                {{ $t('noResults') }}
              </q-item-section>
            </q-item>
          </template>
        </q-select>
        <q-select
          autocomplete="off"
          outlined
          clearable
          use-input
          fill-input
          emit-value
          map-options
          hide-selected
          hide-bottom-space
          option-value="id"
          input-debounce="0"
          v-model="districtId"
          lazy-rules="ondemand"
          option-label="nameEN"
          class="col-md-3 col-6"
          :dense="dense"
          :label="$t('district')"
          :options="districtOptions"
          :readonly="readonly || sameWithEmployer"
          :hide-dropdown-icon="readonly || sameWithEmployer"
          :for="`${prefixId}-${indexId !== undefined ? `select-district-en-${indexId}` : 'select-district-en'}`"
          :rules="
            disabledRule
              ? []
              : [
                  (val) =>
                    (val && val.length > 0) ||
                    $t('formDialogInputDistrictValidate'),
                ]
          "
          @update:model-value="subDistrictId = zipCode = null"
          @filter="districtEnFilter"
        >
          <template v-slot:no-option>
            <q-item>
              <q-item-section class="text-grey">
                {{ $t('noResults') }}
              </q-item-section>
            </q-item>
          </template>
        </q-select>
        <q-select
          autocomplete="off"
          outlined
          clearable
          use-input
          fill-input
          emit-value
          map-options
          hide-selected
          hide-bottom-space
          option-value="id"
          input-debounce="0"
          lazy-rules="ondemand"
          option-label="nameEN"
          class="col-md-3 col-6"
          v-model="subDistrictId"
          :dense="dense"
          :label="$t('subDistrict')"
          :options="subDistrictOptions"
          :readonly="readonly || sameWithEmployer"
          :hide-dropdown-icon="readonly || sameWithEmployer"
          :for="`${prefixId}-${indexId !== undefined ? `select-sub-district-en-${indexId}` : 'select-sub-district-en'}`"
          :rules="
            disabledRule
              ? []
              : [
                  (val) =>
                    (val && val.length > 0) ||
                    $t('formDialogInputSubDistrictValidate'),
                ]
          "
          @update:model-value="(v: string) => selectSubDistrict(v)"
          @filter="subDistrictEnFilter"
        >
          <template v-slot:no-option>
            <q-item>
              <q-item-section class="text-grey">
                {{ $t('noResults') }}
              </q-item-section>
            </q-item>
          </template>
        </q-select>
        <q-input
          lazy-rules="ondemand"
          hide-bottom-space
          :for="`${prefixId}-${indexId !== undefined ? `input-zip-code-${indexId}` : 'input-zip-code'}`"
          :dense="dense"
          outlined
          readonly
          :disable="!readonly"
          zip="zip-en"
          :label="$t('zipCode')"
          class="col-md-2 col-6"
          v-model="zipCode"
        />
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.active-addr {
  color: hsl(var(--info-bg));
  background-color: hsla(var(--info-bg) / 0.1);
  border-radius: var(--radius-3);

  &.dark {
    background-color: var(--surface-1);
  }
}
</style>
