<script setup lang="ts">
import type { UploadInputProps } from '@bagelink/vue'
import { Btn, IMAGE_FORMATS_REGEXP, Icon, Card, Image, pathKeyToURL, Loading } from '@bagelink/vue'
import { watch, ref } from 'vue'

import { useFileUpload } from './useFileUpload'

const props = withDefaults(defineProps<UploadInputProps>(), {
	height: '215px',
	theme: 'dropzone',
	accept: '*',
})

const emit = defineEmits(['update:modelValue', 'addFileStart'])

const {
	fileQueue,
	pathKeys,
	removeFile,
	flushQueue,
	addFile,
	browse,
	pk,
} = useFileUpload({
	disabled: props.disabled,
	dirPath: props.dirPath,
	multiple: props.multiple,
	accept: props.accept,
	namespace: props.id || 'upload',
	onFileQueued: async () => {
		await flushQueue()
		updateModelValue()
	}
})

watch(() => props.modelValue, val => pk.value = val ? [val].flat().filter(Boolean) : [], { immediate: true })

const isImage = (str: string) => IMAGE_FORMATS_REGEXP.test(str)

const isDragOver = ref(false)

function handleDrag(e: DragEvent, isDragging = false) {
	e.preventDefault()
	e.stopPropagation()
	if (!props.disabled) isDragOver.value = isDragging
}

function updateModelValue() {
	if (props.multiple) emit('update:modelValue', pathKeys.value)
	else emit('update:modelValue', pathKeys.value[0] || undefined)
}

async function handleDrop(e: DragEvent) {
	if (props.disabled) return
	e.preventDefault()
	e.stopPropagation()
	emit('addFileStart')
	addFile(e.dataTransfer?.files)
	isDragOver.value = false
}

function fileName(pathKey: string) {
	if (!pathKey || typeof pathKey !== 'string') return 'file'
	return pathKey.split('/').pop() || 'file'
}
</script>

