<template>
    <div>
        <h1 class="text-xl font-bold text-primary-500 sm:text-2xl">{{ $t('sharedFiles.title') }}</h1>

        <!-- Fil d'Ariane -->
        <nav class="mt-4 flex flex-wrap items-center gap-1 text-sm text-neutral-500">
            <button class="hover:text-primary-500" @click="openPath('')">{{ $t('sharedFiles.root') }}</button>
            <template v-for="crumb in breadcrumb" :key="crumb.path">
                <span>/</span>
                <button class="hover:text-primary-500" @click="openPath(crumb.path)">{{ crumb.name }}</button>
            </template>
        </nav>

        <!-- Filtre local + rechargement -->
        <div class="mt-4 flex items-center gap-2">
            <div class="max-w-sm flex-1">
                <MalioInputText
                    v-model="filter"
                    :placeholder="$t('sharedFiles.searchPlaceholder')"
                    input-class="w-full"
                />
            </div>
            <MalioButtonIcon
                icon="heroicons:arrow-path"
                :aria-label="$t('sharedFiles.reload')"
                variant="ghost"
                icon-size="20"
                :disabled="loading"
                button-class="text-neutral-500 hover:text-primary-500"
                @click="reload"
            />
        </div>

        <!-- États -->
        <div v-if="loading || searching" class="mt-10 flex justify-center">
            <Icon name="heroicons:arrow-path" class="h-6 w-6 animate-spin text-neutral-400" />
        </div>
        <p v-else-if="error || searchError" class="mt-10 text-sm text-red-600">{{ error || searchError }}</p>
        <p v-else-if="visibleEntries.length === 0" class="mt-10 text-sm text-neutral-400">
            {{ isSearchMode ? $t('sharedFiles.noResults') : $t('sharedFiles.empty') }}
        </p>

        <!-- Tableau -->
        <table v-else class="mt-6 w-full text-sm">
            <thead class="border-b border-neutral-200 text-left text-xs uppercase tracking-wider text-neutral-400">
                <tr>
                    <th class="py-2">{{ $t('sharedFiles.colName') }}</th>
                    <th class="py-2">{{ $t('sharedFiles.colSize') }}</th>
                    <th class="py-2">{{ $t('sharedFiles.colModified') }}</th>
                </tr>
            </thead>
            <tbody>
                <tr
                    v-for="entry in visibleEntries"
                    :key="entry.path"
                    class="cursor-pointer border-b border-neutral-100 hover:bg-neutral-50"
                    @click="onEntryClick(entry)"
                >
                    <td class="flex items-center gap-2 py-2">
                        <Icon :name="entry.isDir ? 'mdi:folder-outline' : iconForMime(entry.mimeType)" class="h-5 w-5 shrink-0 text-neutral-400" />
                        <span class="flex min-w-0 flex-col">
                            <span class="truncate">{{ entry.name }}</span>
                            <span v-if="isSearchMode && parentDir(entry)" class="truncate text-xs text-neutral-400">{{ parentDir(entry) }}</span>
                        </span>
                    </td>
                    <td class="py-2 text-neutral-500">{{ entry.isDir ? '—' : formatFileSize(entry.size) }}</td>
                    <td class="py-2 text-neutral-500">{{ formatDate(entry.modifiedAt) }}</td>
                </tr>
            </tbody>
        </table>

        <SharedFilePreview
            :entry="previewEntry"
            :has-prev="previewIndex > 0"
            :has-next="previewIndex >= 0 && previewIndex < fileEntries.length - 1"
            @close="previewEntry = null"
            @prev="stepPreview(-1)"
            @next="stepPreview(1)"
        />
    </div>
</template>

<script setup lang="ts">
import type { Breadcrumb, FileEntry } from '~/modules/integration/services/dto/share'
import { useShareService } from '~/modules/integration/services/share'
import { formatFileSize } from '~/utils/format'

useHead({ title: 'Documents' })

const { browse, search } = useShareService()
const { enabled, ensureLoaded } = useShareStatus()

