<script setup lang="ts">
// Components
import { toast } from '~/components/pub/ui/toast'
import { Button } from '~/components/pub/ui/button'
import AppEncounterEntryForm from '~/components/app/encounter/entry-form.vue'
import AppViewPatient from '~/components/app/patient/view-patient.vue'

// Types
import type { DataTableLoader } from '~/components/pub/my-ui/data-table/type'
import type { TreeItem } from '~/components/pub/my-ui/select-tree/type'

// Constants
import { paymentTypes, sepRefTypeCodes, participantGroups } from '~/lib/constants.vclaim'

// Services
import {
  getList as getSpecialistList,
  getValueTreeItems as getSpecialistTreeItems,
} from '~/services/specialist.service'
import { getValueLabelList as getDoctorValueLabelList } from '~/services/doctor.service'
import { create as createEncounter } from '~/services/encounter.service'

// Handlers
import {
  patients,
  selectedPatient,
  selectedPatientObject,
  paginationMeta,
  getPatientsList,
  getPatientCurrent,
  getPatientByIdentifierSearch,
} from '~/handlers/patient.handler'

// Stores
import { useUserStore } from '~/stores/user'



const props = defineProps<{
  id: number
  classCode?: 'ambulatory' | 'emergency' | 'inpatient'
  subClassCode?: 'reg' | 'rehab' | 'chemo' | 'emg' | 'eon' | 'op' | 'icu' | 'hcu' | 'vk'
  formType: string
}>()

const route = useRoute()
const userStore = useUserStore()
const openPatient = ref(false)
const isLoading = reactive<DataTableLoader>({
  isTableLoading: false,
})
const paymentsList = ref<Array<{ value: string; label: string }>>([])
const sepsList = ref<Array<{ value: string; label: string }>>([])
const participantGroupsList = ref<Array<{ value: string; label: string }>>([])
const specialistsTree = ref<TreeItem[]>([])
const specialistsData = ref<any[]>([]) // Store full specialist data with id
const doctorsList = ref<Array<{ value: string; label: string }>>([])
const recSelectId = ref<number | null>(null)
const isSaving = ref(false)
const formRef = ref<InstanceType<typeof AppEncounterEntryForm> | null>(null)

// Computed for save button disable state
const isSaveDisabled = computed(() => {
  return !selectedPatient.value || !selectedPatientObject.value || isSaving.value
})

function handleSavePatient() {
  selectedPatientObject.value = null
  setTimeout(() => {
    getPatientCurrent(selectedPatient.value)
  }, 150)
}

function toKebabCase(str: string): string {
  return str.replace(/([A-Z])/g, '-$1').toLowerCase()
}

function toNavigateSep(values: any) {
  const queryParams = new URLSearchParams()
  if (values['subSpecialistCode']) {
    const isSub = isSubspecialist(values['subSpecialistCode'], specialistsTree.value)
    if (!isSub) {
      values['specialistCode'] = values['subSpecialistCode']
      delete values['subSpecialistCode']
    }
  }

  Object.keys(values).forEach((field) => {
    if (values[field]) {
      queryParams.append(toKebabCase(field), values[field])
    }
  })

  navigateTo('/integration/bpjs/sep/add' + `?${queryParams.toString()}`)
}

