<script setup lang="ts">
import type { FormErrors } from '~/types/error'
import { toTypedSchema } from '@vee-validate/zod'
import Block from '~/components/pub/my-ui/form/block.vue'
import FieldGroup from '~/components/pub/my-ui/form/field-group.vue'
import Field from '~/components/pub/my-ui/form/field.vue'
import InputBase from '~/components/pub/my-ui/form/input-base.vue'
import Label from '~/components/pub/my-ui/form/label.vue'
import { Label as RadioLabel } from '~/components/pub/ui/label'
import { RadioGroup, RadioGroupItem } from '~/components/pub/ui/radio-group'
import SelectDistrict from './_common/select-district.vue'
import SelectPostal from './_common/select-postal.vue'
import SelectProvince from './_common/select-province.vue'
import SelectRegency from './_common/select-regency.vue'
import SelectVillage from './_common/select-village.vue'
import { Form } from '~/components/pub/ui/form'

import * as DE from '~/components/pub/my-ui/doc-entry'

const props = defineProps<{
  title: string
  conf?: {
    withAddressName?: boolean
  }
  schema: any
  initialValues?: any
  errors?: FormErrors
}>()

const formSchema = toTypedSchema(props.schema)
const formRef = ref()

defineExpose({
  validate: () => formRef.value?.validate(),
  resetForm: () => formRef.value?.resetForm(),
  setValues: (values: any, shouldValidate = true) => formRef.value?.setValues(values, shouldValidate),
  values: computed(() => formRef.value?.values),
})

// Watchers untuk cascading reset
let isResetting = false

// Field dependency map for placeholder
const fieldStates: Record<string, { dependsOn?: string; placeholder: string }> = {
  regency_code: { dependsOn: 'province_code', placeholder: 'Pilih provinsi dahulu' },
  district_code: { dependsOn: 'regency_code', placeholder: 'Pilih kabupaten/kota dahulu' },
  village_code: { dependsOn: 'district_code', placeholder: 'Pilih kecamatan dahulu' },
  postalRegion_code: { dependsOn: 'village_code', placeholder: 'Pilih kelurahan dahulu' },
  address: { placeholder: 'Masukkan alamat' },
  rt: { placeholder: '001' },
  rw: { placeholder: '002' },
}

// Computed untuk konversi boolean ke string untuk radio group
const isSameAddressString = computed(() => {
  const value = formRef.value?.values?.isSameAddress
  if (typeof value === 'boolean') {
    return value ? '1' : '0'
  }
  return value || '1'
})
// #region Function Helper
function getFieldState(field: string) {
  const state = fieldStates[field]
  const isSame = formRef.value?.values?.isSameAddress === true || formRef.value?.values?.isSameAddress === '1'

  // Jika alamat sama, semua field kecuali provinsi disabled
  if (['address', 'rt', 'rw'].includes(field) && isSame) {
    return { placeholder: '-', disabled: true }
  }

  // Untuk field yang tergantung pada field lain
  if (state?.dependsOn) {
    const dependencyValue = formRef.value?.values?.[state.dependsOn]
    const isDisabledByDependency = !dependencyValue

    // Jika isSame, semua field location disabled
    if (isSame && ['regency_code', 'district_code', 'village_code', 'postalRegion_code'].includes(field)) {
      return { placeholder: '-', disabled: true }
    }

    if (isDisabledByDependency) {
      return { placeholder: state.placeholder, disabled: true }
    }
  }

  // Jika isSame dan field location, disabled
  if (isSame && ['regency_code', 'district_code', 'village_code', 'postalRegion_code'].includes(field)) {
    return { placeholder: '-', disabled: true }
  }

  return { placeholder: state?.placeholder ?? '', disabled: false }
}

// #endregion

// #region watch

// Watch province_code changes
watch(
  () => formRef.value?.values?.province_code,
  (newValue, oldValue) => {
    if (isResetting || !formRef.value || newValue === oldValue) return

    if (oldValue && newValue !== oldValue) {
      isResetting = true

      formRef.value.setValues(
        {
          regency_code: undefined,
          district_code: undefined,
          village_code: undefined,
          postalRegion_code: undefined,
        },
        false,
      )

      nextTick(() => {
        isResetting = false
      })
    }
  },
)

