<script lang="ts" setup>
import { computed, onMounted, reactive, ref, watch } from 'vue'
import * as select from '@zag-js/select'
import Swal from 'sweetalert2'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Box } from '@/components/ui/box'
import { Field, FieldError, FieldGroup, FieldLabel } from '@/components/ui/field'
import { Input } from '@/components/ui/input'
import { Lucide } from '@/components/ui/lucide'
import {
  SelectRoot,
  SelectControl,
  SelectTrigger,
  SelectValueText,
  SelectContent,
  SelectItemGroup,
  SelectItemGroupLabel,
  SelectItem,
  SelectItemText,
} from '@/components/ui/select'
import { getApiErrorMessage, getApiValidationErrors } from '@/core/utils/getApiErrorMessage'
import {
  createAddress,
  deleteAddress,
  listAddresses,
  updateAddress,
} from '@/modules/profile/services/address.service'
import { updateProfile } from '@/modules/profile/services/profile.service'
import type { Address, AddressPayload } from '@/modules/profile/types/address.types'
import { useAuthStore } from '@/stores/auth'

defineProps<{
  embedded?: boolean
}>()

const authStore = useAuthStore()

const saving = ref(false)

const form = reactive({
  name: '',
  ic_number: '',
  position: '',
  phone_number: '',
  birth_date: '',
  birth_place: '',
})

type ProfileFieldKey = 'gender' | 'marriage_status' | 'birth_date' | 'birth_place'

const PROFILE_FIELD_KEYS: ProfileFieldKey[] = [
  'gender',
  'marriage_status',
  'birth_date',
  'birth_place',
]

const profileErrors = reactive<Partial<Record<ProfileFieldKey, string>>>({})

const addresses = ref<Address[]>([])
const loadingAddresses = ref(false)
const savingAddress = ref(false)
const deletingAddressId = ref<string | null>(null)
const editingAddressId = ref<string | null>(null)

type AddressFieldKey =
  | 'address_type'
  | 'address_line_1'
  | 'address_line_2'
  | 'city'
  | 'state'
  | 'postcode'
  | 'country'

const ADDRESS_FIELD_KEYS: AddressFieldKey[] = [
  'address_type',
  'address_line_1',
  'address_line_2',
  'city',
  'state',
  'postcode',
  'country',
]

const addressErrors = reactive<Partial<Record<AddressFieldKey, string>>>({})

type SelectOption = { label: string; value: string }

const GENDER_OPTIONS: SelectOption[] = [
  { label: 'Lelaki', value: 'Lelaki' },
  { label: 'Perempuan', value: 'Perempuan' },
]

const MARRIAGE_STATUS_OPTIONS: SelectOption[] = [
  { label: 'Belum Berkahwin', value: 'Belum Berkahwin' },
  { label: 'Berkahwin', value: 'Berkahwin' },
  { label: 'Bercerai', value: 'Bercerai' },
  { label: 'Balu', value: 'Balu' },
  { label: 'Duda', value: 'Duda' },
]

const ADDRESS_TYPE_OPTIONS: SelectOption[] = [
  { label: 'Rumah', value: 'home' },
  { label: 'Pejabat', value: 'office' },
  { label: 'Bil', value: 'billing' },
]

const MALAYSIA_STATE_OPTIONS: SelectOption[] = [
  { label: 'Johor', value: 'Johor' },
  { label: 'Kedah', value: 'Kedah' },
  { label: 'Kelantan', value: 'Kelantan' },
  { label: 'Melaka', value: 'Melaka' },
  { label: 'Negeri Sembilan', value: 'Negeri Sembilan' },
  { label: 'Pahang', value: 'Pahang' },
  { label: 'Perak', value: 'Perak' },
  { label: 'Perlis', value: 'Perlis' },
  { label: 'Pulau Pinang', value: 'Pulau Pinang' },
  { label: 'Sabah', value: 'Sabah' },
  { label: 'Sarawak', value: 'Sarawak' },
  { label: 'Selangor', value: 'Selangor' },
  { label: 'Terengganu', value: 'Terengganu' },
  { label: 'Wilayah Persekutuan Kuala Lumpur', value: 'Wilayah Persekutuan Kuala Lumpur' },
  { label: 'Wilayah Persekutuan Labuan', value: 'Wilayah Persekutuan Labuan' },
  { label: 'Wilayah Persekutuan Putrajaya', value: 'Wilayah Persekutuan Putrajaya' },
]

