<script setup>
import {ref, computed, watch, onMounted, onUnmounted} from 'vue';
import DocumentDisplayModal from "~/components/DocumentDisplayModal.vue";
import DocumentUploadModal from "~/components/DocumentUploadModal.vue";
import FileScanModal from "~/components/FileScanModal.vue";
import dayjs from "dayjs";

// --- Services & Stores ---
const dataStore = useDataStore()
const tempStore = useTempStore()
const router = useRouter()
const route = useRoute()
const modal = useModal()
const toast = useToast()
const {$api} = useNuxtApp()
const files = useFiles()

// --- State ---
const documents = ref([])
const folders = ref([])
const filetags = ref([])
const currentFolder = ref(null)
const loadingDocs = ref(true)
const loaded = ref(false)
const displayMode = ref("list")
const displayModes = [
  {label: 'Liste', key: 'list', icon: 'i-heroicons-list-bullet'},
  {label: 'Kacheln', key: 'rectangles', icon: 'i-heroicons-squares-2x2'}
]

const createFolderModalOpen = ref(false)
const initialCreateFolderData = { name: '', standardFiletype: null, standardFiletypeIsOptional: true }
const createFolderData = ref({ ...initialCreateFolderData })

const renameModalOpen = ref(false)
const renameData = ref({id: null, name: '', type: ''})

const selectedFileIndex = ref(0)
const draggedItem = ref(null)

const getEntryActions = (entry) => [[
  {
    label: 'Umbenennen',
    icon: 'i-heroicons-pencil-square',
    onSelect: () => openRenameModal(entry)
  }
]]

// --- Search & Debounce ---
const searchString = ref(tempStore.searchStrings["files"] || '')
const debouncedSearch = ref(searchString.value)
let debounceTimeout = null

watch(searchString, (val) => {
  clearTimeout(debounceTimeout)
  debounceTimeout = setTimeout(() => {
    debouncedSearch.value = val
    tempStore.modifySearchString('files', val)
  }, 300)
})

// --- Data Fetching ---
const setupPage = async () => {
  loadingDocs.value = true
  try {
    const [fRes, dRes, tRes] = await Promise.all([
      useEntities("folders").select(),
      files.selectDocuments(),
      useEntities("filetags").select()
    ])
    folders.value = fRes || []
    documents.value = dRes || []
    filetags.value = tRes || []

    syncCurrentFolderFromRoute()
  } finally {
    loadingDocs.value = false
    loaded.value = true
  }
}

// --- Global Drag & Drop (Auto-Open Upload Modal) ---
let dragCounter = 0
const uploadModalOpening = ref(false)

const handleGlobalDragEnter = (e) => {
  dragCounter++
  if (draggedItem.value) return
  if (uploadModalOpening.value) return
  if (e.dataTransfer && e.dataTransfer.types && e.dataTransfer.types.includes('Files')) {
    uploadModalOpening.value = true

    modal.open(DocumentUploadModal, {
      fileData: {
        folder: currentFolder.value?.id,
        type: currentFolder?.value?.standardFiletype,
        typeEnabled: currentFolder?.value?.standardFiletype ? currentFolder?.value?.standardFiletypeIsOptional : true
      },
      onUploadFinished: () => {
        setupPage()
        dragCounter = 0
      }
    }).finally(() => {
      dragCounter = 0
      uploadModalOpening.value = false
    })
  }
}

const handleGlobalDragLeave = (e) => {
  dragCounter--
}

const handleGlobalDrop = (e) => {
  dragCounter = 0
  e.preventDefault()
}

const handleGlobalDragOver = (e) => {
  e.preventDefault()
}

onMounted(() => {
  setupPage()
  window.addEventListener('dragenter', handleGlobalDragEnter)
  window.addEventListener('dragleave', handleGlobalDragLeave)
  window.addEventListener('dragover', handleGlobalDragOver)
  window.addEventListener('drop', handleGlobalDrop)
})

onUnmounted(() => {
  window.removeEventListener('dragenter', handleGlobalDragEnter)
  window.removeEventListener('dragleave', handleGlobalDragLeave)
  window.removeEventListener('dragover', handleGlobalDragOver)
  window.removeEventListener('drop', handleGlobalDrop)
})


