<script lang="ts" setup>
import { computed, onMounted, reactive, ref } 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 { CheckboxRoot, CheckboxControl, CheckboxLabel } from '@/components/ui/checkbox'
import { Field, FieldError, FieldGroup, FieldLabel } from '@/components/ui/field'
import { Input } from '@/components/ui/input'
import { Lucide } from '@/components/ui/lucide'
import { Textarea } from '@/components/ui/textarea'
import {
  SelectRoot,
  SelectControl,
  SelectTrigger,
  SelectValueText,
  SelectContent,
  SelectItemGroup,
  SelectItemGroupLabel,
  SelectItem,
  SelectItemText,
} from '@/components/ui/select'
import { getApiErrorMessage, getApiValidationErrors } from '@/core/utils/getApiErrorMessage'
import { createHeir, deleteHeir, listHeirs, updateHeir } from '@/modules/profile/services/heir.service'
import type { Heir, HeirPayload } from '@/modules/profile/types/heir.types'

defineProps<{
  embedded?: boolean
}>()

const heirs = ref<Heir[]>([])
const loadingHeirs = ref(false)
const savingHeir = ref(false)
const deletingHeirId = ref<string | null>(null)
const editingHeirId = ref<string | null>(null)

type HeirFieldKey =
  | 'name'
  | 'ic_number'
  | 'relationship'
  | 'phone_number'
  | 'address'
  | 'is_primary'

const HEIR_FIELD_KEYS: HeirFieldKey[] = [
  'name',
  'ic_number',
  'relationship',
  'phone_number',
  'address',
  'is_primary',
]

const heirErrors = reactive<Partial<Record<HeirFieldKey, string>>>({})

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

const RELATIONSHIP_OPTIONS: SelectOption[] = [
  { label: 'Isteri', value: 'Isteri' },
  { label: 'Suami', value: 'Suami' },
  { label: 'Anak', value: 'Anak' },
  { label: 'Bapa', value: 'Bapa' },
  { label: 'Ibu', value: 'Ibu' },
  { label: 'Orang Tua', value: 'Orang Tua' },
  { label: 'Saudara', value: 'Saudara' },
  { label: 'Lain-lain', value: 'Lain-lain' },
]

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 relationshipCollection = createSelectCollection(RELATIONSHIP_OPTIONS)

const relationshipValue = ref<string[]>([])
const relationshipInitial = ref<string[]>([])

const isEditingHeir = computed(() => editingHeirId.value !== null)

function emptyHeirForm() {
  return {
    name: '',
    ic_number: '',
    relationship: '',
    phone_number: '',
    address: '',
    is_primary: false,
  }
}

const heirForm = reactive(emptyHeirForm())

function clearHeirFieldError(field: HeirFieldKey) {
  delete heirErrors[field]
}

function clearHeirErrors() {
  for (const field of HEIR_FIELD_KEYS) {
    delete heirErrors[field]
  }
}

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

  for (const [field, messages] of Object.entries(apiErrors)) {
    if (HEIR_FIELD_KEYS.includes(field as HeirFieldKey) && messages[0]) {
      heirErrors[field as HeirFieldKey] = messages[0]
    }
  }

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

function setRelationshipValue(details: { value: string[] }) {
  relationshipValue.value = details.value
  clearHeirFieldError('relationship')
  heirForm.relationship = labelToApiValue(RELATIONSHIP_OPTIONS, details.value[0]) ?? ''
}

function syncHeirSelectValues() {
  relationshipValue.value = apiValueToLabel(RELATIONSHIP_OPTIONS, heirForm.relationship)
  relationshipInitial.value = [...relationshipValue.value]
}

function resetHeirForm() {
  Object.assign(heirForm, emptyHeirForm())
  editingHeirId.value = null
  clearHeirErrors()
  syncHeirSelectValues()
}

function validateHeirForm(): boolean {
  clearHeirErrors()

  let valid = true

  if (!heirForm.name.trim()) {
    heirErrors.name = 'Nama diperlukan.'
    valid = false
  }

  if (!heirForm.ic_number.trim()) {
    heirErrors.ic_number = 'No. kad pengenalan diperlukan.'
    valid = false
  }

  if (
    !relationshipValue.value[0] ||
    !labelToApiValue(RELATIONSHIP_OPTIONS, relationshipValue.value[0])
  ) {
    heirErrors.relationship = 'Hubungan diperlukan.'
    valid = false
  }

  if (!heirForm.phone_number.trim()) {
    heirErrors.phone_number = 'No. telefon diperlukan.'
    valid = false
  }

  if (!heirForm.address.trim()) {
    heirErrors.address = 'Alamat diperlukan.'
    valid = false
  }

  return valid
}

