<script setup>
import {ref, computed, watch, onMounted, onUnmounted} from 'vue';
import DocumentDisplayModal from "~/components/DocumentDisplayModal.vue";
import DocumentUploadModal from "~/components/DocumentUploadModal.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 createFolderData = ref({name: '', standardFiletype: null, standardFiletypeIsOptional: true})
const renameModalOpen = ref(false)
const renameData = ref({id: null, name: '', type: ''})

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

// --- 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 || []

    if (route.query?.folder) {
      currentFolder.value = folders.value.find(i => i.id === route.query.folder) || null
    } else {
      currentFolder.value = null
    }
  } finally {
    loadingDocs.value = false
    loaded.value = true
  }
}

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

const handleGlobalDragEnter = (e) => {
  dragCounter++

  // 1. Abbrechen, wenn wir gerade intern Ordner/Dateien verschieben
  if (draggedItem.value) return

  // 2. Prüfen ob Files von außen kommen
  if (e.dataTransfer && e.dataTransfer.types && e.dataTransfer.types.includes('Files')) {
    // Modal öffnen, falls noch nicht offen (optionaler Check, useModal handhabt das meist selbst)
    // Wir übergeben den aktuellen Ordner
    modal.open(DocumentUploadModal, {
      fileData: {folder: currentFolder.value?.id, typeEnabled: true},
      onUploadFinished: () => {
        setupPage()
        dragCounter = 0
      }
    })
  }
}

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

const handleGlobalDrop = (e) => {
  dragCounter = 0
  // Verhindert, dass der Browser die Datei öffnet, falls man neben das Modal droppt
  e.preventDefault()
}

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

onMounted(() => {
  setupPage()

  // Globale Listener registrieren
  window.addEventListener('dragenter', handleGlobalDragEnter)
  window.addEventListener('dragleave', handleGlobalDragLeave)
  window.addEventListener('dragover', handleGlobalDragOver)
  window.addEventListener('drop', handleGlobalDrop)
})

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


// --- Navigation ---
const changeFolder = async (folder) => {
  currentFolder.value = folder
  await router.push(folder ? `/files?folder=${folder.id}` : `/files`)
}

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

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

const handleDrop = async (targetFolderId) => {
  // targetFolderId kann null sein (Root)
  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 breadcrumbLinks = computed(() => {
  const links = [{label: "Home", icon: "i-heroicons-home", click: () => changeFolder(null)}]
  if (currentFolder.value) {
    const path = []
    let curr = currentFolder.value
    while (curr) {
      const folderObj = curr
      path.unshift({
        label: folderObj.name,
        icon: "i-heroicons-folder",
        click: () => changeFolder(folderObj)
      })
      curr = folders.value.find(f => f.id === curr.parent)
    }
    return [...links, ...path]
  }
  return links
})

// --- Data Mapping ---
const renderedFileList = computed(() => {
  // 1. Aktuelle Ordner filtern
  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))

  // 2. Aktuelle Dateien filtern
  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)
  }

  // 3. "Nach oben" (..) einfügen, wenn wir nicht im Root sind und nicht suchen
  if (currentFolder.value && !debouncedSearch.value) {
    combined.unshift({
      id: 'go-up',
      label: '..',
      type: 'up',
      parentId: currentFolder.value.parent || null
    })
  }

  return combined
})

// --- Actions ---
const createFolder = async () => {
  await useEntities("folders").create({
    parent: currentFolder.value?.id,
    name: createFolderData.value.name
  })
  createFolderModalOpen.value = false
  createFolderData.value = {name: ''}
  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()
  })
}

defineShortcuts({
  '/': () => document.getElementById("searchinput")?.focus(),
  'Enter': {
    usingInput: true,
    handler: () => {
      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'
    })

    // Liste neu laden
    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 :links="breadcrumbLinks"/>
    </template>
    <template #right>
      <USelectMenu v-model="displayMode" :options="displayModes" value-attribute="key" class="w-32"
                   :ui-menu="{ zIndex: 'z-50' }">
        <template #label>
          <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 }, onUploadFinished: setupPage })">
          Datei
        </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>
              <UDropdown v-if="entry.type !== 'up'"
                         :items="[[{ label: 'Umbenennen', icon: 'i-heroicons-pencil-square', click: () => openRenameModal(entry) }]]">
                <UButton color="gray" variant="ghost" icon="i-heroicons-ellipsis-horizontal"/>
              </UDropdown>
            </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))"
        >
          <UDropdown v-if="entry.type !== 'up'"
                     :items="[[{ label: 'Umbenennen', icon: 'i-heroicons-pencil-square', click: () => openRenameModal(entry) }]]"
                     class="absolute top-1 right-1 opacity-0 group-hover:opacity-100" @click.stop>
            <UButton color="gray" variant="ghost" icon="i-heroicons-ellipsis-vertical" size="xs"/>
          </UDropdown>
          <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>
    </div>
  </UDashboardPanelContent>

  <UModal v-model="createFolderModalOpen">
    <UCard>
      <template #header><h3 class="font-bold">Ordner erstellen</h3></template>
      <UFormGroup label="Name" required>
        <UInput v-model="createFolderData.name" autofocus @keyup.enter="createFolder"/>
      </UFormGroup>
      <template #footer>
        <div class="flex justify-end gap-2">
          <UButton color="gray" @click="createFolderModalOpen = false">Abbrechen</UButton>
          <UButton color="primary" @click="createFolder">Erstellen</UButton>
        </div>
      </template>
    </UCard>
  </UModal>

  <UModal v-model="renameModalOpen">
    <UCard>
      <template #header><h3 class="font-bold">Umbenennen</h3></template>
      <UFormGroup label="Neuer Name">
        <UInput v-model="renameData.name" autofocus @keyup.enter="updateName"/>
      </UFormGroup>
      <template #footer>
        <div class="flex justify-end gap-2">
          <UButton color="gray" @click="renameModalOpen = false">Abbrechen</UButton>
          <UButton color="primary" @click="updateName">Speichern</UButton>
        </div>
      </template>
    </UCard>
  </UModal>
</template>