// --- Navigation ---
const getRouteFolderId = () => {
  const folder = route.query?.folder
  return Array.isArray(folder) ? folder[0] : folder
}

const syncCurrentFolderFromRoute = () => {
  const folderId = getRouteFolderId()
  currentFolder.value = folderId ? folders.value.find(i => i.id === folderId) || null : null
  selectedFileIndex.value = 0
}

const changeFolder = async (folder) => {
  currentFolder.value = folder || null
  selectedFileIndex.value = 0
  await router.push({
    path: '/files',
    query: folder ? { folder: folder.id } : {}
  })
}

const navigateUp = () => {
  if (!currentFolder.value) return
  const parent = folders.value.find(f => f.id === currentFolder.value.parent)
  changeFolder(parent || null)
}

watch(() => route.query?.folder, () => {
  syncCurrentFolderFromRoute()
})

// --- Drag & Drop (Internal Sort) ---
const handleDragStart = (entry) => {
  draggedItem.value = entry
}

const handleDrop = async (targetFolderId) => {
  if (!draggedItem.value) return
  if (draggedItem.value.id === targetFolderId) return

  loadingDocs.value = true
  try {
    if (draggedItem.value.type === 'file') {
      await useEntities("files").update(draggedItem.value.id, {folder: targetFolderId})
    } else {
      await useEntities("folders").update(draggedItem.value.id, {parent: targetFolderId})
    }
    toast.add({title: 'Erfolgreich verschoben', icon: 'i-heroicons-check-circle', color: 'green'})
    await setupPage()
  } catch (e) {
    toast.add({title: 'Fehler beim Verschieben', color: 'red'})
  } finally {
    draggedItem.value = null
    loadingDocs.value = false
  }
}

// --- Breadcrumbs ---
const breadcrumbItems = computed(() => {
  const items = [{
    label: "Dateien",
    icon: "i-heroicons-home",
    to: "/files",
    exact: true
  }]

  if (!currentFolder.value) return items

  const path = []
  const seenFolderIds = new Set()
  let curr = currentFolder.value

  while (curr && !seenFolderIds.has(curr.id)) {
    seenFolderIds.add(curr.id)
    path.unshift(curr)
    curr = folders.value.find(f => f.id === curr.parent)
  }

  return [
    ...items,
    ...path.map((folder, index) => ({
      label: folder.name,
      icon: "i-heroicons-folder",
      to: {
        path: "/files",
        query: { folder: folder.id }
      },
      exact: true,
      exactQuery: true,
      disabled: index === path.length - 1
    }))
  ]
})

// --- Data Mapping ---
const renderedFileList = computed(() => {
  const folderList = folders.value
      .filter(i => currentFolder.value ? i.parent === currentFolder.value.id : !i.parent)
      .map(i => ({...i, label: i.name, type: "folder"}))
      .sort((a, b) => a.label.localeCompare(b.label))

  const fileList = documents.value
      .filter(i => currentFolder.value ? i.folder === currentFolder.value.id : !i.folder)
      .map(i => ({...i, label: i.path.split("/").pop(), type: "file"}))
      .sort((a, b) => a.label.localeCompare(b.label))

  let combined = [...folderList, ...fileList]
  if (debouncedSearch.value) {
    combined = useSearch(debouncedSearch.value, combined)
  }

  if (currentFolder.value && !debouncedSearch.value) {
    combined.unshift({
      id: 'go-up',
      label: '..',
      type: 'up',
      parentId: currentFolder.value.parent || null
    })
  }
  return combined
})

// --- Logic: Mandatory File Types ---
// Prüft, ob der aktuelle Ordner strikte Vorgaben macht
const isParentTypeMandatory = computed(() => {
  return currentFolder.value
      && currentFolder.value.standardFiletype
      && !currentFolder.value.standardFiletypeIsOptional
})

// Überwacht das Öffnen des "Ordner erstellen" Modals, um Vorgaben zu setzen
watch(createFolderModalOpen, (isOpen) => {
  if (isOpen) {
    if (isParentTypeMandatory.value) {
      // Wenn Elternordner strikt ist: Werte übernehmen und erzwingen
      createFolderData.value = {
        name: '',
        standardFiletype: currentFolder.value.standardFiletype,
        standardFiletypeIsOptional: false // Muss auch false sein, damit Kette weitergeht
      }
    } else {
      // Reset auf Standardwerte
      createFolderData.value = { ...initialCreateFolderData }
    }
  }
})


