﻿<template>
    <div class="card">
        <div class="card-title">
            {{ t('title') }}
        </div>

        <div class="card-content">
            <p class="card-text">
                {{ t('description') }}
            </p>

            <div class="file-input-container">
                <input
                    ref="fileInput"
                    accept="image/*"
                    class="hidden"
                    type="file"
                    @change="onFileSelected"
                />
                <button
                    class="choose-file-button"
                    @click="triggerFileInput"
                >
                    {{ t('chooseImage') }}
                </button>
            </div>

            <div
                v-if="errorMessage"
                class="error-message"
            >
                {{ errorMessage }}
            </div>

            <div
                v-if="showCropper"
                class="cropper-wrapper"
            >
                <Cropper
                    ref="cropper"
                    :aspect-ratio="4"
                    :src="fileUrl"
                    :stencil-props="{
                        aspectRatio: 4,
                        class: 'banner-stencil',
                    }"
                />
            </div>

            <div
                v-else
                class="image-preview-container"
                @click="startEditing"
                @dragover.prevent
                @drop.prevent="handleDrop"
            >
                <img
                    :alt="t('preview')"
                    :src="fileUrl || fallbackUrl"
                    class="preview-image"
                />
                <div class="edit-overlay">
                    <span class="edit-text">{{ t('clickToEdit') }}</span>
                </div>
            </div>
        </div>

        <div class="card-actions">
            <button
                :disabled="isUploading"
                class="secondary"
                @click="cancel"
            >
                {{ t('cancel') }}
            </button>
            <button
                :disabled="!selectedFile || isUploading"
                class="primary"
                @click="showCropper ? applyCrop() : publish()"
            >
                <template v-if="isUploading">
                    <span class="loading-spinner"></span>
                    {{ t('uploading') }} ({{ uploadProgress }}%)
                </template>
                <template v-else>
                    {{ showCropper ? t('apply') : t('save') }}
                </template>
            </button>
        </div>
    </div>
</template>

<script setup>
    import { ref } from 'vue';
    import { useClient } from '@/plugins/api.js';
    import { Cropper } from 'vue-advanced-cropper';
    import 'vue-advanced-cropper/dist/style.css';
    import { useI18n } from 'vue-i18n';

    const props = defineProps({
        creator: {
            required: true,
        },
    });

    const emits = defineEmits(['closeRequested']);

    const fileInput = ref(null);
    const selectedFile = ref(null);
    const fileUrl = ref(props.creator?.bannerUrl);
    const fallbackUrl = '/images/hutopymedia/banners/hutopyul.png';
    const errorMessage = ref('');
    const showCropper = ref(false);
    const cropper = ref(null);
    const isUploading = ref(false);
    const uploadProgress = ref(0);

    // Get translations for this component
    const { t } = useI18n();

    const triggerFileInput = () => {
        if (fileInput.value) {
            fileInput.value.value = ''; // Reset the input value to ensure the change event fires
            fileInput.value.click();
        }
    };

    const onFileSelected = event => {
        const file = event.target.files[0];
        if (file) {
            selectedFile.value = file;
            const reader = new FileReader();
            reader.onload = e => {
                fileUrl.value = e.target.result;
                showCropper.value = true;
            };
            reader.readAsDataURL(file);
        } else {
            selectedFile.value = null;
            fileUrl.value = null;
            showCropper.value = false;
        }
    };

    const startEditing = () => {
        if (fileUrl.value && fileUrl.value.startsWith('data:')) {
            // Only try to load the image if it's a data URL (newly selected image)
            const blob = dataURLtoBlob(fileUrl.value);
            selectedFile.value = new File([blob], 'current-image.jpg', { type: 'image/jpeg' });
            showCropper.value = true;
        } else {
            // If no image is selected, using fallback, or have an existing uploaded image, trigger the file input
            triggerFileInput();
        }
    };

    // Helper function to convert data URL to blob
    const dataURLtoBlob = dataURL => {
        const arr = dataURL.split(',');
        const mime = arr[0].match(/:(.*?);/)[1];
        const bstr = atob(arr[1]);
        let n = bstr.length;
        const u8arr = new Uint8Array(n);
        while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
        }
        return new Blob([u8arr], { type: mime });
    };

    const applyCrop = () => {
        if (!cropper.value) return;

        const canvas = cropper.value.getResult().canvas;
        canvas.toBlob(blob => {
            const croppedFile = new File([blob], selectedFile.value.name, {
                type: selectedFile.value.type,
            });
            selectedFile.value = croppedFile;
            fileUrl.value = canvas.toDataURL();
            showCropper.value = false;
        }, selectedFile.value.type);
    };

    const client = useClient();
    const publish = async () => {
        if (!selectedFile.value || isUploading.value) return;

        try {
            isUploading.value = true;
            uploadProgress.value = 0;
            const formData = new FormData();
            formData.append('file', selectedFile.value);

            const response = await client.post(`/api/creators/${props.creator.id}/banner`, formData, {
                onUploadProgress: progressEvent => {
                    uploadProgress.value = Math.round((progressEvent.loaded * 100) / progressEvent.total);
                },
            });

            props.creator.bannerUrl = `${response.data.blobUrl}?t=${Date.now()}`;
            fileUrl.value = props.creator.bannerUrl;
            emits('closeRequested');
        } catch (error) {
            console.error(error);
            errorMessage.value = t('errors.imageUpload');
        } finally {
            isUploading.value = false;
            uploadProgress.value = 0;
        }
    };

    const cancel = () => {
        showCropper.value = false;
        // Reset to original state if we were editing
        if (props.creator?.bannerUrl) {
            fileUrl.value = props.creator.bannerUrl;
            selectedFile.value = null;
        } else {
            fileUrl.value = fallbackUrl;
            selectedFile.value = null;
        }
        emits('closeRequested');
    };

    // Add drop handler
    const handleDrop = event => {
        const file = event.dataTransfer.files[0];
        if (file && file.type.startsWith('image/')) {
            selectedFile.value = file;
            const reader = new FileReader();
            reader.onload = e => {
                fileUrl.value = e.target.result;
                showCropper.value = true;
            };
            reader.readAsDataURL(file);
        }
    };
