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

        <template #right>
          <UButton
            v-if="hasUnsavedChanges"
            icon="i-lucide-rotate-ccw"
            :label="$t('templates.reset')"
            color="neutral"
            variant="outline"
            @click="resetEditor"
          />
          <UButton
            icon="i-lucide-file-plus"
            :label="$t('templates.newTemplate')"
            color="neutral"
            variant="outline"
            @click="createNewTemplate"
          />
          <UButton
            icon="i-lucide-save"
            :label="$t('common.save')"
            :disabled="!hasUnsavedChanges || !isValidJson"
            :loading="isSaving"
            @click="saveTemplate"
          />
        </template>
      </UDashboardNavbar>
    </template>

    <template #body>
      <div class="flex flex-col gap-4 w-full h-full p-4">
        <UCard v-if="currentTemplate" class="mb-4">
          <div class="flex items-center justify-between">
            <div>
              <h3 class="font-semibold text-lg">{{ currentTemplate.name }}</h3>
              <p class="text-sm text-muted mt-1">
                {{ $t('templates.lastModified') }} {{ formatDate(new Date(currentTemplate.modifiedAt)) }}
              </p>
            </div>
            <UBadge v-if="hasUnsavedChanges" :label="$t('templates.unsavedChanges')" color="warning" variant="subtle" />
          </div>
        </UCard>

        <UCard v-else class="mb-4">
          <div class="text-center py-4">
            <UIcon name="i-lucide-info" class="size-8 text-muted mx-auto mb-2" />
            <p class="text-muted">{{ $t('templates.noTemplateFound') }}</p>
          </div>
        </UCard>

        <UCard class="flex-1">
          <div class="h-[800px] overflow-hidden rounded-lg border border-gray-200 dark:border-gray-700">
            <vue-monaco-editor
              v-model:value="editorContent"
              language="json"
              :options="editorOptions"
              :theme="colorMode.value === 'dark' ? 'vs-dark' : 'vs'"
              @change="onEditorChange"
            />
          </div>
        </UCard>

        <UAlert
          v-if="!isValidJson"
          color="error"
          icon="i-lucide-alert-circle"
          :title="$t('templates.invalidJson')"
          :description="$t('templates.invalidJsonDescription')"
        />
      </div>
    </template>
  </UDashboardPanel>
</template>

<script setup lang="ts">
import type { ApplicationFormDto } from '~~/.api-client'
import { VueMonacoEditor } from '@guolao/vue-monaco-editor'
import { formatDate } from '~/utils/date'

definePageMeta({
  layout: 'default'
})

const toast = useToast()
const colorMode = useColorMode()
const { hasRole } = usePermissions()
const { getAllApplicationFormTemplates, updateApplicationFormTemplate, createApplicationFormTemplate } =
  await useApplicationFormTemplate()
const { t: $t } = useI18n()

if (!hasRole('CHIEF_EXECUTIVE_OFFICER') && !hasRole('IT_DEPARTMENT')) {
  await navigateTo('/')
}

const currentTemplate = ref<ApplicationFormDto | null>(null)
const editorContent = ref<string>('')
const originalJson = ref<string>('')
const hasUnsavedChanges = ref(false)
const isValidJson = ref(true)
const isSaving = ref(false)

const editorOptions = {
  automaticLayout: true,
  formatOnPaste: true,
  formatOnType: true,
  fontSize: 14,
  lineNumbers: 'on',
  scrollBeyondLastLine: false,
  wordWrap: 'on',
  wrappingStrategy: 'advanced',
  bracketPairColorization: {
    enabled: true
  },
  guides: {
    bracketPairs: true,
    indentation: true
  },
  suggest: {
    showKeywords: true,
    showSnippets: true
  }
}

const { data: templatesData } = await useAsyncData('applicationFormTemplates', async () => {
  return await getAllApplicationFormTemplates()
})

