<template>
  <div class="flex flex-col h-full">

    <!-- ── Sticky toolbar ──────────────────────────────────────────────── -->
    <div class="sticky top-0 z-10 bg-white border-b border-gray-100">
      <div class="px-6 py-3 flex items-center gap-3 flex-wrap">
        <BreadcrumbBar
          :segments="breadcrumb"
          :root-label="mode === 'cloud' ? 'Cloud' : 'Home'"
          @navigate="$emit('breadcrumb-navigate', $event)"
        />
        <div class="ml-auto flex items-center gap-2 shrink-0">
          <SearchBar v-if="showSearch" ref="searchBarRef" :model-value="searchQuery" @update:modelValue="$emit('search-change', $event)" />
          <SortControls
            v-if="showSearch"
            :sort="sortField"
            :order="sortOrder"
            @change="$emit('sort-change', $event)"
          />
          <button
            v-if="mode === 'local'"
            @click="$emit('new-folder')"
            class="flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium text-indigo-600 border border-indigo-200 hover:bg-indigo-50 rounded-lg transition-colors"
          >
            <AppIcon name="plus" class="w-4 h-4" />
            New folder
          </button>
        </div>
      </div>
    </div>

    <!-- ── Content area ───────────────────────────────────────────────── -->
    <div class="flex-1 overflow-y-auto flex flex-col">

      <!-- Upload zone -->
      <div class="px-6 pt-5 pb-3">
        <DropZone ref="dropZoneRef" @files-selected="$emit('upload', $event)" />
        <UploadProgress :items="uploadQueue" />
      </div>

      <!-- Column headers — 5-column grid, consistent for local and cloud -->
      <div class="mx-6 px-4 py-2 grid grid-cols-[2rem_1fr_6rem_8rem_6rem] gap-3 items-center rounded-lg bg-gray-50 text-xs font-semibold text-gray-400 uppercase tracking-wider select-none">
        <span></span>
        <span>Name</span>
        <span class="text-right hidden md:block">Size</span>
        <span class="text-right hidden sm:block">Modified</span>
        <span></span>
      </div>

      <!-- Inline new-folder row (local only) -->
      <div v-if="showNewFolderInput" class="mx-6 mt-1 px-4 py-2.5 grid grid-cols-[2rem_1fr_6rem_8rem_6rem] gap-3 items-center rounded-lg border border-amber-200 bg-amber-50/40">
        <div class="w-7 h-7 bg-amber-50 rounded-lg flex items-center justify-center">
          <AppIcon name="folder" class="w-4 h-4 text-amber-400" />
        </div>
        <div class="flex items-center gap-2 col-span-4">
          <input
            ref="newFolderInputRef"
            v-model="newFolderName"
            type="text"
            placeholder="Folder name"
            class="border border-gray-300 rounded-lg px-2 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500"
            @keydown.enter="submitNewFolder"
            @keydown.escape="cancelNewFolder"
          />
          <button @click="submitNewFolder" class="text-sm text-indigo-600 hover:underline font-medium">Save</button>
          <button @click="cancelNewFolder" class="text-sm text-gray-500 hover:text-gray-700">Cancel</button>
          <p v-if="newFolderError" class="text-xs text-red-500">{{ newFolderError }}</p>
        </div>
      </div>

      <!-- ── Item list ─────────────────────────────────────────────────── -->
      <div class="mx-6 mt-1 mb-6 flex flex-col divide-y divide-gray-100 border border-gray-100 rounded-xl overflow-hidden">

        <!-- Folder rows -->
        <div
          v-for="folder in folders"
          :key="`f-${folder.id}`"
          class="px-4 py-2.5 grid grid-cols-[2rem_1fr_6rem_8rem_6rem] gap-3 items-center hover:bg-gray-50 group cursor-pointer transition-colors"
          :class="{
            'bg-amber-50 ring-2 ring-inset ring-amber-300': dragOverFolderId === folder.id,
            'bg-gray-50': renamingId === folder.id,
          }"
          @click="renamingId === folder.id ? null : $emit('folder-navigate', folder)"
          @dragover.prevent="mode === 'local' ? onFolderDragOver(folder.id, $event) : null"
          @dragleave="dragOverFolderId = null"
          @drop.prevent="mode === 'local' ? onDropDocOnFolder(folder.id) : null"
        >
          <div class="w-7 h-7 bg-amber-50 rounded-lg flex items-center justify-center shrink-0">
            <AppIcon name="folder" class="w-4 h-4 text-amber-500" />
          </div>

          <!-- Name / rename input -->
          <div>
            <input
              v-if="renamingId === folder.id"
              v-model="renameValue"
              class="border border-indigo-300 rounded-lg px-2 py-0.5 text-sm w-full max-w-xs focus:outline-none focus:ring-2 focus:ring-indigo-500"
              @keydown.enter="$emit('folder-rename', { id: folder.id, name: renameValue.trim() }); renamingId = null"
              @keydown.escape="renamingId = null"
              @vue:mounted="e => e.el?.focus()"
            />
            <span v-else class="text-sm font-medium text-gray-900 truncate block">{{ folder.name }}</span>
          </div>

          <span class="text-right text-xs text-gray-400 hidden md:block">—</span>
          <span class="text-right text-xs text-gray-400 hidden sm:block">{{ formatDate(folder.created_at) }}</span>

          <!-- Folder actions (local only) -->
          <div class="flex justify-end gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity" @click.stop>
            <template v-if="mode === 'local'">
              <button @click.stop="startRename(folder)" title="Rename"
                class="p-1.5 rounded hover:bg-gray-200 text-gray-400 hover:text-gray-700 transition-colors">
                <AppIcon name="pencil" class="w-3.5 h-3.5" />
              </button>
              <button @click.stop="$emit('folder-delete', folder)" title="Delete folder"
                class="p-1.5 rounded hover:bg-red-50 text-gray-400 hover:text-red-500 transition-colors">
                <AppIcon name="trash" class="w-3.5 h-3.5" />
              </button>
            </template>
          </div>
        </div>

        <!-- File rows -->
        <div
          v-for="file in files"
          :key="`d-${file.id}`"
          :draggable="mode === 'local'"
          class="px-4 py-2.5 grid grid-cols-[2rem_1fr_6rem_8rem_6rem] gap-3 items-center hover:bg-gray-50 group cursor-pointer transition-colors select-none"
          :class="{ 'opacity-50': draggingFile?.id === file.id }"
          @click="draggingFile ? null : $emit('file-open', file)"
          @dragstart="mode === 'local' ? onFileDragStart(file, $event) : null"
          @dragend="onFileDragEnd"
        >
          <div class="w-7 h-7 bg-indigo-50 rounded-lg flex items-center justify-center shrink-0">
            <AppIcon name="document" class="w-4 h-4 text-indigo-400" />
          </div>

          <!-- Name + topics + shared badge -->
          <div class="min-w-0">
            <div class="flex items-center gap-2">
              <p class="text-sm font-medium text-gray-900 truncate">{{ file.original_name ?? file.name }}</p>
              <span v-if="file.is_shared" class="shrink-0 bg-indigo-50 text-indigo-600 text-xs font-medium px-2 py-0.5 rounded-full">Shared</span>
            </div>
            <div v-if="file.topics?.length" class="flex items-center gap-1 mt-0.5 flex-wrap">
              <TopicBadge
                v-for="t in file.topics.slice(0, 3)"
                :key="t"
                :name="t"
                :color="topicColor(t)"
              />
            </div>
          </div>

          <span class="text-right text-xs text-gray-400 hidden md:block">{{ formatSize(file.size_bytes ?? file.size) }}</span>
          <span class="text-right text-xs text-gray-400 hidden sm:block">{{ formatDate(file.created_at) }}</span>

          <!-- File actions (local only) -->
          <div class="flex justify-end gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity" @click.stop>
            <template v-if="mode === 'local'">
              <!-- Share -->
              <button @click.stop="$emit('file-share', file)" title="Share"
                class="p-1.5 rounded hover:bg-gray-200 text-gray-400 hover:text-gray-700 transition-colors">
                <AppIcon name="share" class="w-3.5 h-3.5" />
              </button>
              <!-- Move -->
              <div class="relative">
                <button
                  @click.stop="openFolderPicker(file.id, $event)"
                  title="Move to folder"
                  class="p-1.5 rounded hover:bg-gray-200 text-gray-400 hover:text-gray-700 transition-colors"
                >
                  <AppIcon name="folderMove" class="w-3.5 h-3.5" />
                </button>
              </div>
              <!-- Delete -->
              <button @click.stop="$emit('file-delete', file.id)" title="Delete"
                class="p-1.5 rounded hover:bg-red-50 text-gray-400 hover:text-red-500 transition-colors">
                <AppIcon name="trash" class="w-3.5 h-3.5" />
              </button>
            </template>
          </div>
        </div>

        <template v-if="loading">
          <div
            v-for="n in 5"
            :key="`sk-${n}`"
            class="px-4 py-2.5 grid grid-cols-[2rem_1fr_6rem_8rem_6rem] gap-3 items-center border-b border-gray-100"
          >
            <div class="w-7 h-7 bg-gray-100 rounded-lg animate-pulse"></div>
            <div class="h-4 bg-gray-100 rounded animate-pulse w-2/3"></div>
            <div class="h-3 bg-gray-100 rounded animate-pulse hidden md:block"></div>
            <div class="h-3 bg-gray-100 rounded animate-pulse hidden sm:block"></div>
            <div class="w-14 h-3 bg-gray-100 rounded animate-pulse"></div>
          </div>
        </template>

        <EmptyState
          v-else-if="searchQuery && folders.length === 0 && files.length === 0"
          icon="search"
          :headline="`No results for &quot;${searchQuery}&quot;`"
          subtext="Try a different search term or clear the filter."
        >
          <template #cta>
            <button @click="$emit('search-change', '')" class="mt-3 text-sm text-indigo-600 hover:underline">
              Clear search
            </button>
          </template>
        </EmptyState>

        <EmptyState
          v-else-if="breadcrumb.length > 0 && folders.length === 0 && files.length === 0 && !showNewFolderInput"
          icon="document"
          :headline="emptyMessage"
          :subtext="emptyHint"
        />

        <EmptyState
          v-else-if="folders.length === 0 && files.length === 0 && !showNewFolderInput"
          icon="folder"
          :headline="emptyMessage"
          :subtext="emptyHint"
        />
      </div>
    </div>
  </div>

  <!-- Teleported folder picker — avoids overflow:hidden clipping -->
  <Teleport to="body">
    <div
      v-if="folderPickerFileId"
      :style="pickerStyle"
      data-test="folder-picker"
      class="fixed z-[9999] bg-white border border-gray-200 rounded-xl shadow-lg overflow-y-auto py-1"
      style="max-height: 240px;"
      @click.stop
    >
      <button
        class="w-full text-left px-3 py-2 text-sm text-gray-600 hover:bg-gray-50"
        @click.stop="$emit('file-move', { fileId: folderPickerFileId, folderId: null }); folderPickerFileId = null"
      >
        Root (no folder)
      </button>
      <button
        v-for="f in rootFolders"
        :key="f.id"
        class="w-full text-left px-3 py-2 text-sm text-gray-700 hover:bg-indigo-50 hover:text-indigo-700 truncate"
        @click.stop="$emit('file-move', { fileId: folderPickerFileId, folderId: f.id }); folderPickerFileId = null"
      >{{ f.name }}</button>
      <p v-if="!rootFolders.length" class="px-3 py-2 text-xs text-gray-400">No folders yet</p>
    </div>
  </Teleport>