function buildHeirPayload(): HeirPayload {
  return {
    name: heirForm.name.trim(),
    ic_number: heirForm.ic_number.trim(),
    relationship:
      labelToApiValue(RELATIONSHIP_OPTIONS, relationshipValue.value[0]) ?? heirForm.relationship,
    phone_number: heirForm.phone_number.trim(),
    address: heirForm.address.trim(),
    is_primary: heirForm.is_primary,
  }
}

async function fetchHeirs() {
  loadingHeirs.value = true

  try {
    const res = await listHeirs()
    heirs.value = res.data
  } catch (error) {
    await Swal.fire({
      icon: 'error',
      title: 'Ralat',
      text: getApiErrorMessage(error, 'Gagal memuatkan pewaris.'),
    })
  } finally {
    loadingHeirs.value = false
  }
}

function startEditHeir(heir: Heir) {
  clearHeirErrors()
  editingHeirId.value = heir.id
  heirForm.name = heir.name
  heirForm.ic_number = heir.ic_number
  heirForm.relationship = heir.relationship
  heirForm.phone_number = heir.phone_number
  heirForm.address = heir.address
  heirForm.is_primary = heir.is_primary
  syncHeirSelectValues()
}

async function onSaveHeir() {
  if (!validateHeirForm()) {
    return
  }

  savingHeir.value = true
  const wasEditing = isEditingHeir.value
  const payload = buildHeirPayload()

  try {
    const res = wasEditing
      ? await updateHeir(editingHeirId.value!, payload)
      : await createHeir(payload)

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

    await fetchHeirs()
    resetHeirForm()

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

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

  if (!result.isConfirmed) return

  deletingHeirId.value = heir.id

  try {
    const res = await deleteHeir(heir.id)

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

    if (editingHeirId.value === heir.id) {
      resetHeirForm()
    }

    await fetchHeirs()

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

onMounted(async () => {
  syncHeirSelectValues()
  await fetchHeirs()
})
</script>

<template>
  <div :class="embedded ? '' : 'mt-5'">
    <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">Pewaris</h3>
            <p class="mt-1 text-sm text-slate-500">
              Urus maklumat pewaris anda.
            </p>
          </div>
        </div>

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

        <div v-else-if="heirs.length" class="space-y-3">
          <div
            v-for="heir in heirs"
            :key="heir.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">
                <span class="font-medium text-slate-900">{{ heir.name }}</span>
                <Badge v-if="heir.is_primary" class="bg-green-500 text-white">Utama</Badge>
                <Badge look="outline">{{ heir.relationship }}</Badge>
              </div>
              <p class="mt-1 text-sm text-slate-500">{{ heir.ic_number }}</p>
              <p class="mt-1 text-sm text-slate-500">{{ heir.phone_number }}</p>
              <p class="mt-1 text-sm text-slate-700">{{ heir.address }}</p>
            </div>
            <div class="flex shrink-0 gap-2">
              <Button
                type="button"
                variant="ghost"
                class="border border-foreground/15 shadow-none"
                :disabled="deletingHeirId === heir.id"
                @click="startEditHeir(heir)"
              >
                <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="deletingHeirId === heir.id"
                @click="onDeleteHeir(heir)"
              >
                <Lucide
                  class="mr-2 size-4"
                  :icon="deletingHeirId === heir.id ? 'LoaderCircle' : 'Trash'"
                  :class="{ 'animate-spin': deletingHeirId === heir.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 pewaris direkodkan.
        </div>

        <form class="space-y-6 border-t border-foreground/10 pt-6" @submit.prevent="onSaveHeir">
          <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">
                {{ isEditingHeir ? 'Kemaskini Pewaris' : 'Tambah Pewaris' }}
              </h4>
              <p class="mt-1 text-sm text-slate-500">
                {{
                  isEditingHeir
                    ? 'Kemas kini maklumat pewaris yang dipilih.'
                    : 'Tambah pewaris baharu ke profil anda.'
                }}
              </p>
            </div>
            <div class="flex gap-2">
              <Button
                v-if="isEditingHeir"
                type="button"
                variant="ghost"
                class="border border-foreground/15 shadow-none"
                :disabled="savingHeir"
                @click="resetHeirForm"
              >
                Batal
              </Button>
              <Button type="submit" variant="primary" :disabled="savingHeir">
                {{ savingHeir ? 'Menyimpan...' : isEditingHeir ? 'Kemaskini' : 'Tambah' }}
              </Button>
            </div>
          </div>

          <FieldGroup>
            <div class="grid grid-cols-1 gap-4 md:grid-cols-2">
              <Field>
                <FieldLabel for="heir-name">Nama</FieldLabel>
                <Input
                  id="heir-name"
                  v-model="heirForm.name"
                  type="text"
                  placeholder="Nama penuh"
                  :aria-invalid="!!heirErrors.name"
                  @input="clearHeirFieldError('name')"
                />
                <FieldError v-if="heirErrors.name">{{ heirErrors.name }}</FieldError>
              </Field>
              <Field>
                <FieldLabel for="heir-ic">No. Kad Pengenalan</FieldLabel>
                <Input
                  id="heir-ic"
                  v-model="heirForm.ic_number"
                  type="text"
                  placeholder="No. kad pengenalan"
                  :aria-invalid="!!heirErrors.ic_number"
                  @input="clearHeirFieldError('ic_number')"
                />
                <FieldError v-if="heirErrors.ic_number">{{ heirErrors.ic_number }}</FieldError>
              </Field>
              <Field>
                <FieldLabel>Hubungan</FieldLabel>
                <SelectRoot
                  :key="`heir-relationship-${editingHeirId ?? 'new'}`"
                  class="w-full"
                  :collection="relationshipCollection"
                  :default-value="relationshipInitial"
                  :disabled="savingHeir"
                  @value-change="setRelationshipValue"
                >
                  <SelectControl>
                    <SelectTrigger :aria-invalid="!!heirErrors.relationship">
                      <SelectValueText placeholder="Pilih hubungan" />
                    </SelectTrigger>
                  </SelectControl>
                  <SelectContent>
                    <SelectItemGroup>
                      <SelectItemGroupLabel>Hubungan</SelectItemGroupLabel>
                      <SelectItem
                        v-for="item in relationshipCollection.items"
                        :key="item.label"
                        :item="item"
                      >
                        <SelectItemText>{{ item.label }}</SelectItemText>
                      </SelectItem>
                    </SelectItemGroup>
                  </SelectContent>
                </SelectRoot>
                <FieldError v-if="heirErrors.relationship">{{ heirErrors.relationship }}</FieldError>
              </Field>
              <Field>
                <FieldLabel for="heir-phone">No. Telefon</FieldLabel>
                <Input
                  id="heir-phone"
                  v-model="heirForm.phone_number"
                  type="text"
                  placeholder="No. telefon"
                  :aria-invalid="!!heirErrors.phone_number"
                  @input="clearHeirFieldError('phone_number')"
                />
                <FieldError v-if="heirErrors.phone_number">{{ heirErrors.phone_number }}</FieldError>
              </Field>
              <Field class="md:col-span-2">
                <FieldLabel for="heir-address">Alamat</FieldLabel>
                <Textarea
                  id="heir-address"
                  v-model="heirForm.address"
                  placeholder="Alamat penuh"
                  class="resize-none"
                  :aria-invalid="!!heirErrors.address"
                  @input="clearHeirFieldError('address')"
                />
                <FieldError v-if="heirErrors.address">{{ heirErrors.address }}</FieldError>
              </Field>
              <Field class="md:col-span-2">
                <CheckboxRoot
                  :checked="heirForm.is_primary"
                  :disabled="savingHeir"
                  @checked-change="({ checked }) => (heirForm.is_primary = checked === true)"
                >
                  <CheckboxControl />
                  <CheckboxLabel>Pewaris utama</CheckboxLabel>
                </CheckboxRoot>
              </Field>
            </div>
          </FieldGroup>
        </form>
      </div>
    </Box>
  </div>
</template>