</script>

<style scoped>
    .card-text {
        @apply font-sans text-lg;
    }

    .image-preview-container {
        @apply mb-5;
        @apply w-full;
        @apply flex;
        @apply justify-center;
        @apply items-center;
        @apply overflow-hidden;
        @apply rounded-lg;
        @apply relative;
        @apply cursor-pointer;
        @apply border-2;
        @apply border-dashed;
        @apply border-gray-300;
        @apply hover:border-gray-500;
        @apply transition-colors;
        @apply duration-200;
    }

    .preview-image {
        @apply w-full;
        @apply aspect-[4/1];
        @apply object-cover;
    }

    .edit-overlay {
        @apply absolute;
        @apply inset-0;
        @apply flex;
        @apply items-center;
        @apply justify-center;
        @apply bg-black;
        @apply bg-opacity-0;
        @apply transition-opacity;
        @apply duration-200;
    }

    .image-preview-container:hover .edit-overlay {
        @apply bg-opacity-30;
    }

    .edit-text {
        @apply text-white;
        @apply font-medium;
        @apply opacity-0;
        @apply transition-opacity;
        @apply duration-200;
    }

    .image-preview-container:hover .edit-text {
        @apply opacity-100;
    }

    .cropper-wrapper {
        @apply mb-5;
        @apply w-full;
        @apply h-[400px];
        @apply flex;
        @apply justify-center;
        @apply items-center;
        @apply overflow-hidden;
    }

    .file-input-container {
        @apply flex;
        @apply justify-center;
        @apply items-center;
        @apply w-full;
    }

    .choose-file-button {
        @apply px-4;
        @apply py-2;
        @apply primary;
        @apply rounded-lg;
        @apply cursor-pointer;
    }

    .error-message {
        @apply text-red-500;
        @apply mt-2;
        @apply text-center;
        @apply font-medium;
    }

    :deep(.banner-stencil) {
        @apply border-2;
        @apply border-white;
    }

    :deep(.cropper) {
        @apply max-h-full;
    }

    .loading-spinner {
        @apply inline-block;
        @apply w-4;
        @apply h-4;
        @apply mr-2;
        @apply border-2;
        @apply border-white;
        @apply border-t-transparent;
        @apply rounded-full;
        animation: spin 1s linear infinite;
    }

    @keyframes spin {
        from {
            transform: rotate(0deg);
        }
        to {
            transform: rotate(360deg);
        }
    }
</style>

<i18n>
{
    "en": {
        "title": "Banner Editor",
        "description": "Upload or edit your profile banner image. The recommended size is 1024x256 pixels (4:1 ratio).",
        "chooseImage": "Choose an image",
        "clickToEdit": "Click to edit",
        "uploading": "Uploading"
    },
    "fr": {
        "title": "Éditeur de bannière",
        "description": "Téléchargez ou modifiez votre image de bannière de profil. La taille recommandée est de 1024x256 pixels (ratio 4:1).",
        "chooseImage": "Choisir une image",
        "clickToEdit": "Cliquez pour modifier",
        "uploading": "Téléchargement"
    }
}
</i18n>