</template>

<script setup>
import { ref, computed, nextTick, onMounted, onUnmounted } from 'vue'
import AppIcon from '../ui/AppIcon.vue'
import BreadcrumbBar from '../ui/BreadcrumbBar.vue'
import EmptyState from '../ui/EmptyState.vue'
import SearchBar from '../documents/SearchBar.vue'
import SortControls from '../documents/SortControls.vue'
import DropZone from '../upload/DropZone.vue'
import UploadProgress from '../upload/UploadProgress.vue'
import TopicBadge from '../topics/TopicBadge.vue'
import { formatDate, formatSize } from '../../utils/formatters.js'

const props = defineProps({
  /** "local" or "cloud" — controls which actions are visible */
  mode: { type: String, default: 'local' },
  folders: { type: Array, default: () => [] },
  files: { type: Array, default: () => [] },
  breadcrumb: { type: Array, default: () => [] },
  uploadQueue: { type: Array, default: () => [] },
  loading: { type: Boolean, default: false },
  searchQuery: { type: String, default: '' },
  sortField: { type: String, default: 'created_at' },
  sortOrder: { type: String, default: 'desc' },
  /** Root-level folders — used by the move-to-folder picker (local mode) */
  rootFolders: { type: Array, default: () => [] },
  /** Lookup function: topic name → color hex (local mode) */
  topicColorFn: { type: Function, default: () => '#6366f1' },
  emptyMessage: { type: String, default: 'This folder is empty' },
  emptyHint: { type: String, default: 'Upload files above or create a sub-folder' },
})