function createSelectCollection(options: SelectOption[]) {
  return select.collection({
    items: options,
    itemToValue: (item) => item.label,
  })
}

function labelToApiValue(options: SelectOption[], label: string | undefined): string | null {
  if (!label) return null
  return options.find((option) => option.label === label)?.value ?? null
}

function apiValueToLabel(options: SelectOption[], value: string | null | undefined): string[] {
  if (!value) return []
  const option = options.find((item) => item.value === value)
  return option ? [option.label] : [value]
}

const genderCollection = createSelectCollection(GENDER_OPTIONS)
const marriageStatusCollection = createSelectCollection(MARRIAGE_STATUS_OPTIONS)
const addressTypeCollection = createSelectCollection(ADDRESS_TYPE_OPTIONS)
const stateCollection = createSelectCollection(MALAYSIA_STATE_OPTIONS)

const genderValue = ref<string[]>([])
const marriageStatusValue = ref<string[]>([])
const genderInitial = ref<string[]>([])
const marriageStatusInitial = ref<string[]>([])
const profileSelectKey = ref(0)

const addressTypeValue = ref<string[]>([])
const stateValue = ref<string[]>([])
const addressTypeInitial = ref<string[]>([])
const stateInitial = ref<string[]>([])

function clearProfileFieldError(field: ProfileFieldKey) {
  delete profileErrors[field]
}

function clearProfileErrors() {
  for (const field of PROFILE_FIELD_KEYS) {
    delete profileErrors[field]
  }
}

function setProfileErrorsFromApi(error: unknown): boolean {
  const apiErrors = getApiValidationErrors(error)
  if (!apiErrors) return false

  for (const [field, messages] of Object.entries(apiErrors)) {
    if (PROFILE_FIELD_KEYS.includes(field as ProfileFieldKey) && messages[0]) {
      profileErrors[field as ProfileFieldKey] = messages[0]
    }
  }

  return Object.keys(profileErrors).length > 0
}

function setGenderValue(details: { value: string[] }) {
  genderValue.value = details.value
  clearProfileFieldError('gender')
}

function setMarriageStatusValue(details: { value: string[] }) {
  marriageStatusValue.value = details.value
  clearProfileFieldError('marriage_status')
}

function clearAddressFieldError(field: AddressFieldKey) {
  delete addressErrors[field]
}

function clearAddressErrors() {
  for (const field of ADDRESS_FIELD_KEYS) {
    delete addressErrors[field]
  }
}

function setAddressErrorsFromApi(error: unknown): boolean {
  const apiErrors = getApiValidationErrors(error)
  if (!apiErrors) return false

  for (const [field, messages] of Object.entries(apiErrors)) {
    if (ADDRESS_FIELD_KEYS.includes(field as AddressFieldKey) && messages[0]) {
      addressErrors[field as AddressFieldKey] = messages[0]
    }
  }

  return Object.keys(addressErrors).length > 0
}

function validateAddressForm(): boolean {
  clearAddressErrors()

  let valid = true

  if (
    !addressTypeValue.value[0] ||
    !labelToApiValue(ADDRESS_TYPE_OPTIONS, addressTypeValue.value[0])
  ) {
    addressErrors.address_type = 'Jenis alamat diperlukan.'
    valid = false
  }

  if (!addressForm.address_line_1.trim()) {
    addressErrors.address_line_1 = 'Alamat 1 diperlukan.'
    valid = false
  }

  if (!addressForm.city.trim()) {
    addressErrors.city = 'Bandar diperlukan.'
    valid = false
  }

  if (!labelToApiValue(MALAYSIA_STATE_OPTIONS, stateValue.value[0]) && !addressForm.state.trim()) {
    addressErrors.state = 'Negeri diperlukan.'
    valid = false
  }

  if (!addressForm.postcode.trim()) {
    addressErrors.postcode = 'Poskod diperlukan.'
    valid = false
  }

  if (!addressForm.country.trim()) {
    addressErrors.country = 'Negara diperlukan.'
    valid = false
  }

  return valid
}

function setAddressTypeValue(details: { value: string[] }) {
  addressTypeValue.value = details.value
  clearAddressFieldError('address_type')
  addressForm.address_type =
    labelToApiValue(ADDRESS_TYPE_OPTIONS, details.value[0]) ?? ''
}

