<script setup lang="ts">
import {
    Dialog,
    DialogTrigger,
    DialogContent,
    DialogHeader,
    DialogTitle,
    DialogDescription,
    DialogFooter,
} from '@/components/ui/dialog';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Button } from '@/components/ui/button';
import byteSize from 'byte-size';
import { uploadToWarren } from '~/lib/api/warrens';
const warrenRoute = useWarrenRoute();

const fileInputElement = ref<HTMLInputElement>(
    null as unknown as HTMLInputElement
);

const uploading = ref(false);
const open = ref(false);
const files = ref<Array<{ uploaded: boolean; data: File }>>([]);
const presentPaths = new Set<string>();

function onFilesChanged(event: Event) {
    if (event.target == null) {
        return;
    }

    const target = event.target as HTMLInputElement;

    if (target.files == null) {
        return;
    }

    for (const file of target.files) {
        if (presentPaths.has(file.name)) {
            continue;
        }
        files.value.push({ uploaded: false, data: file });
        presentPaths.add(file.name);
    }

    fileInputElement.value.value = '';
}

async function submit() {
    if (files.value.length < 1) {
        return;
    }

    uploading.value = true;

    const dt = new DataTransfer();
    for (const file of files.value) {
        if (!file.uploaded) {
            dt.items.add(file.data);
        }
    }

    const { success } = await uploadToWarren(warrenRoute.value, dt.files);

    uploading.value = false;
    if (success) {
        for (const file of files.value) {
            file.uploaded = true;
        }
    }
}

function removeFile(index: number) {
    if (files.value.length <= index) {
        return;
    }

    const [file] = files.value.splice(index, 1);
    presentPaths.delete(file.data.name);
}

function clearCompletedFiles() {
    files.value = files.value.filter((f) => {
        if (f.uploaded) {
            presentPaths.delete(f.data.name);
            return false;
        }

        return true;
    });
}
</script>

<template>
    <Dialog v-model:open="open">
        <DialogTrigger as-child>
            <slot />
        </DialogTrigger>
        <DialogContent class="!min-w-[min(50%,98vw)] sm:!min-h-[unset]">
            <DialogHeader>
                <DialogTitle>Upload files</DialogTitle>
                <DialogDescription
                    >Upload files to the current directory</DialogDescription
                >
            </DialogHeader>

            <input
                ref="fileInputElement"
                class="hidden"
                type="file"
                multiple="true"
                @change="onFilesChanged"
            />

            <div
                class="flex min-h-[280px] sm:min-h-[unset] sm:aspect-video w-full items-center justify-center rounded-xl border overflow-hidden"
            >
                <ScrollArea v-if="files.length > 0" class="h-full w-full">
                    <div
                        class="flex h-full w-full flex-col items-stretch gap-1 text-left p-2"
                    >
                        <div
                            v-for="(file, i) in files"
                            :key="file.data.name"
                            class="flex flex-row items-center justify-between gap-4 rounded-lg border px-4 py-2"
                        >
                            <div class="rounded-sm border p-3">
                                <Icon
                                    v-if="!file.uploaded"
                                    class="h-5 w-5"
                                    :name="getFileIcon(file.data.type)"
                                />
                                <Icon
                                    v-else
                                    class="h-5 w-5 text-green-300"
                                    name="lucide:circle-check"
                                />
                            </div>
                            <div class="flex flex-col grow overflow-hidden">
                                <span class="font-medium truncate">{{
                                    file.data.name
                                }}</span>
                                <span class="text-muted-foreground">{{
                                    byteSize(file.data.size)
                                }}</span>
                            </div>
                            <div class="flex flex-row gap-2 items-center">
                                <Button
                                    variant="ghost"
                                    size="icon"
                                    :disabled="uploading"
                                    @click="() => removeFile(i)"
                                >
                                    <Icon name="lucide:x" />
                                </Button>
                            </div>
                        </div>
                    </div>
                </ScrollArea>
                <div
                    v-else
                    class="flex h-full w-full items-center justify-center"
                    :disabled="fileInputElement == null"
                    @click="() => files.length < 1 && fileInputElement?.click()"
                >
                    <Icon
                        class="h-[25%] w-[25%] opacity-25"
                        name="lucide:upload"
                    />
                </div>
            </div>

            <DialogFooter>
                <Button
                    class="sm:mr-auto"
                    variant="outline"
                    :disabled="files.every((f) => !f.uploaded)"
                    @click="clearCompletedFiles"
                >
                    Clear completed
                </Button>
                <Button
                    variant="outline"
                    :disabled="fileInputElement == null || uploading"
                    @click="() => fileInputElement?.click()"
                >
                    Select files
                </Button>
                <Button
                    :disabled="uploading || !files.some((f) => !f.uploaded)"
                    @click="submit"
                    >Upload</Button
                >
            </DialogFooter>
        </DialogContent>
    </Dialog>
</template>