// --- Actions ---
const createFolder = async () => {
  await useEntities("folders").create({
    parent: currentFolder.value?.id,
    name: createFolderData.value.name,
    standardFiletype: createFolderData.value.standardFiletype,
    standardFiletypeIsOptional: createFolderData.value.standardFiletypeIsOptional
  })
  createFolderModalOpen.value = false
  // Reset passiert beim nächsten Öffnen durch den Watcher, aber sicherheitshalber hier clean
  createFolderData.value = { ...initialCreateFolderData }
  setupPage()
}

const openRenameModal = (entry) => {
  renameData.value = {id: entry.id, name: entry.label, type: entry.type}
  renameModalOpen.value = true
}

const updateName = async () => {
  if (!renameData.value.name) return
  loadingDocs.value = true
  try {
    if (renameData.value.type === 'folder') {
      await useEntities("folders").update(renameData.value.id, {name: renameData.value.name})
    } else {
      const file = documents.value.find(d => d.id === renameData.value.id)
      const pathParts = file.path.split('/')
      pathParts[pathParts.length - 1] = renameData.value.name
      await useEntities("files").update(renameData.value.id, {path: pathParts.join('/')})
    }
    toast.add({title: 'Umbenannt', color: 'green'})
    setupPage()
  } finally {
    renameModalOpen.value = false
    loadingDocs.value = false
  }
}

const showFile = (fileId) => {
  modal.open(DocumentDisplayModal, {
    documentData: documents.value.find(i => i.id === fileId),
    onUpdatedNeeded: () => setupPage()
  })
}

const openScanModal = () => {
  modal.open(FileScanModal, {
    scanData: {
      folder: currentFolder.value?.id,
      type: currentFolder.value?.standardFiletype,
      typeEnabled: currentFolder.value?.standardFiletype ? currentFolder.value?.standardFiletypeIsOptional : true
    },
    onScanFinished: setupPage
  })
}

const isDialogOpen = computed(() => createFolderModalOpen.value || renameModalOpen.value)

defineShortcuts({
  '/': () => document.getElementById("searchinput")?.focus(),
  'Enter': {
    usingInput: false,
    handler: () => {
      if (isDialogOpen.value) return

      const entry = renderedFileList.value[selectedFileIndex.value]
      if (!entry) return
      if (entry.type === "file") showFile(entry.id)
      else if (entry.type === "folder") changeFolder(entry)
      else if (entry.type === "up") navigateUp()
    }
  },
  'arrowdown': () => {
    if (selectedFileIndex.value < renderedFileList.value.length - 1) selectedFileIndex.value++
  },
  'arrowup': () => {
    if (selectedFileIndex.value > 0) selectedFileIndex.value--
  }
})

const isSyncing = ref(false)

const syncdokubox = async () => {
  isSyncing.value = true
  try {
    await $api('/api/functions/services/syncdokubox', {method: 'POST'})
    toast.add({
      title: 'Erfolg',
      description: 'Dokubox wurde synchronisiert.',
      icon: 'i-heroicons-check-circle',
      color: 'green'
    })
    await setupPage()
  } catch (error) {
    console.error(error)
    toast.add({
      title: 'Fehler',
      description: 'Beim Synchronisieren der Dokubox ist ein Fehler aufgetreten.',
      icon: 'i-heroicons-exclamation-circle',
      color: 'red'
    })
  } finally {
    isSyncing.value = false
  }
}
</script>

