<script setup>
import { FileUploadStore } from '@/stores/FileUploadStore';
import { useAuth } from '@websanova/vue-auth/src/v3.js';
import { usePrimeVue } from 'primevue/config';
import { useToast } from 'primevue/usetoast';
import { ref, watch } from 'vue';

const props = defineProps({
    inputName: {
        type: String,
        required: true
    },
    label: {
        type: String,
        required: true
    },
    tooltipText: {
        type: String,
        default: 'Upload files'
    },
    uploadUrl: {
        type: String,
        required: true
    },
    isMultiple: {
        type: Boolean,
        default: false
    },
    acceptedFormats: {
        type: String,
        default: '.docx'
    },
    folderName: {
        type: String,
        required: true
    },
    uploadedFiles: {
        type: Array,
        default: () => []
    }
});

const emit = defineEmits(['upload', 'remove', 'update:uploadedFiles']);

const fileUploadStore = FileUploadStore();
const toast = useToast();
const auth = useAuth();
const $primevue = usePrimeVue();

const localUploadedFiles = ref(props.uploadedFiles);

// Sync uploaded files with parent
watch(
    localUploadedFiles,
    (newFiles) => {
        emit('update:uploadedFiles', newFiles);
    },
    { deep: true }
);

watch(
    () => props.uploadedFiles,
    (newFiles) => {
        localUploadedFiles.value = newFiles;
    },
    { deep: true }
);

const onBeforeSend = (event) => {
    const { xhr } = event;
    const token = auth.token();
    xhr.setRequestHeader('Authorization', 'Bearer ' + token);
};

const handleUpload = (event) => {
    const { xhr } = event;

    if (xhr.status === 200) {
        const uploadedFileName = event.files && event.files.length > 0 ? event.files[0].name : 'UnknownFile';

        toast.add({
            severity: 'success',
            summary: 'Success',
            detail: 'File uploaded successfully!',
            life: 3000
        });

        emit('upload', {
            fileName: uploadedFileName,
            response: xhr.response,
            files: event.files,
            inputName: props.inputName
        });
    } else {
        toast.add({
            severity: 'error',
            summary: 'Error',
            detail: `Failed to upload file. Status: ${xhr.status}`,
            life: 3000
        });
    }
};

const handleRemove = async (event, removeUploadedFileCallback) => {
    const { file, index } = event;

    try {
        const response = await fileUploadStore.deleteFile(file.name, props.folderName);

        if (response.status === 200) {
            toast.add({
                severity: 'success',
                summary: 'Success',
                detail: 'File removed successfully!',
                life: 3000
            });

            removeUploadedFileCallback(index);
            emit('remove', { fileName: file.name, inputName: props.inputName });
        } else {
            toast.add({
                severity: 'error',
                summary: 'Error',
                detail: `Failed to remove file. Status: ${response.statusText}`,
                life: 3000
            });
        }
    } catch (error) {
        toast.add({
            severity: 'error',
            summary: 'Error',
            detail: `Error while removing file: ${error.message}`,
            life: 3000
        });
    }
};

const formatSize = (bytes) => {
    const k = 1024;
    const sizes = $primevue.config.locale.fileSizeTypes;

    if (bytes === 0) {
        return `0 ${sizes[0]}`;
    }

    const i = Math.floor(Math.log(bytes) / Math.log(k));
    const truncatedSize = Math.trunc(bytes / Math.pow(k, i));

    return `${truncatedSize} ${sizes[i]}`;
};
</script>

<template>
    <div>
        <label :for="inputName">
            <b>{{ label }}</b>
            <i class="pi pi-info-circle text-violet-600 cursor-pointer" v-tooltip="tooltipText"></i>
        </label>
        <div>
            <FileUpload
                name="MultiFileUpload"
                :customUpload="false"
                :url="uploadUrl"
                @upload="handleUpload"
                :multiple="isMultiple"
                :accept="acceptedFormats"
                auto
                :showUploadButton="false"
                :showCancelButton="false"
                :maxFileSize="52428800"
                :invalidFileSizeMessage="'Invalid file size, file size should be smaller than 20 MB'"
                v-model:files="localUploadedFiles"
                @before-send="onBeforeSend"
            >
                <template #content="{ uploadedFiles, removeUploadedFileCallback }">
                    <div class="pt-4">
                        <div v-if="uploadedFiles.length > 0">
                            <table class="table-auto w-full border-collapse border border-gray-200">
                                <thead>
                                    <tr>
                                        <th class="border border-gray-300 p-2">Name</th>
                                        <th class="border border-gray-300 p-2">Dimension</th>
                                        <th class="border border-gray-300 p-2">Status</th>
                                        <th class="border border-gray-300 p-2">Actions</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr v-for="(file, index) in uploadedFiles" :key="file.name + file.size" class="hover:bg-gray-50">
                                        <td class="border border-gray-300 p-2">{{ file.name }}</td>
                                        <td class="border border-gray-300 p-2">{{ formatSize(file.size) }}</td>
                                        <td class="border border-gray-300 p-2">
                                            <Badge value="UPLOADED" severity="success" />
                                        </td>
                                        <td class="border border-gray-300 p-2">
                                            <Button label="Remove" @click="handleRemove({ file, index }, removeUploadedFileCallback)" />
                                        </td>
                                    </tr>
                                </tbody>
                            </table>
                        </div>
                    </div>
                </template>

                <template #empty>
                    <div class="flex items-center justify-center flex-col">
                        <div class="!border !border-violet-600 !rounded-full !w-24 !h-24 flex items-center justify-center">
                            <i class="pi pi-cloud-upload !text-4xl !-violet-600"></i>
                        </div>
                        <p class="mt-2 mb-2 text-m">Drag and drop files here to upload.</p>
                    </div>
                </template>
            </FileUpload>
        </div>
    </div>
</template>