async function handleSaveEncounter(formValues: any) {
  // Validate patient is selected
  if (!selectedPatient.value || !selectedPatientObject.value) {
    toast({
      title: 'Gagal',
      description: 'Pasien harus dipilih terlebih dahulu',
      variant: 'destructive',
    })
    return
  }

  try {
    isSaving.value = true

    // Get employee_id from user store
    const employeeId = userStore.user?.employee_id || userStore.user?.employee?.id || 0

    // Format date to ISO format
    const formatDate = (dateString: string): string => {
      if (!dateString) return ''
      const date = new Date(dateString)
      return date.toISOString()
    }

    // Get specialist_id and subspecialist_id from TreeSelect value (code)
    const { specialist_id, subspecialist_id } = getSpecialistIdsFromCode(formValues.subSpecialistId || '')

    // Build payload
    const payload: any = {
      patient_id: selectedPatientObject.value?.id || Number(selectedPatient.value),
      registeredAt: formatDate(formValues.registerDate),
      visitDate: formatDate(formValues.registerDate),
      class_code: props.classCode || '',
      subClass_code: props.subClassCode || '',
      infra_id: null,
      unit_id: null,
      appointment_doctor_id: Number(formValues.doctorId),
      responsible_doctor_id: Number(formValues.doctorId),
      paymentType: formValues.paymentType,
      cardNumber: formValues.cardNumber,
      refSource_name: '',
      appointment_id: null,
    }

    if (employeeId && employeeId > 0) {
      payload.adm_employee_id = employeeId
    }

    // Add specialist_id and subspecialist_id if available
    if (specialist_id) {
      payload.specialist_id = specialist_id
    }
    if (subspecialist_id) {
      payload.subspecialist_id = subspecialist_id
    }

    if (formValues.paymentType === 'jkn') {
      payload.paymentMethod_code = 'insurance'
      payload.insuranceCompany_id = null
      payload.member_number = formValues.cardNumber
      payload.ref_number = formValues.sepNumber
    }

    // Add visitMode_code and allocatedVisitCount only if classCode is ambulatory
    if (props.classCode === 'ambulatory') {
      payload.visitMode_code = 'adm'
      payload.allocatedVisitCount = 0
    }

    // Call encounter service
    const result = await createEncounter(payload)

    if (result.success) {
      toast({
        title: 'Berhasil',
        description: 'Kunjungan berhasil dibuat',
        variant: 'default',
      })
      // Optionally navigate or reset form
      // navigateTo(`/encounter/${result.body?.data?.id}`)
    } else {
      const errorMessage = result.body?.message || 'Gagal membuat kunjungan'
      toast({
        title: 'Gagal',
        description: errorMessage,
        variant: 'destructive',
      })
    }
  } catch (error: any) {
    console.error('Error saving encounter:', error)
    toast({
      title: 'Gagal',
      description: error?.message || 'Gagal membuat kunjungan',
      variant: 'destructive',
    })
  } finally {
    isSaving.value = false
  }
}

async function handleEvent(menu: string, value?: any) {
  if (menu === 'search') {
    getPatientsList({ 'page-size': 10, includes: 'person' }).then(() => {
      openPatient.value = true
    })
  } else if (menu === 'add') {
    navigateTo('/client/patient/add')
  } else if (menu === 'add-sep') {
    recSelectId.value = null
    toNavigateSep({
      isService: 'false',
      sourcePath: route.path,
      resource: `${props.classCode}-${props.subClassCode}`,
      ...value,
    })
  } else if (menu === 'save') {
    await handleSaveEncounter(value)
  } else if (menu === 'cancel') {
    console.log('Cancel')
  }
}

async function handleFetchSpecialists() {
  try {
    const specialistsResult = await getSpecialistList({ 'page-size': 100, includes: 'subspecialists' })
    if (specialistsResult.success) {
      const specialists = specialistsResult.body?.data || []
      specialistsData.value = specialists // Store full data for mapping
      specialistsTree.value = getSpecialistTreeItems(specialists)
    }
  } catch (error) {
    console.error('Error fetching specialist-subspecialist tree:', error)
  }
}

/**
 * Helper function to check if a value exists in the specialistsTree
 * Returns true if it's a leaf node (subspecialist), false if parent node (specialist)
 */
function isSubspecialist(value: string, items: TreeItem[]): boolean {
  for (const item of items) {
    if (item.value === value) {
      // If this item has children, it's not selected, so skip
      // If this is the selected item, check if it has children in the tree
      return false // This means it's a specialist, not a subspecialist
    }
    if (item.children) {
      for (const child of item.children) {
        if (child.value === value) {
          // This is a subspecialist (leaf node)
          return true
        }
      }
    }
  }
  return false
}

/**
 * Helper function to find specialist_id and subspecialist_id from TreeSelect value (code)
 * Returns { specialist_id: number | null, subspecialist_id: number | null }
 */
