<script setup lang="ts">
import { ImagePlus, X } from '@lucide/vue';
import { computed, ref } from 'vue';
import { Button } from '@/components/ui/button';
import { Field, FieldDescription, FieldError, FieldLabel } from '@/components/ui/field';
import { Input } from '@/components/ui/input';
import { cn } from '@/lib/utils';

const props = defineProps<{
    id: string;
    label: string;
    description?: string;
    currentUrl?: string | null;
    errors?: string[];
    accept?: string;
    required?: boolean;
    previewClass?: string;
}>();

const model = defineModel<File | null>();

const previewUrl = ref<string | null>(null);

const displayUrl = computed(() => previewUrl.value ?? props.currentUrl ?? null);

function onFileChange(event: Event) {
    const input = event.target as HTMLInputElement;
    const file = input.files?.[0] ?? null;

    if (previewUrl.value) {
        URL.revokeObjectURL(previewUrl.value);
        previewUrl.value = null;
    }

    model.value = file;
    previewUrl.value = file ? URL.createObjectURL(file) : null;
}

function clearFile() {
    if (previewUrl.value) {
        URL.revokeObjectURL(previewUrl.value);
        previewUrl.value = null;
    }

    model.value = null;
}
</script>

<template>
    <Field>
        <FieldLabel :for="id" :required="required">
            {{ label }}
        </FieldLabel>
        <FieldDescription v-if="description">
            {{ description }}
        </FieldDescription>

        <div class="space-y-3">
            <div v-if="displayUrl" :class="cn(
                'relative overflow-hidden rounded-lg border bg-muted/30',
                previewClass ?? 'aspect-video max-w-md',
            )">
                <img :src="displayUrl" :alt="label" class="size-full object-cover">
                <Button v-if="model" type="button" variant="secondary" size="icon" class="absolute top-2 right-2 size-7"
                    @click="clearFile">
                    <X class="size-4" />
                </Button>
            </div>

            <div class="flex items-center gap-2">
                <Input :id="id" type="file" :accept="accept ?? 'image/*'" class="max-w-md cursor-pointer"
                    @change="onFileChange" />
                <ImagePlus v-if="!displayUrl" class="text-muted-foreground size-5 shrink-0" />
            </div>
        </div>

        <FieldError :errors="errors ?? []" />
    </Field>
</template>
