<script lang="ts" setup>
import { fetchShareFile, getShare, listShareFiles } from '~/lib/api/shares';
import type { DirectoryEntry } from '~/shared/types';
import type { Share } from '~/shared/types/shares';

definePageMeta({
    layout: 'share',
});

const warrenStore = useWarrenStore();
const route = useRoute();

const entries = computed(() =>
    warrenStore.current != null && warrenStore.current.dir != null
        ? warrenStore.current.dir.entries
        : null
);
const parent = computed(() =>
    warrenStore.current != null && warrenStore.current.dir != null
        ? warrenStore.current.dir.parent
        : null
);

const share = await getShareFromQuery();
const password = ref<string>('');
const loading = ref<boolean>(false);
const passwordValid = ref<boolean>(
    share == null ? false : !share.data.password
);

if (share != null) {
    warrenStore.setCurrentWarren(share.data.warrenId, '/');

    if (!share.data.password) {
        await loadFiles();
    }
}

async function getShareFromQuery(): Promise<{
    data: Share;
    file: DirectoryEntry;
} | null> {
    const shareId = route.query.id;

    if (shareId == null || typeof shareId !== 'string') {
        return null;
    }

    const result = await getShare(shareId);

    if (!result.success) {
        return null;
    }

    return { data: result.share, file: result.file };
}

async function submitPassword() {
    loadFiles();
}

async function loadFiles() {
    if (loading.value || share == null || warrenStore.current == null) {
        return;
    }

    if (share.file.fileType !== 'directory') {
        return;
    }

    loading.value = true;

    const result = await listShareFiles(
        share.data.id,
        warrenStore.current.path,
        password.value.length > 0 ? password.value : null
    );

    if (result.success) {
        passwordValid.value = true;
        let cookie = `X-Share-Password=${password.value}; Path=/; SameSite=Lax; Secure;`;

        if (share.data.expiresAt != null) {
            const dayjs = useDayjs();

            const diff = dayjs(share.data.expiresAt).diff(dayjs()) / 1000;
            cookie += `Max-Age=${diff};`;
        }

        document.cookie = cookie;

        warrenStore.setCurrentWarrenEntries(result.files, result.parent);
    }

    loading.value = false;
}

async function onEntryClicked(entry: DirectoryEntry, event: MouseEvent) {
    if (warrenStore.current == null) {
        return;
    }

    if (event.ctrlKey) {
        warrenStore.toggleSelection(entry);
        return;
    }

    const entryPath = joinPaths(warrenStore.current.path, entry.name);

    if (entry.fileType === 'directory') {
        warrenStore.setCurrentWarrenPath(entryPath);
        await loadFiles();
        return;
    }

    if (entry.mimeType == null) {
        return;
    }

    if (entry.mimeType.startsWith('image/')) {
        const result = await fetchShareFile(
            share!.data.id,
            entryPath,
            password.value.length > 0 ? password.value : null
        );

        if (result.success) {
            const url = URL.createObjectURL(result.data);
            warrenStore.imageViewer.src = url;
        }
    }
}

async function onBack() {
    if (warrenStore.backCurrentPath()) {
        await loadFiles();
    }
}

function onDowloadClicked() {
    if (share == null) {
        return;
    }

    const downloadName =
        share.file.fileType === 'directory'
            ? `${share.file.name}.zip`
            : share.file.name;
    const downloadApiUrl = getApiUrl(
        `warrens/files/cat_share?shareId=${share.data.id}&paths=/`
    );

    downloadFile(downloadName, downloadApiUrl);
}

function onEntryDownload(entry: DirectoryEntry) {
    if (share == null || warrenStore.current == null) {
        return;
    }

    let downloadName: string;
    let downloadApiUrl: string;

    const selectionSize = warrenStore.selection.size;

    if (selectionSize === 0 || !warrenStore.isSelected(entry)) {
        downloadName =
            entry.fileType === 'directory' ? `${entry.name}.zip` : entry.name;
        downloadApiUrl = getApiUrl(
            `warrens/files/cat_share?shareId=${share.data.id}&paths=${joinPaths(warrenStore.current.path, entry.name)}`
        );
    } else {
        downloadName = 'download.zip';
        const paths = Array.from(warrenStore.selection).map((entry) =>
            joinPaths(warrenStore.current!.path, entry.name)
        );

        downloadApiUrl = getApiUrl(
            `warrens/files/cat_share?shareId=${share.data.id}&paths=${paths.join(':')}`
        );
    }

    downloadFile(downloadName, downloadApiUrl);
}
</script>

<template>
    <div
        v-if="share != null"
        class="flex h-full w-full items-center justify-center px-2"
    >
        <div
            :class="[
                'h-[min(98vh,600px)] w-full max-w-screen-xl rounded-lg border transition-all',
                passwordValid ? 'max-w-screen-xl' : 'max-w-lg',
            ]"
        >
            <div
                class="flex flex-row items-center justify-between gap-4 px-6 pt-6"
            >
                <div class="flex w-full flex-row">
                    <div class="flex grow flex-col gap-1.5">
                        <h3 class="leading-none font-semibold">Share</h3>
                        <p class="text-muted-foreground text-sm">
                            Created
                            {{
                                $dayjs(share.data.createdAt).format(
                                    'MMM D, YYYY HH:mm'
                                )
                            }}
                        </p>
                    </div>
                    <div class="flex flex-row items-center justify-end gap-4">
                        <p>{{ share.file.name }}</p>
                        <DirectoryEntryIcon
                            :entry="{ ...share.file, name: '/' }"
                        />
                    </div>
                </div>
                <div class="flex flex-row items-end">
                    <Button
                        :class="
                            share.file.fileType !== 'file' &&
                            entries == null &&
                            'hidden'
                        "
                        size="icon"
                        variant="outline"
                        @click="onDowloadClicked"
                        ><Icon name="lucide:download"
                    /></Button>
                </div>
            </div>

            <div class="flex w-full flex-col p-6">
                <DirectoryList
                    v-if="entries != null"
                    :entries
                    :parent
                    :disable-entries="loading"
                    :entries-draggable="false"
                    @entry-click="onEntryClicked"
                    @entry-download="onEntryDownload"
                    @back="onBack"
                />
                <div
                    v-else-if="share.data.password"
                    class="flex h-full flex-col justify-between gap-2"
                >
                    <div class="flex flex-col gap-1">
                        <Label for="password">Password</Label>
                        <Input
                            id="password"
                            v-model="password"
                            type="password"
                            name="password"
                            autocomplete="off"
                            data-1p-ignore
                            data-protonpass-ignore
                            data-bwignore
                        />
                    </div>
                    <div class="flex flex-row-reverse items-end">
                        <Button
                            :disabled="loading || password.length < 1"
                            @click="submitPassword"
                            >Enter</Button
                        >
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div v-else class="bg-accent/20 rounded-md p-4">
        <p class="text-destructive-foreground">Failed to get share</p>
    </div>
</template>
