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

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

    <template #body>
      <div v-if="!canWriteApplicationForms" class="text-center py-12">
        <UIcon name="i-lucide-shield-x" class="w-16 h-16 mx-auto text-red-400 mb-4" />
        <h2 class="text-2xl font-semibold text-gray-700 mb-2">{{ $t('applicationForms.noPermission') }}</h2>
        <p class="text-gray-500 mb-4">{{ $t('applicationForms.noPermissionDescription') }}</p>
        <UButton to="/" class="mt-4"> {{ $t('applicationForms.backToOverview') }} </UButton>
      </div>
      <div v-else-if="applicationFormTemplate">
        <FormStepperWithNavigation
          :form-element-sections="applicationFormTemplate.formElementSections"
          @save="onSave"
          @submit="onSubmit"
          @add-input-form="handleAddInputForm"
          @update:form-element-sections="handleFormElementSectionsUpdate"
        >
          <UFormField :label="$t('common.name')" class="mb-4">
            <UInput v-model="applicationFormTemplate.name" class="w-full" />
          </UFormField>
        </FormStepperWithNavigation>
      </div>
    </template>
  </UDashboardPanel>

  <!-- Recovery Modal - outside UDashboardPanel to avoid SSR Teleport hydration conflicts -->
  <UModal
    :open="showRecoveryModal"
    :title="$t('applicationForms.recovery.title')"
    @update:open="showRecoveryModal = $event"
  >
    <template #body>
      <p class="text-sm text-(--ui-text-muted)">
        {{
          $t('applicationForms.recovery.message', {
            timestamp: backupTimestamp?.toLocaleString()
          })
        }}
      </p>
    </template>

    <template #footer>
      <UButton color="neutral" variant="outline" @click="handleDiscardBackup">
        {{ $t('applicationForms.recovery.discard') }}
      </UButton>
      <UButton color="primary" @click="handleRestoreBackup">
        {{ $t('applicationForms.recovery.restore') }}
      </UButton>
    </template>
  </UModal>
</template>

<script setup lang="ts">
import { watchDebounced } from '@vueuse/core'
import {
  ComplianceStatus,
  type FormElementDto,
  type FormElementSectionDto,
  type PagedApplicationFormDto
} from '~~/.api-client'
import { useApplicationFormValidator } from '~/composables/useApplicationFormValidator'
import { useLocalStorageBackup } from '~/composables/useLocalStorageBackup'
import type { FormElementId } from '~~/types/formElement'
import { useUserStore } from '~~/stores/useUserStore'

const { getAllApplicationFormTemplates } = useApplicationFormTemplate()
const { createApplicationForm, submitApplicationForm } = useApplicationForm()
const { validateFormElements, getHighestComplianceStatus } = useApplicationFormValidator()
const { evaluateFormElementVisibility } = useFormElementVisibility()
const { canWriteApplicationForms } = usePermissions()
const userStore = useUserStore()
const { selectedOrganization } = storeToRefs(userStore)
const toast = useToast()
const { t: $t } = useI18n()
const logger = useLogger().withTag('create')

const { data, error } = await useAsyncData<PagedApplicationFormDto>(
  'create-application-form',
  async () => {
    return await getAllApplicationFormTemplates()
  },
  { deep: true }
)

if (error.value) {
  throw createError({ statusText: error.value.message })
}

const applicationFormTemplate = computed(
  // TODO: Don't select always the first item, allow user to select a template
  () => data?.value?.content[0] ?? undefined
)

// LocalStorage backup for auto-save (using 'create' as key for new forms)
const { hasBackup, backupTimestamp, saveBackup, loadBackup, clearBackup } = useLocalStorageBackup('create')

const showRecoveryModal = ref(false)

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

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

onMounted(() => {
  originalFormJson.value = JSON.stringify(applicationFormTemplate.value)
  window.addEventListener('beforeunload', handleBeforeUnload)

  // Show recovery modal if backup exists
  if (hasBackup.value) {
    showRecoveryModal.value = true
  }
})

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

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

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

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

const allFormElements = computed(() => {
  return (
    applicationFormTemplate.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 }
)

// Auto-save to localStorage with 5 second debounce
watchDebounced(
  () => applicationFormTemplate.value,
  (form) => {
    if (form && hasUnsavedChanges.value) {
      saveBackup(form, 0)
    }
  },
  { debounce: 5000, deep: true }
)

function handleRestoreBackup() {
  const backupData = loadBackup()
  if (backupData && data.value?.content[0]) {
    // Restore the backed up form data to the template
    Object.assign(data.value.content[0], backupData)
    originalFormJson.value = JSON.stringify(backupData)
    showRecoveryModal.value = false
    clearBackup()

    toast.add({
      title: $t('common.success'),
      description: $t('applicationForms.recovery.restore'),
      color: 'success'
    })
  }
}

function handleDiscardBackup() {
  clearBackup()
  showRecoveryModal.value = false
}

async function onSave() {
  const applicationForm = await prepareAndCreateApplicationForm()
  if (applicationForm?.id) {
    // Reset to prevent unsaved changes warning when navigating
    originalFormJson.value = JSON.stringify(applicationFormTemplate.value)
    clearBackup()
    toast.add({ title: $t('common.success'), description: $t('applicationForms.saved'), color: 'success' })
    await navigateTo(`/application-forms/${applicationForm.id}/0`)
  }
}

async function onSubmit() {
  const applicationForm = await prepareAndCreateApplicationForm()
  if (applicationForm?.id) {
    await submitApplicationForm(applicationForm.id)
    // Reset to prevent unsaved changes warning when navigating
    originalFormJson.value = JSON.stringify(applicationFormTemplate.value)
    clearBackup()
    await navigateTo('/')
    toast.add({ title: $t('common.success'), description: $t('applicationForms.submitted'), color: 'success' })
  }
}

function handleAddInputForm() {
  // In create mode (no applicationFormId), addInputFormToApplicationForm returns undefined
  // The form element is added locally to the template sections, which are reactive
  // No action needed here
}

function handleFormElementSectionsUpdate(sections: FormElementSectionDto[]) {
  if (applicationFormTemplate.value) {
    applicationFormTemplate.value.formElementSections = sections
  }
}

async function prepareAndCreateApplicationForm() {
  if (!applicationFormTemplate.value) {
    logger.error('Application form data is undefined')
    return null
  }

  logger.debug('selectedOrganization', selectedOrganization.value)
  applicationFormTemplate.value.organizationId = selectedOrganization.value?.id ?? ''

  return await createApplicationForm(applicationFormTemplate.value)
}
</script>