function setStateValue(details: { value: string[] }) {
  stateValue.value = details.value
  addressForm.state = details.value[0] ?? ''
  clearAddressFieldError('state')
}

function emptyAddressForm(): AddressPayload {
  return {
    address_type: '',
    address_line_1: '',
    address_line_2: '',
    city: '',
    state: '',
    postcode: '',
    country: 'Malaysia',
  }
}

const addressForm = reactive(emptyAddressForm())

const addressTypeLabel = computed(() =>
  Object.fromEntries(ADDRESS_TYPE_OPTIONS.map((option) => [option.value, option.label])),
)

const isEditingAddress = computed(() => editingAddressId.value !== null)

const displayValue = (value: string | number | null | undefined) => {
  if (value === null || value === undefined || value === '') return '-'
  return String(value).trim() || '-'
}

function formatDate(value: string | null | undefined): string {
  if (!value) return '-'
  return value.slice(0, 10)
}

function calculateAge(birthDate: string | null | undefined): number | null {
  if (!birthDate) return null
  const birth = new Date(birthDate.slice(0, 10))
  if (Number.isNaN(birth.getTime())) return null

  const today = new Date()
  let age = today.getFullYear() - birth.getFullYear()
  const monthDiff = today.getMonth() - birth.getMonth()
  if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) {
    age--
  }

  return age >= 0 ? age : null
}

const ageLabel = computed(() => {
  const age = calculateAge(form.birth_date || authStore.userBirthDate)
  if (age === null) return '-'
  return `${age} tahun`
})

function toDateInputValue(value: string | null | undefined): string {
  if (!value) return ''
  return value.slice(0, 10)
}

function syncProfileSelectValues() {
  genderValue.value = apiValueToLabel(GENDER_OPTIONS, authStore.user?.gender)
  genderInitial.value = [...genderValue.value]
  marriageStatusValue.value = apiValueToLabel(MARRIAGE_STATUS_OPTIONS, authStore.user?.marriage_status)
  marriageStatusInitial.value = [...marriageStatusValue.value]
  profileSelectKey.value++
}

function syncFormFromUser() {
  const user = authStore.user
  if (!user) return

  form.name = user.name ?? ''
  form.ic_number = user.ic_number ?? ''
  form.position = user.position ?? ''
  form.phone_number = user.phone_number ?? ''
  form.birth_date = toDateInputValue(user.birth_date)
  form.birth_place = user.birth_place ?? ''
  syncProfileSelectValues()
}

async function onSaveProfile() {
  saving.value = true
  clearProfileErrors()

  const gender = labelToApiValue(GENDER_OPTIONS, genderValue.value[0])
  const marriageStatus = labelToApiValue(MARRIAGE_STATUS_OPTIONS, marriageStatusValue.value[0])

  try {
    const res = await updateProfile({
      name: form.name.trim(),
      ic_number: form.ic_number.trim(),
      position: form.position.trim(),
      phone_number: form.phone_number.trim(),
      gender: gender ?? undefined,
      marriage_status: marriageStatus ?? undefined,
      birth_date: form.birth_date || undefined,
      birth_place: form.birth_place.trim() || undefined,
    })

    if (!res.success) {
      throw new Error(res.message ?? 'Gagal mengemas kini profil.')
    }

    authStore.setUserProfile(res.data)
    syncFormFromUser()

    await Swal.fire({
      toast: true,
      position: 'top-end',
      icon: 'success',
      title: 'Profil berjaya dikemas kini.',
      showConfirmButton: false,
      timer: 3000,
    })
  } catch (error) {
    if (!setProfileErrorsFromApi(error)) {
      await Swal.fire({
        icon: 'error',
        title: 'Ralat',
        text: getApiErrorMessage(error, 'Gagal mengemas kini profil.'),
      })
    }
  } finally {
    saving.value = false
  }
}

function syncAddressSelectValues() {
  addressTypeValue.value = apiValueToLabel(ADDRESS_TYPE_OPTIONS, addressForm.address_type)
  addressTypeInitial.value = [...addressTypeValue.value]
  stateValue.value = apiValueToLabel(MALAYSIA_STATE_OPTIONS, addressForm.state)
  stateInitial.value = [...stateValue.value]
}

