<template>
  <UDashboardPanel id="home">
    <template #header>
      <UDashboardNavbar :title="$t('common.home')" :ui="{ right: 'gap-3' }">
        <template #leading>
          <UDashboardSidebarCollapse />
        </template>

        <template #right>
          <UButton
            icon="i-lucide-circle-plus"
            :label="$t('applicationForms.createNew')"
            to="/create"
            :disabled="!canWriteApplicationForms"
            size="xl"
            class="bg-gradient-to-br from-teal-500 to-cyan-500 text-white font-semibold rounded-xl shadow-lg shadow-teal-500/25 hover:from-cyan-500 hover:to-violet-500 hover:shadow-xl hover:shadow-violet-500/30 transition-all duration-200"
          />
        </template>
      </UDashboardNavbar>

      <UDashboardToolbar>
        <UNavigationMenu :items="links" highlight class="-mx-1 flex-1" />
        <USeparator orientation="vertical" class="h-8 mx-2" />
        <FormValidationIndicator :status="validationStatus" />
      </UDashboardToolbar>
    </template>

    <template #body>
      <FormStepperWithNavigation
        :form-element-sections="applicationForm.formElementSections"
        :initial-section-index="sectionIndex"
        :application-form-id="applicationForm.id ?? undefined"
        :disabled="isReadOnly"
        @save="onSave"
        @submit="onSubmit"
        @navigate="handleNavigate"
        @add-input-form="handleAddInputForm"
        @update:form-element-sections="handleFormElementSectionsUpdate"
      >
        <UFormField :label="$t('common.name')" class="mb-4">
          <UInput v-model="applicationForm.name" class="w-full" :disabled="isReadOnly" />
        </UFormField>
      </FormStepperWithNavigation>
    </template>
  </UDashboardPanel>
</template>

<script setup lang="ts">
import {
  ComplianceStatus,
  type ApplicationFormDto,
  type FormElementDto,
  type FormElementSectionDto
} from '~~/.api-client'
import type { FormElementId } from '~~/types/formElement'
import { useApplicationFormValidator } from '~/composables/useApplicationFormValidator'
import { useUserStore } from '~~/stores/useUserStore'
import { useCommentStore } from '~~/stores/useCommentStore'

const route = useRoute()
const toast = useToast()
const { t: $t } = useI18n()
const commentStore = useCommentStore()

definePageMeta({
  // Prevent whole page from re-rendering when navigating between sections to keep state
  key: (route) => `${route.params.id}`
})

const applicationFormId = Array.isArray(route.params.id) ? route.params.id[0] : route.params.id
const {
  applicationForm,
  navigationLinks: links,
  updateApplicationForm
} = await useApplicationFormNavigation(applicationFormId!)

if (applicationFormId) {
  await commentStore.loadCounts(applicationFormId)
}

const { updateApplicationForm: updateForm, submitApplicationForm } = useApplicationForm()
const { validateFormElements, getHighestComplianceStatus } = useApplicationFormValidator()
const { evaluateFormElementVisibility } = useFormElementVisibility()
const { canWriteApplicationForms } = usePermissions()
const userStore = useUserStore()
const { user } = storeToRefs(userStore)

const sectionIndex = computed(() => {
  const param = route.params.sectionIndex
  const index = parseInt(Array.isArray(param) ? param[0]! : (param ?? '0'))
  return !isNaN(index) ? index : 0
})

const isReadOnly = computed(() => {
  return applicationForm.value?.createdBy?.keycloakId !== user.value?.keycloakId
})

// Unsaved changes tracking
const originalFormJson = ref<string>('')

onMounted(async () => {
  await nextTick()
  originalFormJson.value = JSON.stringify(applicationForm.value)
  window.addEventListener('beforeunload', handleBeforeUnload)
})

onUnmounted(() => {
  window.removeEventListener('beforeunload', handleBeforeUnload)
})

const hasUnsavedChanges = computed(() => {
  if (!originalFormJson.value) return false
  return JSON.stringify(applicationForm.value) !== originalFormJson.value
})

function handleBeforeUnload(e: BeforeUnloadEvent) {
  if (hasUnsavedChanges.value) {
    e.preventDefault()
  }
}

onBeforeRouteLeave((to, from, next) => {
  // Allow navigation between sections of the same form
  if (to.params.id === from.params.id) {
    next()
    return
  }

  if (hasUnsavedChanges.value) {
    const answer = window.confirm($t('applicationForms.unsavedWarning'))
    next(answer)
  } else {
    next()
  }
})

const validationMap = ref<Map<FormElementId, ComplianceStatus> | undefined>()
const validationStatus = ref<ComplianceStatus>(ComplianceStatus.NonCritical)

const allFormElements = computed(() => {
  return (
    applicationForm.value?.formElementSections?.flatMap((section: FormElementSectionDto) =>
      section.formElementSubSections.flatMap((subsection) => subsection.formElements)
    ) ?? []
  )
})

const visibilityMap = computed(() => {
  return evaluateFormElementVisibility(allFormElements.value)
})

watch(
  () => allFormElements.value,
  (updatedFormElements: FormElementDto[]) => {
    validationMap.value = validateFormElements(updatedFormElements, visibilityMap.value)
    validationStatus.value = getHighestComplianceStatus()
  },
  { deep: true }
)

// Re-capture baseline after section navigation to absorb initialization effects
// (e.g. TheTable applying row presets, TheEditor normalizing content on mount)
watch(sectionIndex, async () => {
  await nextTick()
  originalFormJson.value = JSON.stringify(applicationForm.value)
})

async function onSave() {
  if (applicationForm.value?.id) {
    const updated = await updateForm(applicationForm.value.id, applicationForm.value)
    if (updated) {
      updateApplicationForm(updated)
      originalFormJson.value = JSON.stringify(updated)
      toast.add({ title: $t('common.success'), description: $t('applicationForms.saved'), color: 'success' })
    }
  }
}

async function onSubmit() {
  if (applicationForm.value?.id) {
    // Save the form first to persist any unsaved changes before submitting
    const updated = await updateForm(applicationForm.value.id, applicationForm.value)
    if (updated) {
      updateApplicationForm(updated)
    }
    await submitApplicationForm(applicationForm.value.id)
    await navigateTo('/')
    toast.add({ title: $t('common.success'), description: $t('applicationForms.submitted'), color: 'success' })
  }
}

async function handleNavigate({ index }: { direction: 'forward' | 'backward'; index: number }) {
  await navigateTo(`/application-forms/${applicationFormId}/${index}`)
}

function handleAddInputForm(updatedForm: ApplicationFormDto | undefined) {
  if (updatedForm) {
    updateApplicationForm(updatedForm)
  }
}

function handleFormElementSectionsUpdate(sections: FormElementSectionDto[]) {
  if (applicationForm.value) {
    applicationForm.value.formElementSections = sections
  }
}
</script>
