<template>
    <component :is="Default || 'div'">
        <div class="p-4">
            <div v-if="loading" class="flex justify-center py-8">
                <ULoader />
            </div>
            <div v-else-if="error" class="text-red-500">
                {{ error }}
            </div>
            <UTree v-if="showTree" :items="treeItems" v-model:expanded="expandedFolders" :key="treeKey" @toggle="onToggle" :get-key="item => item.value">
                <template #item-wrapper="{ item }">
                    <div class="flex items-start cursor-pointer" @click.stop="!item.isFolder">
                        <div class="flex items-center gap-1">
                            <UIcon :name="item.icon" :size="30" />
                            <div class="flex gap-1 items-center">
                                <span class="text-[15px] font-medium">
                                    {{ item.label }}
                                </span>
                                <UButton v-if="!item.isFolder && item.fileName" size="xxs" color="neutral"
                                    variant="outline" icon="i-lucide-download"
                                    @click.stop="downloadFile(item.path, item.fileName)" :ui="{ base: 'ring-0!' }" />
                            </div>
                        </div>
                    </div>
                </template>
            </UTree>
        </div>
    </component>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { useFetchJson } from '@/composable/useFetchJson'
import Default from '@/layouts/default.vue'

interface FileItemRaw {
    Name: string
    IsFolder: boolean
}

interface FileItem {
    name: string
    type: 'file' | 'folder'
}

interface TreeItem {
    label: string
    icon: string
    children?: TreeItem[]
    isFolder: boolean
    path: string
    value: string
    fileName?: string
}

const props = defineProps<{ initialPath?: string }>()

const currentPath = ref(props.initialPath || '')

const allData = ref<Record<string, FileItem[]>>({})
const expandedFolders = ref<string[]>([])
const treeKey = ref(0)

const loading = ref(false)
const error = ref<string | null>(null)

const showTree = computed(() => !error.value)

async function fetchFolderContents(path: string): Promise<FileItem[]> {
    const url = `/api/v1/restricted/storage/list-content/${path}`
    const data = await useFetchJson<FileItemRaw[]>(url)

    return (data.items || []).map(i => ({
        name: i.Name,
        type: i.IsFolder ? 'folder' : 'file'
    }))
}

async function loadFolder(path: string) {
    if (allData.value[path]) return

    try {
        const items = await fetchFolderContents(path)
        allData.value[path] = items
    } catch (e) {
        error.value = e instanceof Error ? e.message : 'Failed to load folder contents'
    }
}

function buildTree(path: string): TreeItem[] {
    const items = allData.value[path] || []

    return items.map(item => {
        const itemPath = path ? `${path}/${item.name}` : item.name
        const isFolder = item.type === 'folder'

        const isExpanded = expandedFolders.value.includes(itemPath)
        const isLoaded = !!allData.value[itemPath]

        return {
            label: item.name,
            icon: isFolder ? 'fxemoji:folder' : 'flat-color-icons:file',
            isFolder,
            path: isFolder ? itemPath : path,
            value: itemPath,
            fileName: isFolder ? undefined : item.name,

            children: isFolder && isExpanded && isLoaded
                ? buildTree(itemPath)
                : []
        }
    })
}

const treeItems = computed(() => buildTree(currentPath.value))

async function toggleFolder(item: TreeItem) {
    if (!item.isFolder) return

    const isOpen = expandedFolders.value.includes(item.value)

    if (!isOpen) {
        await loadFolder(item.value)
        treeKey.value++
    } else {
        treeKey.value++
    }
}

function onToggle(_event: unknown, item: TreeItem) {
    console.log('Toggle:', item)
    if (item.isFolder) {
        toggleFolder(item)
    }
}

async function downloadFile(path: string, fileName: string) {
    try {
        const response = await fetch(`/api/v1/restricted/storage/download-file/${path}/${fileName}`)
        if (!response.ok) throw new Error('Download failed')

        const blob = await response.blob()
        const url = window.URL.createObjectURL(blob)

        const a = document.createElement('a')
        a.href = url
        a.download = fileName

        document.body.appendChild(a)
        a.click()
        a.remove()

        window.URL.revokeObjectURL(url)
    } catch (e) {
        console.error(e)
        alert('Download failed')
    }
}

loadFolder(currentPath.value)
</script>