const MIN_SEARCH_LENGTH = 2

const currentPath = ref('')
const breadcrumb = ref<Breadcrumb[]>([])
const entries = ref<FileEntry[]>([])
const filter = ref('')
const loading = ref(false)
const error = ref<string | null>(null)

const searchResults = ref<FileEntry[]>([])
const searching = ref(false)
const searchError = ref<string | null>(null)

const previewEntry = ref<FileEntry | null>(null)

// Recherche globale (récursive sur tout le partage) dès 2 caractères ;
// en deçà, simple filtre local sur le dossier courant.
const isSearchMode = computed(() => filter.value.trim().length >= MIN_SEARCH_LENGTH)

const visibleEntries = computed(() => {
    const f = filter.value.trim().toLowerCase()
    if (!f) return entries.value
    if (f.length < MIN_SEARCH_LENGTH) {
        return entries.value.filter((e) => e.name.toLowerCase().includes(f))
    }
    return searchResults.value
})

function parentDir(entry: FileEntry): string {
    const idx = entry.path.lastIndexOf('/')
    return idx === -1 ? '' : entry.path.slice(0, idx)
}

let searchTimer: ReturnType<typeof setTimeout> | null = null
let searchSeq = 0

async function runSearch(query: string) {
    const seq = ++searchSeq
    searching.value = true
    searchError.value = null
    try {
        const result = await search(query)
        if (seq !== searchSeq) return // une frappe plus récente a pris le relais
        searchResults.value = result.entries
    } catch (e: unknown) {
        if (seq !== searchSeq) return
        searchError.value = (e as Error)?.message ?? 'Erreur'
        searchResults.value = []
    } finally {
        if (seq === searchSeq) searching.value = false
    }
}

watch(filter, (value) => {
    if (searchTimer) clearTimeout(searchTimer)

    const q = value.trim()
    if (q.length < MIN_SEARCH_LENGTH) {
        searchSeq++ // invalide toute recherche en vol
        searching.value = false
        searchError.value = null
        searchResults.value = []
        return
    }

    searching.value = true
    searchTimer = setTimeout(() => runSearch(q), 300)
})

const fileEntries = computed(() => visibleEntries.value.filter((e) => !e.isDir))
const previewIndex = computed(() => previewEntry.value ? fileEntries.value.findIndex((e) => e.path === previewEntry.value!.path) : -1)

async function load(path: string) {
    loading.value = true
    error.value = null
    try {
        const result = await browse(path)
        currentPath.value = result.path
        breadcrumb.value = result.breadcrumb
        entries.value = result.entries
    } catch (e: unknown) {
        error.value = (e as Error)?.message ?? 'Erreur'
        entries.value = []
    } finally {
        loading.value = false
    }
}

function openPath(path: string) {
    filter.value = ''
    load(path)
}

function reload() {
    load(currentPath.value)
}

function onEntryClick(entry: FileEntry) {
    if (entry.isDir) {
        openPath(entry.path)
    } else {
        previewEntry.value = entry
    }
}

function stepPreview(delta: number) {
    const idx = previewIndex.value + delta
    if (idx >= 0 && idx < fileEntries.value.length) {
        previewEntry.value = fileEntries.value[idx] ?? null
    }
}

function iconForMime(mime: string): string {
    if (mime.startsWith('image/')) return 'mdi:file-image-outline'
    if (mime === 'application/pdf') return 'mdi:file-pdf-box'
    if (mime.includes('wordprocessingml') || mime === 'application/msword') return 'mdi:file-word-outline'
    if (mime.includes('spreadsheetml') || mime === 'application/vnd.ms-excel') return 'mdi:file-excel-outline'
    if (mime.startsWith('text/')) return 'mdi:file-document-outline'
    return 'mdi:file-outline'
}

function formatDate(ts: number | null): string {
    if (!ts) return '—'
    return new Date(ts * 1000).toLocaleString()
}

onMounted(async () => {
    await ensureLoaded()
    if (enabled.value === false) {
        await navigateTo('/')
        return
    }
    load('')
})
</script>