<template>
  <UDashboardNavbar title="Dateien">
    <template #right>
      <UButton
          label="Dokubox Sync"
          icon="i-heroicons-sparkles"
          color="primary"
          variant="solid"
          :loading="isSyncing"
          @click="syncdokubox"
          class="mr-2"
      />
      <UInput id="searchinput" v-model="searchString" icon="i-heroicons-magnifying-glass" placeholder="Suche..." class="w-64"/>
    </template>
  </UDashboardNavbar>

  <UDashboardToolbar class="sticky top-0 z-30 bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800">
    <template #left>
      <UBreadcrumb :items="breadcrumbItems"/>
    </template>
    <template #right>
      <USelectMenu v-model="displayMode" :items="displayModes" value-key="key" class="w-32" :content="{ zIndex: 'z-50' }">
        <template #default>
          <UIcon :name="displayModes.find(i => i.key === displayMode).icon" class="w-4 h-4"/>
          <span>{{ displayModes.find(i => i.key === displayMode).label }}</span>
        </template>
      </USelectMenu>
      <UButtonGroup size="sm">
        <UButton icon="i-heroicons-document-plus" color="primary"
                 @click="modal.open(DocumentUploadModal, { fileData: { folder: currentFolder?.id,type: currentFolder?.standardFiletype, typeEnabled: currentFolder?.standardFiletype ? currentFolder?.standardFiletypeIsOptional : true }, onUploadFinished: setupPage })">
          Datei
        </UButton>
        <UButton icon="i-heroicons-document-magnifying-glass" color="neutral" @click="openScanModal">
          Scan
        </UButton>
        <UButton icon="i-heroicons-folder-plus" color="white" @click="createFolderModalOpen = true">Ordner</UButton>
      </UButtonGroup>
    </template>
  </UDashboardToolbar>

  <UDashboardPanelContent class="p-0 overflow-y-auto">
    <div v-if="!loaded" class="p-10 flex justify-center">
      <UProgress animation="carousel" class="w-1/2"/>
    </div>

      <div v-else>
        <div v-if="displayMode === 'list'">
          <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-800">
          <thead class="bg-gray-50 dark:bg-gray-800 sticky top-0 z-20">
          <tr>
            <th class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold sm:pl-6">Name</th>
            <th class="px-3 py-3.5 text-left text-sm font-semibold">Erstellt</th>
            <th class="relative py-3.5 pl-3 pr-4 sm:pr-6"></th>
          </tr>
          </thead>
          <tbody class="divide-y divide-gray-200 dark:divide-gray-800 bg-white dark:bg-gray-900">
          <tr
              v-for="(entry, index) in renderedFileList" :key="entry.id"
              :draggable="entry.type !== 'up'"
              @dragstart="handleDragStart(entry)"
              @dragover.prevent
              @drop="entry.type === 'folder' ? handleDrop(entry.id) : (entry.type === 'up' ? handleDrop(entry.parentId) : null)"
              class="hover:bg-gray-50 dark:hover:bg-gray-800/50 cursor-pointer transition-colors"
              :class="{'bg-primary-50 dark:bg-primary-900/10': index === selectedFileIndex}"
              @click="entry.type === 'folder' ? changeFolder(entry) : (entry.type === 'up' ? navigateUp() : showFile(entry.id))"
          >
            <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
              <div class="flex items-center font-medium">
                <UIcon
                    :name="entry.type === 'up' ? 'i-heroicons-arrow-uturn-left' : (entry.type === 'folder' ? 'i-heroicons-folder-solid' : 'i-heroicons-document-text')"
                    class="h-5 w-5 mr-3"
                    :class="entry.type === 'up' ? 'text-orange-500' : (entry.type === 'folder' ? 'text-primary-500' : 'text-gray-400')"
                />
                {{ entry.label }}
              </div>
            </td>
            <td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
              {{ entry.type !== 'up' ? dayjs(entry.createdAt).format("DD.MM.YY") : '-' }}
            </td>
            <td class="px-3 text-right" @click.stop>
              <UDropdownMenu
                  v-if="entry.type !== 'up'"
                  :items="getEntryActions(entry)"
                  :content="{ align: 'end' }"
              >
                <UButton color="neutral" variant="ghost" icon="i-heroicons-ellipsis-horizontal"/>
              </UDropdownMenu>
            </td>
          </tr>
          <tr v-if="renderedFileList.length === 0">
            <td colspan="3" class="px-6 py-16 text-center text-sm text-gray-500">
              Keine Dateien oder Ordner vorhanden.
            </td>
          </tr>
          </tbody>
        </table>
      </div>

      <div v-else class="p-6 grid grid-cols-2 sm:grid-cols-4 md:grid-cols-6 lg:grid-cols-8 gap-4">
        <div
            v-for="entry in renderedFileList" :key="entry.id"
            :draggable="entry.type !== 'up'"
            @dragstart="handleDragStart(entry)"
            @dragover.prevent
            @drop="entry.type === 'folder' ? handleDrop(entry.id) : (entry.type === 'up' ? handleDrop(entry.parentId) : null)"
            class="group relative bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl p-4 flex flex-col items-center hover:border-primary-500 transition-all cursor-pointer"
            @click="entry.type === 'folder' ? changeFolder(entry) : (entry.type === 'up' ? navigateUp() : showFile(entry.id))"
        >
          <UDropdownMenu
              v-if="entry.type !== 'up'"
              :items="getEntryActions(entry)"
              :content="{ align: 'end' }"
              class="absolute top-1 right-1 opacity-0 group-hover:opacity-100"
              @click.stop
          >
            <UButton color="neutral" variant="ghost" icon="i-heroicons-ellipsis-vertical" size="xs"/>
          </UDropdownMenu>
          <UIcon
              :name="entry.type === 'up' ? 'i-heroicons-arrow-uturn-left' : (entry.type === 'folder' ? 'i-heroicons-folder-solid' : 'i-heroicons-document-text')"
              class="w-12 h-12 mb-2"
              :class="entry.type === 'up' ? 'text-orange-500' : (entry.type === 'folder' ? 'text-primary-500' : 'text-gray-400')"
          />
          <span class="text-xs font-medium text-center truncate w-full">{{ entry.label }}</span>
        </div>
        <div
            v-if="renderedFileList.length === 0"
            class="col-span-full rounded-xl border border-dashed border-gray-300 dark:border-gray-700 px-6 py-16 text-center text-sm text-gray-500"
        >
          Keine Dateien oder Ordner vorhanden.
        </div>
      </div>
    </div>
  </UDashboardPanelContent>

  <UModal v-model:open="createFolderModalOpen">
    <template #content>
      <UCard class="shadow-xl ring-1 ring-black/5">
        <template #header>
          <div class="flex items-start gap-4">
            <div class="flex h-12 w-12 items-center justify-center rounded-2xl bg-primary/10 text-primary ring-1 ring-primary/15">
              <UIcon name="i-heroicons-folder-plus" class="h-6 w-6" />
            </div>
            <div>
              <h3 class="text-lg font-semibold text-highlighted">Ordner erstellen</h3>
              <p class="mt-1 text-sm text-muted">Lege einen neuen Ordner im aktuellen Bereich an.</p>
            </div>
          </div>
        </template>

        <form class="space-y-5" @submit.prevent="createFolder">
          <UFormField label="Name" required>
            <UInput v-model="createFolderData.name" autofocus class="w-full" />
          </UFormField>

          <UFormField
              label="Standard Dateityp (Tag)"
              :help="isParentTypeMandatory ? 'Vom übergeordneten Ordner vorgegeben' : ''"
          >
            <USelectMenu
                v-model="createFolderData.standardFiletype"
                :items="filetags"
                value-key="id"
                label-key="name"
                placeholder="Kein Standardtyp"
                class="w-full"
                :search-input="{ placeholder: 'Dateityp suchen...' }"
                :filter-fields="['name']"
                :disabled="isParentTypeMandatory"
            />
          </UFormField>

          <UCheckbox
              v-model="createFolderData.standardFiletypeIsOptional"
              label="Dateityp ist optional"
              :disabled="isParentTypeMandatory"
          />
        </form>

        <template #footer>
          <div class="flex justify-end gap-2">
            <UButton color="neutral" variant="ghost" @click="createFolderModalOpen = false">Abbrechen</UButton>
            <UButton color="primary" @click="createFolder">Erstellen</UButton>
          </div>
        </template>
      </UCard>
    </template>
  </UModal>

  <UModal v-model:open="renameModalOpen">
    <template #content>
      <UCard class="shadow-xl ring-1 ring-black/5">
        <template #header><h3 class="text-lg font-semibold text-highlighted">Umbenennen</h3></template>
        <form @submit.prevent="updateName">
          <UFormField label="Neuer Name">
            <UInput v-model="renameData.name" autofocus class="w-full" />
          </UFormField>
        </form>
        <template #footer>
          <div class="flex justify-end gap-2">
            <UButton color="neutral" variant="ghost" @click="renameModalOpen = false">Abbrechen</UButton>
            <UButton color="primary" @click="updateName">Speichern</UButton>
          </div>
        </template>
      </UCard>
    </template>
  </UModal>
</template>