function resetAddressForm() {
  Object.assign(addressForm, emptyAddressForm())
  editingAddressId.value = null
  clearAddressErrors()
  syncAddressSelectValues()
}

function formatAddressLine(address: Address) {
  return [address.address_line_1, address.address_line_2, address.postcode, address.city, address.state, address.country]
    .filter((part) => part?.trim())
    .join(', ')
}

async function fetchAddresses() {
  loadingAddresses.value = true

  try {
    const res = await listAddresses()
    addresses.value = res.data
  } catch (error) {
    await Swal.fire({
      icon: 'error',
      title: 'Ralat',
      text: getApiErrorMessage(error, 'Gagal memuatkan alamat.'),
    })
  } finally {
    loadingAddresses.value = false
  }
}

function startEditAddress(address: Address) {
  clearAddressErrors()
  editingAddressId.value = address.id
  addressForm.address_type = address.address_type
  addressForm.address_line_1 = address.address_line_1
  addressForm.address_line_2 = address.address_line_2 ?? ''
  addressForm.city = address.city
  addressForm.state = address.state
  addressForm.postcode = address.postcode
  addressForm.country = address.country
  syncAddressSelectValues()
}

async function onSaveAddress() {
  if (!validateAddressForm()) {
    return
  }

  savingAddress.value = true
  const wasEditing = isEditingAddress.value

  const payload: AddressPayload = {
    address_type: labelToApiValue(ADDRESS_TYPE_OPTIONS, addressTypeValue.value[0]) ?? addressForm.address_type,
    address_line_1: addressForm.address_line_1.trim(),
    address_line_2: addressForm.address_line_2?.trim() || undefined,
    city: addressForm.city.trim(),
    state: labelToApiValue(MALAYSIA_STATE_OPTIONS, stateValue.value[0]) ?? addressForm.state.trim(),
    postcode: addressForm.postcode.trim(),
    country: addressForm.country.trim(),
  }

  try {
    const res = wasEditing
      ? await updateAddress(editingAddressId.value!, payload)
      : await createAddress(payload)

    if (!res.success) {
      throw new Error(res.message ?? 'Gagal menyimpan alamat.')
    }

    await fetchAddresses()
    resetAddressForm()

    await Swal.fire({
      toast: true,
      position: 'top-end',
      icon: 'success',
      title: (wasEditing ? 'Alamat berjaya dikemas kini.' : 'Alamat berjaya ditambah.'),
      showConfirmButton: false,
      timer: 3000,
    })
  } catch (error) {
    if (!setAddressErrorsFromApi(error)) {
      await Swal.fire({
        icon: 'error',
        title: 'Ralat',
        text: getApiErrorMessage(error, 'Gagal menyimpan alamat.'),
      })
    }
  } finally {
    savingAddress.value = false
  }
}

async function onDeleteAddress(address: Address) {
  const result = await Swal.fire({
    icon: 'warning',
    title: 'Padam alamat?',
    text: 'Tindakan ini tidak boleh dibatalkan.',
    showCancelButton: true,
    confirmButtonText: 'Padam',
    cancelButtonText: 'Batal',
  })

  if (!result.isConfirmed) return

  deletingAddressId.value = address.id

  try {
    const res = await deleteAddress(address.id)

    if (!res.success) {
      throw new Error(res.message ?? 'Gagal memadam alamat.')
    }

    if (editingAddressId.value === address.id) {
      resetAddressForm()
    }

    await fetchAddresses()

    await Swal.fire({
      toast: true,
      position: 'top-end',
      icon: 'success',
      title: 'Alamat berjaya dipadam.',
      showConfirmButton: false,
      timer: 3000,
    })
  } catch (error) {
    await Swal.fire({
      icon: 'error',
      title: 'Ralat',
      text: getApiErrorMessage(error, 'Gagal memadam alamat.'),
    })
  } finally {
    deletingAddressId.value = null
  }
}

watch(() => authStore.user, syncFormFromUser, { immediate: true })

onMounted(async () => {
  syncFormFromUser()
  syncAddressSelectValues()
  await fetchAddresses()
})
</script>