const emit = defineEmits([
  'breadcrumb-navigate',
  'new-folder',
  'sort-change',
  'search-change',
  'upload',
  'folder-navigate',
  'folder-create',
  'folder-rename',
  'folder-delete',
  'file-open',
  'file-share',
  'file-move',
  'file-delete',
])

const showSearch = computed(() => props.mode === 'local' && props.breadcrumb.length > 0)

function topicColor(name) {
  return props.topicColorFn(name)
}

// ── Child component refs ──────────────────────────────────────────────────────

const dropZoneRef = ref(null)
const searchBarRef = ref(null)

// ── New folder inline input ───────────────────────────────────────────────────

const showNewFolderInput = ref(false)
const newFolderName = ref('')
const newFolderError = ref('')
const newFolderInputRef = ref(null)

function startNewFolder() {
  newFolderName.value = ''
  newFolderError.value = ''
  showNewFolderInput.value = true
  nextTick(() => newFolderInputRef.value?.focus())
}

function cancelNewFolder() {
  showNewFolderInput.value = false
  newFolderError.value = ''
}

async function submitNewFolder() {
  const name = newFolderName.value.trim()
  if (!name) { newFolderError.value = 'Folder name cannot be empty.'; return }
  emit('folder-create', { name, onError: (msg) => { newFolderError.value = msg }, onSuccess: cancelNewFolder })
}

