<script lang="ts" setup>
import byteSize from 'byte-size';
import { toast } from 'vue-sonner';
import {
    fetchShareFile,
    getShare,
    listShareFiles,
    verifySharePassword,
} from '~/lib/api/shares';
import type { DirectoryEntry } from '~/shared/types';
import type { Share } from '~/shared/types/shares';
import { useImageViewer, useTextEditor } from '~/stores/viewers';

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

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

const imageViewer = useImageViewer();
const textEditor = useTextEditor();

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() {
    if (share == null || loading.value) {
        return;
    }

    if (!passwordValid.value) {
        loading.value = true;
        const result = await verifySharePassword(share.data.id, password.value);
        loading.value = false;

        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;
        } else {
            toast.error('Share', {
                id: 'SHARE_PASSWORD_TOAST',
                description: 'Invalid password',
            });
            return;
        }
    }

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

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

    loading.value = true;

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

    if (result.success) {
        warrenStore.setCurrentWarrenEntries(result.files, result.parent);
    }

    loading.value = false;
}

async function onEntryClicked(entry: DirectoryEntry, event: MouseEvent) {
    event.stopPropagation();

    if (
        warrenStore.current == null ||
        share == null ||
        (share.data.password && !passwordValid.value)
    ) {
        return;
    }

    if (warrenStore.handleSelectionClick(entry, event)) {
        return;
    }

    const entryPath =
        entry !== share.file
            ? joinPaths(warrenStore.current.path, entry.name)
            : warrenStore.current.path;

    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);
            imageViewer.open(url);
        }

        return;
    }

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

        if (result.success) {
            textEditor.open(
                warrenStore.current.warrenId,
                warrenStore.current.path,
                entry,
                result.data
            );
        }

        return;
    }
}

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.values()).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="[
                'w-full rounded-lg border transition-all',
                passwordValid && share.file.fileType === 'directory'
                    ? 'h-[min(98vh,600px)] max-w-screen-xl'
                    : 'max-w-2xl',
            ]"
        >
            <div class="flex flex-row items-center justify-between gap-4 p-6">
                <button
                    :disabled="share.data.password && !passwordValid"
                    :class="[
                        'flex min-w-0 grow flex-row items-center gap-2 text-left',
                        (!share.data.password || passwordValid) &&
                            'cursor-pointer',
                    ]"
                    @click="(e) => onEntryClicked(share!.file, e)"
                >
                    <DirectoryEntryIcon :entry="share.file" />

                    <div class="flex flex-col overflow-hidden">
                        <h3
                            :title="share.file.name"
                            class="truncate leading-none font-semibold"
                        >
                            {{ share.file.name }}
                        </h3>
                        <p class="text-muted-foreground text-sm text-nowrap">
                            {{ byteSize(share.file.size) }}
                        </p>
                        <p class="text-muted-foreground text-sm text-nowrap">
                            Created
                            {{
                                $dayjs(share.data.createdAt).format(
                                    'MMM D, YYYY HH:mm'
                                )
                            }}
                        </p>
                    </div>
                </button>

                <div class="flex flex-row items-end">
                    <Button
                        :class="
                            share.data.password && !passwordValid && 'hidden'
                        "
                        size="icon"
                        variant="outline"
                        @click="onDowloadClicked"
                        ><Icon name="lucide:download"
                    /></Button>
                </div>
            </div>

            <div
                v-if="
                    share.file.fileType === 'directory' ||
                    (share.data.password && !passwordValid)
                "
                class="flex w-full flex-col px-6 pb-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>