<template>
	<div class="bagel-input">
		<label v-if="label">{{ label }}</label>
		<input v-if="required && !pathKeys.length" placeholder="required" type="text" required class="pixel">
		<Card
			v-if="theme === 'basic'"
			outline
			class="flex p-05 gap-1"
			@dragover="(e) => handleDrag(e, true)"
			@drop="handleDrop"
		>
			<Btn
				v-if="!pathKeys.length && !fileQueue.length"
				class="px-1-5"
				icon="upload"
				outline
				:value="btnPlaceholder || 'Upload'"
				@click="browse()"
			/>

			<template v-for="path_key in pathKeys" :key="path_key">
				<div class="txt-gray txt-12 flex">
					<div class="m-05 flex opacity-7 z-99">
						<Btn
							v-tooltip="'Delete'"
							color="gray"
							thin
							icon="delete"
							@click="removeFile(path_key)"
						/>
						<Btn
							v-tooltip="'Replace'"
							color="gray"
							thin
							icon="autorenew"
							@click="browse()"
						/>
						<Btn
							icon="download"
							flat
							thin
							:href="pathKeyToURL(path_key)"
							:download="fileName(path_key)"
						/>
						<div class="flex gap-025 rounded pe-1 ps-05 py-025 bg-gray-80 -my-1 ">
							<Icon icon="draft" :size="1.5" />
							<p
								v-lightbox="{ src: pathKeyToURL(path_key), download: true }"
								class="ellipsis-1 word-break-all h-20 m-0 color-black txt16"
							>
								{{ fileName(path_key) }}
							</p>
						</div>
					</div>
				</div>
			</template>

			<span
				v-if="!pathKeys.length && !fileQueue.length"
				class="txt-gray txt-12"
			>
				{{ noFilePlaceholder || 'No file selected' }}
			</span>
		</Card>

		<div
			v-else
			class="fileUploadWrap"
			:class="{
				'fileDropZone': !pathKeys.length && !fileQueue.length,
				'dragover': isDragOver,
				'bgl_oval-upload': oval,
			}"
			:style="{ width, height }"
			@click="browse()"
			@dragover="(e) => handleDrag(e, true)"
			@drop="handleDrop"
			@dragleave="(e) => handleDrag(e)"
		>
			<slot name="files" :files="pathKeys" :fileQueue>
				<div v-if="multiple" class="bgl-multi-preview">
					<div
						v-for="path_key in pathKeys"
						:key="path_key"
						v-lightbox="{ src: pathKeyToURL(path_key), download: true }"
						class="multi-image-item-preview"
						:class="{ 'bgl_fill-image': fill }"
					>
						<Image
							v-if="isImage(path_key)"
							:pathKey="path_key"
							class="multi-preview"
						/>
						<Icon v-else icon="description" class="multi-preview" />
						<p class="m-0">
							{{ fileName(path_key) }}
						</p>
						<Btn
							thin
							flat
							icon="delete"
							color="red"
							@click="removeFile(path_key)"
						/>
					</div>
					<div
						v-for="file in fileQueue"
						:key="file.name"
						class="multi-image-item-preview"
						:class="{ 'bgl_fill-image': fill }"
					>
						<img
							v-if="isImage(file.file.type)"
							class="multi-preview"
							:src="file.url"
							alt=""
						>
						<Icon v-else icon="description" class="multi-preview" />
						<p class="no-margin multi-preview-txt">
							{{ file.name }}
						</p>
						<div
							class="pie"
							:style="{ '--p': file.progress }"
							style="--b: 2px"
							:class="{ complete: file.progress === 100 }"
						>
							<span v-if="file.progress < 100" class="progress">
								{{ file.progress.toFixed(0) }}
							</span>
							<Icon class="success" icon="check_circle" />
						</div>
					</div>
				</div>

				<div
					v-else-if="pathKeys.length > 0 || fileQueue.length > 0"
					class="bgl-single-preview"
				>
					<div
						v-for="path_key in pathKeys"
						:key="path_key"
						class="single-image-item-preview"
						:class="{ 'bgl_fill-image': fill }"
					>
						<div class="position-start m-05 flex opacity-7 z-99 gap-025">
							<Btn
								v-tooltip="'Delete'"
								color="gray"
								thin
								icon="delete"
								@click="removeFile(path_key)"
							/>
							<Btn
								v-tooltip="'Replace'"
								color="gray"
								thin
								icon="autorenew"
								@click="browse()"
							/>
							<Btn
								v-tooltip="'Download'"
								color="gray"
								thin
								icon="download"
								:href="pathKeyToURL(path_key)"
								:download="fileName(path_key)"
							/>
						</div>
						<div v-if="isImage(path_key)" class="h-100">
							<Image
								v-lightbox="{ src: pathKeyToURL(path_key), download: true }"

								class="single-preview"
								:pathKey="path_key"
								alt=""
							/>
						</div>
						<Icon
							v-else
							v-lightbox="{ src: pathKeyToURL(path_key), download: true }"
							:size="4"
							weight="2"
							icon="description"
							class="color-primary w-100"
						/>
					</div>
					<div
						v-for="file in fileQueue"
						:key="file.name"
						class="single-image-item-preview"
						:class="{ 'bgl_fill-image': fill }"
					>
						<Loading type="bar" :progress="file.progress" class="absolute bottom-05 end start w-100px mx-auto" />
						<img
							v-if="isImage(file.file.type)"
							class="single-preview opacity-5"
							:src="file.url"
							alt=""
						>
					</div>
				</div>
			</slot>

			<slot
				v-if="(!pathKeys.length && !fileQueue.length) || multiple"
				name="placeholder"
				:files="pathKeys"
				:fileQueue
				:browse
			>
				<p class="p-1 flex column hover fileUploadPlaceHolder justify-content-center mb-05 ">
					<Icon icon="upload_2" />
					<span class=" pretty balance">
						{{ dropPlaceholder || 'Drag and Drop files here or click to upload' }}
					</span>
				</p>
			</slot>
		</div>
	</div>
</template>

<style src="./upload.css" scoped></style>