// Watch regency_code changes
watch(
  () => formRef.value?.values?.regency_code,
  (newValue, oldValue) => {
    if (isResetting || !formRef.value || newValue === oldValue) return

    if (oldValue && newValue !== oldValue) {
      isResetting = true

      formRef.value.setValues(
        {
          district_code: undefined,
          village_code: undefined,
          postalRegion_code: undefined,
        },
        false,
      )

      nextTick(() => {
        isResetting = false
      })
    }
  },
)

// Watch district_code changes
watch(
  () => formRef.value?.values?.district_code,
  (newValue, oldValue) => {
    if (isResetting || !formRef.value || newValue === oldValue) return

    if (oldValue && newValue !== oldValue) {
      isResetting = true

      formRef.value.setValues(
        {
          village_code: undefined,
          postalRegion_code: undefined,
        },
        false,
      )

      nextTick(() => {
        isResetting = false
      })
    }
  },
)

// Watch village_code changes
watch(
  () => formRef.value?.values?.village_code,
  (newValue, oldValue) => {
    if (isResetting || !formRef.value || newValue === oldValue) return

    if (oldValue && newValue !== oldValue) {
      isResetting = true

      formRef.value.setValues(
        {
          postalRegion_code: undefined,
        },
        false,
      )

      nextTick(() => {
        isResetting = false
      })
    }
  },
)

// Watch isSameAddress changes untuk trigger validasi
watch(
  () => formRef.value?.values?.isSameAddress,
  (newValue, oldValue) => {
    if (!formRef.value || newValue === oldValue) return

    // Konversi ke boolean untuk perbandingan yang konsisten
    const newBool = newValue === true || newValue === '1'
    const oldBool = oldValue === true || oldValue === '1'

    // Ketika berubah dari true ke false, clear empty strings dan trigger validasi
    if (oldBool && !newBool) {
      nextTick(() => {
        // Set empty strings ke undefined untuk trigger required validation
        const currentValues = formRef.value.values
        const updatedValues = { ...currentValues }

        // Convert empty strings to undefined untuk field yang sekarang required
        if (updatedValues.province_code === '') updatedValues.province_code = undefined
        if (updatedValues.regency_code === '') updatedValues.regency_code = undefined
        if (updatedValues.district_code === '') updatedValues.district_code = undefined
        if (updatedValues.village_code === '') updatedValues.village_code = undefined
        if (updatedValues.postalRegion_code === '') updatedValues.postalRegion_code = undefined
        if (updatedValues.address === '') updatedValues.address = undefined

        // Update values dan trigger validasi
        formRef.value.setValues(updatedValues, false)

        // Trigger validasi untuk menampilkan error
        setTimeout(() => {
          formRef.value?.validate()
        }, 50)
      })
    }

    // Ketika berubah dari false ke true, clear error messages
    if (!oldBool && newBool) {
      nextTick(() => {
        // Clear error messages untuk field yang tidak lagi required
        formRef.value?.setFieldError('province_code', undefined)
        formRef.value?.setFieldError('regency_code', undefined)
        formRef.value?.setFieldError('district_code', undefined)
        formRef.value?.setFieldError('village_code', undefined)
        formRef.value?.setFieldError('postalRegion_code', undefined)
        formRef.value?.setFieldError('address', undefined)
        formRef.value?.setFieldError('rt', undefined)
        formRef.value?.setFieldError('rw', undefined)
      })
    }
  },
)
// #endregion
</script>