defineExpose({
  startNewFolder,
  triggerUpload: () => dropZoneRef.value?.triggerInput?.(),
  focusSearch: () => searchBarRef.value?.focus?.(),
  clearSearch: () => emit('search-change', ''),
})

// ── Rename ────────────────────────────────────────────────────────────────────

const renamingId = ref(null)
const renameValue = ref('')

function startRename(folder) {
  renamingId.value = folder.id
  renameValue.value = folder.name
}

// ── Drag and drop (local only) ────────────────────────────────────────────────

const draggingFile = ref(null)
const dragOverFolderId = ref(null)

function onFileDragStart(file, e) {
  draggingFile.value = file
  e.dataTransfer.effectAllowed = 'move'
  e.dataTransfer.setData('text/plain', file.id)
}

function onFolderDragOver(folderId, e) {
  if (!draggingFile.value) return
  e.preventDefault()
  dragOverFolderId.value = folderId
}

function onFileDragEnd() {
  dragOverFolderId.value = null
  nextTick(() => { draggingFile.value = null })
}

async function onDropDocOnFolder(folderId) {
  if (!draggingFile.value) return
  const fileId = draggingFile.value.id
  dragOverFolderId.value = null
  emit('file-move', { fileId, folderId })
  await nextTick()
  draggingFile.value = null
}

// ── Move folder picker (Teleport + getBoundingClientRect) ─────────────────────

const folderPickerFileId = ref(null)
const pickerStyle = ref({})
// Map fileId → trigger button element, so scroll listener can reposition
const pickerTriggerMap = new Map()

function updatePickerPosition(rect) {
  const spaceBelow = window.innerHeight - rect.bottom
  const dropH = 240
  if (spaceBelow >= dropH || spaceBelow > 120) {
    pickerStyle.value = {
      top: `${rect.bottom + 4}px`,
      left: `${rect.left}px`,
      width: '192px',
    }
  } else {
    pickerStyle.value = {
      bottom: `${window.innerHeight - rect.top + 4}px`,
      left: `${rect.left}px`,
      width: '192px',
    }
  }
}

function openFolderPicker(fileId, ev) {
  // Toggle off if same file
  if (folderPickerFileId.value === fileId) {
    folderPickerFileId.value = null
    return
  }
  folderPickerFileId.value = fileId
  const trigger = ev.currentTarget
  pickerTriggerMap.set(fileId, trigger)
  updatePickerPosition(trigger.getBoundingClientRect())
}

function onWindowScroll() {
  if (!folderPickerFileId.value) return
  const trig = pickerTriggerMap.get(folderPickerFileId.value)
  if (trig) updatePickerPosition(trig.getBoundingClientRect())
}

function onOutsideClick(e) {
  if (
    !e.target.closest('[data-test="folder-picker"]') &&
    !e.target.closest('.relative')
  ) {
    folderPickerFileId.value = null
  }
}

onMounted(() => {
  document.addEventListener('click', onOutsideClick)
  window.addEventListener('scroll', onWindowScroll, true)
  window.addEventListener('resize', onWindowScroll)
})
onUnmounted(() => {
  document.removeEventListener('click', onOutsideClick)
  window.removeEventListener('scroll', onWindowScroll, true)
  window.removeEventListener('resize', onWindowScroll)
})
</script>