function getSpecialistIdsFromCode(code: string): { specialist_id: number | null; subspecialist_id: number | null } {
  if (!code) {
    return { specialist_id: null, subspecialist_id: null }
  }

  // Check if it's a subspecialist
  const isSub = isSubspecialist(code, specialistsTree.value)

  if (isSub) {
    // Find subspecialist and its parent specialist
    for (const specialist of specialistsData.value) {
      if (specialist.subspecialists && Array.isArray(specialist.subspecialists)) {
        for (const subspecialist of specialist.subspecialists) {
          if (subspecialist.code === code) {
            return {
              specialist_id: specialist.id ? Number(specialist.id) : null,
              subspecialist_id: subspecialist.id ? Number(subspecialist.id) : null,
            }
          }
        }
      }
    }
  } else {
    // It's a specialist
    for (const specialist of specialistsData.value) {
      if (specialist.code === code) {
        return {
          specialist_id: specialist.id ? Number(specialist.id) : null,
          subspecialist_id: null,
        }
      }
    }
  }

  return { specialist_id: null, subspecialist_id: null }
}

async function handleFetchDoctors(subSpecialistId: string | null = null) {
  try {
    // Build filter based on selection type
    const filterParams: any = { 'page-size': 100, includes: 'employee-Person' }

    if (!subSpecialistId) {
      const doctors = await getDoctorValueLabelList(filterParams)
      doctorsList.value = doctors
      return
    }

    // Check if the selectd value is a subspecialist or specialist
    const isSub = isSubspecialist(subSpecialistId, specialistsTree.value)

    if (isSub) {
      // If selected is subspecialist, filter by subspecialist-id
      filterParams['subspecialist-id'] = subSpecialistId
    } else {
      // If selected is specialist, filter by specialist-id
      filterParams['specialist-id'] = subSpecialistId
    }

    const doctors = await getDoctorValueLabelList(filterParams)
    doctorsList.value = doctors
  } catch (error) {
    console.error('Error fetching doctors:', error)
    doctorsList.value = []
  }
}

function handleFetch(value?: any) {
  if (value?.subSpecialistId) {
    // handleFetchDoctors(value.subSpecialistId)
  }
}

async function handleInit() {
  paymentsList.value = Object.keys(paymentTypes).map((item) => ({
    value: item.toString(),
    label: paymentTypes[item],
  })) as any
  sepsList.value = Object.keys(sepRefTypeCodes).map((item) => ({
    value: item.toString(),
    label: sepRefTypeCodes[item],
  })) as any
  participantGroupsList.value = Object.keys(participantGroups).map((item) => ({
    value: item.toString(),
    label: participantGroups[item],
  })) as any
  // Fetch tree data
  await handleFetchDoctors()
  await handleFetchSpecialists()
}

provide('rec_select_id', recSelectId)
provide('table_data_loader', isLoading)

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

<template>
  <div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
    <Icon
      name="i-lucide-user"
      class="me-2"
    />
    <span class="font-semibold">{{ props.formType }}</span>
    Kunjungan
  </div>

  <AppEncounterEntryForm
    ref="formRef"
    :payments="paymentsList"
    :seps="sepsList"
    :participant-groups="participantGroupsList"
    :specialists="specialistsTree"
    :doctor="doctorsList"
    :patient="selectedPatientObject"
    @event="handleEvent"
    @fetch="handleFetch"
  />

  <AppViewPatient
    v-model:open="openPatient"
    v-model:selected="selectedPatient"
    :patients="patients"
    :pagination-meta="paginationMeta"
    @fetch="
      (value) => {
        if (value.search && value.search.length >= 3) {
          // Use identifier search for specific searches (NIK, RM, etc.)
          getPatientByIdentifierSearch(value.search)
        } else {
          // Use regular search for general searches
          getPatientsList({ ...value, 'page-size': 10, includes: 'person' })
        }
      }
    "
    @save="handleSavePatient"
  />

  <!-- Footer Actions -->
  <div class="mt-6 flex justify-end gap-2 border-t border-t-slate-300 pt-4">
    <Button
      variant="outline"
      type="button"
      class="h-[40px] min-w-[120px] rounded-md border-orange-400 text-orange-400 hover:bg-green-50 hover:text-orange-400"
      @click="handleEvent('cancel')"
    >
      <Icon
        name="i-lucide-x"
        class="h-5 w-5"
      />
      Batal
    </Button>
    <Button
      type="button"
      class="h-[40px] min-w-[120px] text-white"
      :disabled="isSaveDisabled"
      @click="formRef?.submitForm()"
    >
      <Icon
        name="i-lucide-save"
        class="h-5 w-5"
      />
      Simpan
    </Button>
  </div>
</template>