onMounted(() => {
  if (templatesData.value?.content && templatesData.value.content.length > 0) {
    const sortedTemplates = [...templatesData.value.content].sort((a, b) => {
      const dateA = new Date(a.modifiedAt || 0).getTime()
      const dateB = new Date(b.modifiedAt || 0).getTime()
      return dateB - dateA
    })

    const latestTemplate = sortedTemplates[0]
    if (latestTemplate) {
      currentTemplate.value = latestTemplate
      editorContent.value = JSON.stringify(currentTemplate.value, null, 2)
      originalJson.value = editorContent.value
    }
  } else {
    const emptyTemplate = {
      name: '',
      description: '',
      status: 'DRAFT',
      isTemplate: true,
      organizationId: '',
      sections: []
    }
    editorContent.value = JSON.stringify(emptyTemplate, null, 2)
    originalJson.value = editorContent.value
  }
})

function onEditorChange() {
  try {
    JSON.parse(editorContent.value)
    isValidJson.value = true
    hasUnsavedChanges.value = editorContent.value !== originalJson.value
  } catch {
    isValidJson.value = false
    hasUnsavedChanges.value = true
  }
}

function resetEditor() {
  editorContent.value = originalJson.value
  hasUnsavedChanges.value = false
  isValidJson.value = true
}

function createNewTemplate() {
  currentTemplate.value = null
  const emptyTemplate = {
    name: '',
    description: '',
    status: 'DRAFT',
    isTemplate: true,
    organizationId: '',
    sections: []
  }
  editorContent.value = JSON.stringify(emptyTemplate, null, 2)
  originalJson.value = editorContent.value
  hasUnsavedChanges.value = true
  isValidJson.value = true
}

async function saveTemplate() {
  if (!isValidJson.value) {
    toast.add({
      title: $t('common.error'),
      description: $t('templates.invalidJsonDescription'),
      color: 'error'
    })
    return
  }

  isSaving.value = true

  try {
    const parsedData = JSON.parse(editorContent.value)
    const dataWithDates = convertDates(parsedData) as ApplicationFormDto

    if (currentTemplate.value?.id) {
      currentTemplate.value = await updateApplicationFormTemplate(currentTemplate.value.id, dataWithDates)
      toast.add({
        title: $t('common.success'),
        description: $t('templates.updated'),
        color: 'success'
      })
    } else {
      currentTemplate.value = await createApplicationFormTemplate(dataWithDates)
      toast.add({
        title: $t('common.success'),
        description: $t('templates.created'),
        color: 'success'
      })
    }

    editorContent.value = JSON.stringify(currentTemplate.value, null, 2)
    originalJson.value = editorContent.value
    hasUnsavedChanges.value = false

    await refreshNuxtData('applicationFormTemplates')
  } catch (error) {
    toast.add({
      title: $t('common.error'),
      description: $t('templates.saveError'),
      color: 'error'
    })
    console.error('Error saving template:', error)
  } finally {
    isSaving.value = false
  }
}

onBeforeRouteLeave((to, from, next) => {
  if (hasUnsavedChanges.value) {
    const answer = window.confirm($t('templates.unsavedWarning'))
    if (answer) {
      next()
    } else {
      next(false)
    }
  } else {
    next()
  }
})

function convertDates(obj: unknown): unknown {
  if (obj === null || obj === undefined) return obj

  if (typeof obj === 'string') {
    const date = new Date(obj)
    if (!isNaN(date.getTime()) && obj.includes('T') && (obj.includes('Z') || obj.includes('+'))) {
      return date
    }
    return obj
  }

  if (Array.isArray(obj)) {
    return obj.map((item) => convertDates(item))
  }

  if (typeof obj === 'object') {
    const converted: Record<string, unknown> = {}
    for (const key in obj as Record<string, unknown>) {
      if (key === 'createdAt' || key === 'modifiedAt') {
        const value = (obj as Record<string, unknown>)[key]
        converted[key] = value ? new Date(value as string) : value
      } else {
        converted[key] = convertDates((obj as Record<string, unknown>)[key])
      }
    }
    return converted
  }

  return obj
}
</script>