<template>
  <div :class="embedded ? 'space-y-8' : 'mt-5 space-y-8'">
    <Box raised="single" class="p-6">
      <form class="space-y-6" @submit.prevent="onSaveProfile">
        <div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
          <div>
            <h3 class="text-lg font-semibold text-slate-900">Maklumat Peribadi</h3>
            <p class="mt-1 text-sm text-slate-500">
              Kemas kini maklumat peribadi anda.
            </p>
          </div>
          <Button type="submit" variant="primary" :disabled="saving">
            {{ saving ? 'Menyimpan...' : 'Simpan' }}
          </Button>
        </div>

        <FieldGroup>
          <div class="grid grid-cols-1 gap-4 md:grid-cols-2">
            <Field>
              <FieldLabel for="profile-name">Nama</FieldLabel>
              <Input id="profile-name" v-model="form.name" type="text" placeholder="Nama penuh" required />
            </Field>
            <Field>
              <FieldLabel for="profile-email">E-mel</FieldLabel>
              <Input id="profile-email" :model-value="authStore.user?.email ?? ''" type="email" disabled />
            </Field>
            <Field>
              <FieldLabel for="profile-ic">No. Kad Pengenalan</FieldLabel>
              <Input id="profile-ic" v-model="form.ic_number" type="text" placeholder="No. kad pengenalan" />
            </Field>
            <Field>
              <FieldLabel for="profile-phone">No. Telefon</FieldLabel>
              <Input id="profile-phone" v-model="form.phone_number" type="tel" pattern="[0-9]*"
                placeholder="0123456789" />
            </Field>
            <Field class="md:col-span-2">
              <FieldLabel for="profile-position">Jawatan</FieldLabel>
              <Input id="profile-position" v-model="form.position" type="text" placeholder="Jawatan" />
            </Field>
            <Field>
              <FieldLabel>Jantina</FieldLabel>
              <SelectRoot :key="`profile-gender-${profileSelectKey}`" class="w-full" :collection="genderCollection"
                :default-value="genderInitial" :disabled="saving" @value-change="setGenderValue">
                <SelectControl>
                  <SelectTrigger :aria-invalid="!!profileErrors.gender">
                    <SelectValueText placeholder="Pilih jantina" />
                  </SelectTrigger>
                </SelectControl>
                <SelectContent>
                  <SelectItemGroup>
                    <SelectItemGroupLabel>Jantina</SelectItemGroupLabel>
                    <SelectItem v-for="item in genderCollection.items" :key="item.label" :item="item">
                      <SelectItemText>{{ item.label }}</SelectItemText>
                    </SelectItem>
                  </SelectItemGroup>
                </SelectContent>
              </SelectRoot>
              <FieldError v-if="profileErrors.gender">{{ profileErrors.gender }}</FieldError>
            </Field>
            <Field>
              <FieldLabel for="profile-age">Umur</FieldLabel>
              <Input id="profile-age" :model-value="ageLabel" type="text" disabled />
            </Field>
            <Field>
              <FieldLabel>Status Perkahwinan</FieldLabel>
              <SelectRoot :key="`profile-marriage-${profileSelectKey}`" class="w-full"
                :collection="marriageStatusCollection" :default-value="marriageStatusInitial" :disabled="saving"
                @value-change="setMarriageStatusValue">
                <SelectControl>
                  <SelectTrigger :aria-invalid="!!profileErrors.marriage_status">
                    <SelectValueText placeholder="Pilih status perkahwinan" />
                  </SelectTrigger>
                </SelectControl>
                <SelectContent>
                  <SelectItemGroup>
                    <SelectItemGroupLabel>Status Perkahwinan</SelectItemGroupLabel>
                    <SelectItem v-for="item in marriageStatusCollection.items" :key="item.label" :item="item">
                      <SelectItemText>{{ item.label }}</SelectItemText>
                    </SelectItem>
                  </SelectItemGroup>
                </SelectContent>
              </SelectRoot>
              <FieldError v-if="profileErrors.marriage_status">{{ profileErrors.marriage_status }}</FieldError>
            </Field>
            <Field>
              <FieldLabel for="profile-member-number">Nombor Anggota</FieldLabel>
              <Input id="profile-member-number" :model-value="displayValue(authStore.userMemberNumber)" type="text"
                disabled />
            </Field>
            <Field>
              <FieldLabel for="profile-member-type">Jenis Anggota</FieldLabel>
              <Input id="profile-member-type" :model-value="displayValue(authStore.userMemberType)" type="text"
                disabled />
            </Field>
            <Field>
              <FieldLabel for="profile-join-date">Tarikh Sertai</FieldLabel>
              <Input id="profile-join-date" :model-value="formatDate(authStore.userJoinDate)" type="text" disabled />
            </Field>
            <Field>
              <FieldLabel for="profile-birth-date">Tarikh Lahir</FieldLabel>
              <Input id="profile-birth-date" v-model="form.birth_date" type="date" :disabled="saving"
                :aria-invalid="!!profileErrors.birth_date" @input="clearProfileFieldError('birth_date')" />
              <FieldError v-if="profileErrors.birth_date">{{ profileErrors.birth_date }}</FieldError>
            </Field>
            <Field class="md:col-span-2">
              <FieldLabel for="profile-birth-place">Tempat Lahir</FieldLabel>
              <Input id="profile-birth-place" v-model="form.birth_place" type="text" placeholder="Tempat lahir"
                :disabled="saving" :aria-invalid="!!profileErrors.birth_place"
                @input="clearProfileFieldError('birth_place')" />
              <FieldError v-if="profileErrors.birth_place">{{ profileErrors.birth_place }}</FieldError>
            </Field>
          </div>
        </FieldGroup>
      </form>
    </Box>

    <Box raised="single" class="p-6">
      <div class="space-y-6">
        <div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
          <div>
            <h3 class="text-lg font-semibold text-slate-900">Alamat</h3>
            <p class="mt-1 text-sm text-slate-500">
              Urus alamat rumah, pejabat, atau bil anda.
            </p>
          </div>
        </div>

        <div v-if="loadingAddresses" class="text-sm text-slate-500">
          Memuatkan alamat...
        </div>

        <div v-else-if="addresses.length" class="space-y-3">
          <div v-for="address in addresses" :key="address.id"
            class="flex flex-col gap-4 rounded-lg border border-foreground/10 p-4 sm:flex-row sm:items-start sm:justify-between">
            <div class="min-w-0 flex-1">
              <div class="flex flex-wrap items-center gap-2">
                <Badge look="outline">
                  {{ addressTypeLabel[address.address_type] ?? address.address_type }}
                </Badge>
              </div>
              <p class="mt-2 text-sm text-slate-700">
                {{ formatAddressLine(address) }}
              </p>
            </div>
            <div class="flex shrink-0 gap-2">
              <Button type="button" variant="ghost" class="border border-foreground/15 shadow-none"
                :disabled="deletingAddressId === address.id" @click="startEditAddress(address)">
                <Lucide class="mr-2 size-4" icon="Pencil" />
                Kemaskini
              </Button>
              <Button type="button" variant="ghost" class="border border-foreground/15 shadow-none text-danger"
                :disabled="deletingAddressId === address.id" @click="onDeleteAddress(address)">
                <Lucide class="mr-2 size-4" :icon="deletingAddressId === address.id ? 'LoaderCircle' : 'Trash'"
                  :class="{ 'animate-spin': deletingAddressId === address.id }" />
                Padam
              </Button>
            </div>
          </div>
        </div>

        <div v-else class="rounded-lg border border-dashed border-foreground/15 p-6 text-center text-sm text-slate-500">
          Tiada alamat direkodkan.
        </div>

        <form class="space-y-6 border-t border-foreground/10 pt-6" @submit.prevent="onSaveAddress">
          <div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
            <div>
              <h4 class="text-base font-semibold text-slate-900">
                {{ isEditingAddress ? 'Kemaskini Alamat' : 'Tambah Alamat' }}
              </h4>
              <p class="mt-1 text-sm text-slate-500">
                {{ isEditingAddress ?
                  'Kemas kini maklumat alamat yang dipilih.' : 'Tambah alamat baharu ke profil anda.' }}
              </p>
            </div>
            <div class="flex gap-2">
              <Button v-if="isEditingAddress" type="button" variant="ghost"
                class="border border-foreground/15 shadow-none" :disabled="savingAddress" @click="resetAddressForm">
                Batal
              </Button>
              <Button type="submit" variant="primary" :disabled="savingAddress">
                {{ savingAddress ? 'Menyimpan...' : isEditingAddress ? 'Kemaskini' : 'Tambah' }}
              </Button>
            </div>
          </div>

          <!-- Address Form -->
          <FieldGroup>
            <div class="grid grid-cols-1 gap-4 md:grid-cols-2">
              <Field>
                <FieldLabel>Jenis Alamat</FieldLabel>
                <SelectRoot :key="`address-type-${editingAddressId ?? 'new'}`" class="w-full"
                  :collection="addressTypeCollection" :default-value="addressTypeInitial" :disabled="savingAddress"
                  @value-change="setAddressTypeValue">
                  <SelectControl>
                    <SelectTrigger :aria-invalid="!!addressErrors.address_type">
                      <SelectValueText placeholder="Pilih jenis alamat" />
                    </SelectTrigger>
                  </SelectControl>
                  <SelectContent>
                    <SelectItemGroup>
                      <SelectItemGroupLabel>Jenis Alamat</SelectItemGroupLabel>
                      <SelectItem v-for="item in addressTypeCollection.items" :key="item.label" :item="item">
                        <SelectItemText>{{ item.label }}</SelectItemText>
                      </SelectItem>
                    </SelectItemGroup>
                  </SelectContent>
                </SelectRoot>
                <FieldError v-if="addressErrors.address_type">{{ addressErrors.address_type }}</FieldError>
              </Field>
              <Field>
                <FieldLabel for="address-country">Negara</FieldLabel>
                <Input id="address-country" v-model="addressForm.country" type="text" placeholder="Negara"
                  :aria-invalid="!!addressErrors.country" @input="clearAddressFieldError('country')" />
                <FieldError v-if="addressErrors.country">{{ addressErrors.country }}</FieldError>
              </Field>
              <Field class="md:col-span-2">
                <FieldLabel for="address-line-1">Alamat 1</FieldLabel>
                <Input id="address-line-1" v-model="addressForm.address_line_1" type="text"
                  placeholder="Alamat baris pertama" :aria-invalid="!!addressErrors.address_line_1"
                  @input="clearAddressFieldError('address_line_1')" />
                <FieldError v-if="addressErrors.address_line_1">{{ addressErrors.address_line_1 }}</FieldError>
              </Field>
              <Field class="md:col-span-2">
                <FieldLabel for="address-line-2">Alamat 2</FieldLabel>
                <Input id="address-line-2" v-model="addressForm.address_line_2" type="text"
                  placeholder="Alamat baris kedua (pilihan)" :aria-invalid="!!addressErrors.address_line_2"
                  @input="clearAddressFieldError('address_line_2')" />
                <FieldError v-if="addressErrors.address_line_2">{{ addressErrors.address_line_2 }}</FieldError>
              </Field>
              <Field>
                <FieldLabel for="address-city">Bandar</FieldLabel>
                <Input id="address-city" v-model="addressForm.city" type="text" placeholder="Bandar"
                  :aria-invalid="!!addressErrors.city" @input="clearAddressFieldError('city')" />
                <FieldError v-if="addressErrors.city">{{ addressErrors.city }}</FieldError>
              </Field>
              <Field>
                <FieldLabel>Negeri</FieldLabel>
                <SelectRoot :key="`address-state-${editingAddressId ?? 'new'}`" class="w-full"
                  :collection="stateCollection" :default-value="stateInitial" :disabled="savingAddress"
                  @value-change="setStateValue">
                  <SelectControl>
                    <SelectTrigger :aria-invalid="!!addressErrors.state">
                      <SelectValueText placeholder="Pilih negeri" />
                    </SelectTrigger>
                  </SelectControl>
                  <SelectContent>
                    <SelectItemGroup>
                      <SelectItemGroupLabel>Negeri</SelectItemGroupLabel>
                      <SelectItem v-for="item in stateCollection.items" :key="item.label" :item="item">
                        <SelectItemText>{{ item.label }}</SelectItemText>
                      </SelectItem>
                    </SelectItemGroup>
                  </SelectContent>
                </SelectRoot>
                <FieldError v-if="addressErrors.state">{{ addressErrors.state }}</FieldError>
              </Field>
              <Field>
                <FieldLabel for="address-postcode">Poskod</FieldLabel>
                <Input id="address-postcode" v-model="addressForm.postcode" type="text" placeholder="Poskod"
                  :aria-invalid="!!addressErrors.postcode" @input="clearAddressFieldError('postcode')" />
                <FieldError v-if="addressErrors.postcode">{{ addressErrors.postcode }}</FieldError>
              </Field>
            </div>
          </FieldGroup>
        </form>
      </div>
    </Box>
  </div>
</template>