<template>
  <Form
    ref="formRef"
    v-slot="{ values }"
    as=""
    keep-values
    :validation-schema="formSchema"
    :validate-on-mount="false"
    validation-mode="onSubmit"
    :initial-values="initialValues ?? { isSameAddress: '1', locationType_code: 'identity' }"
  >
    <div>
      <p
        v-if="props.title"
        class="text-sm 2xl:text-base mb-2 2xl:mb-3 font-semibold"
      >
        {{ props.title }}
      </p>
    </div>
    <!-- locationType_code - Hidden field with default value 'identity' -->
    <FormField
      v-slot="{ componentField }"
      name="locationType_code"
    >
      <input
        type="hidden"
        v-bind="componentField"
        value="identity"
      />
    </FormField>
    <DE.Block :col-count="4" :cell-flex="false">
      <DE.Cell :col-span="4">
        <DE.Label
          size="fit"
          height="compact"
          label-for="isSameAddress"
        >
          Apakah alamat KTP sama dengan alamat sekarang?
        </DE.Label>
        <DE.Field
          id="isSameAddress"
          :errors="errors"
        >
          <FormField
            v-slot="{ componentField }"
            name="isSameAddress"
          >
            <FormItem>
              <FormControl>
                <RadioGroup
                  :model-value="isSameAddressString"
                  @update:model-value="(value) => componentField.onChange(value)"
                  class="flex flex-row flex-wrap gap-4 sm:gap-6"
                >
                  <div
                    v-for="(option, index) in [
                      { label: 'Ya', value: '1' },
                      { label: 'Tidak', value: '0' },
                    ]"
                    :key="option.value"
                    class="flex min-w-fit items-center space-x-2"
                  >
                    <RadioGroupItem
                      :id="`isSameAddress-${index}`"
                      :value="option.value"
                      class="relative h-4 w-4 rounded-full border-2 border-muted-foreground before:absolute before:inset-1 before:rounded-full before:bg-primary before:opacity-0 before:transition-opacity data-[state=checked]:border-primary data-[state=checked]:bg-white data-[state=checked]:before:opacity-100 sm:h-5 sm:w-5"
                    />
                    <RadioLabel
                      :for="`isSameAddress-${index}`"
                      class="cursor-pointer select-none text-xs font-medium leading-none transition-colors hover:text-primary peer-disabled:cursor-not-allowed peer-disabled:opacity-70 sm:text-sm"
                    >
                      {{ option.label }}
                    </RadioLabel>
                  </div>
                </RadioGroup>
              </FormControl>
              <FormMessage class="ml-0 mt-1" />
            </FormItem>
          </FormField>
        </DE.Field>
      </DE.Cell>
      <SelectProvince
        field-name="province_code"
        placeholder="Pilih"
        :is-disabled="values.isSameAddress === true || values.isSameAddress === '1'"
        :is-required="values.isSameAddress !== true && values.isSameAddress !== '1'"
      />
      <SelectRegency
        field-name="regency_code"
        :province-code="values.province_code"
        :is-disabled="getFieldState('regency_code').disabled"
        :is-required="values.isSameAddress !== true && values.isSameAddress !== '1'"
      />
      <SelectDistrict
        field-name="district_code"
        :regency-code="values.regency_code"
        :is-disabled="getFieldState('district_code').disabled"
        :is-required="values.isSameAddress !== true && values.isSameAddress !== '1'"
      />
      <SelectVillage
        field-name="village_code"
        :district-code="values.district_code"
        :is-disabled="getFieldState('village_code').disabled"
        :is-required="values.isSameAddress !== true && values.isSameAddress !== '1'"
      />
      <InputBase
        field-name="address"
        label="Alamat"
        :placeholder="getFieldState('address').placeholder"
        :is-disabled="getFieldState('address').disabled"
        :errors="errors"
        :is-required="values.isSameAddress !== true && values.isSameAddress !== '1'"
        :col-span="2"
      />
      <div class="grid grid-cols-2 gap-1">
        <InputBase
          field-name="rt"
          label="RT"
          :errors="errors"
          numeric-only
          :max-length="2"
          :placeholder="getFieldState('rt').placeholder"
          :is-disabled="getFieldState('rt').disabled"
        />
        <InputBase
          field-name="rw"
          label="RW"
          :placeholder="getFieldState('rw').placeholder"
          :is-disabled="getFieldState('rw').disabled"
          :errors="errors"
          :max-length="2"
          numeric-only
        />
      </div>
      <SelectPostal
        field-name="postalRegion_code"
        :village-code="values.village_code"
        :placeholder="getFieldState('postalRegion_code').placeholder"
        :is-disabled="getFieldState('postalRegion_code').disabled || !values.village_code"
      />
    </DE.Block>

  </Form>
</template>
