<template>
  <div class="image-uploader">
    <div class="image-uploader__stage">
      <div v-if="previewUrl" class="image-uploader__preview">
        <img :src="previewUrl" :alt="fileName || 'تصویر'" />
      </div>
      <button
        v-else
        type="button"
        class="image-uploader__main-btn"
        :disabled="disabled"
        @click="triggerFilePicker"
      >
        <SvgIcon name="upload" :size="48" color="var(--color-thd-gray)" />
      </button>

      <p v-if="fileName && previewUrl" class="image-uploader__name">{{ fileName }}</p>
    </div>

    <div v-if="previewUrl" class="image-uploader__actions">
      <button
        type="button"
        class="image-uploader__btn"
        :disabled="disabled"
        title="جایگزینی تصویر"
        @click="triggerFilePicker"
      >
        <SvgIcon name="upload" :size="20" color="var(--color-thd-gray)" />
      </button>
      <button type="button" class="image-uploader__btn" title="حذف" @click="clear">
        <SvgIcon name="close" :size="20" color="var(--color-thd-gray)" />
      </button>
    </div>

    <input
      ref="fileInput"
      type="file"
      :accept="accept"
      class="image-uploader__file-input"
      @change="onFileSelected"
    />

    <p v-if="error" class="image-uploader__error">{{ error }}</p>
  </div>
</template>

<script setup>
import { toast } from 'vue3-toastify'
import { onBeforeUnmount, ref, watch } from 'vue'
import SvgIcon from '@/components/icons/SvgIcon.vue'

const props = defineProps({
  modelValue: { type: [Object, File, String, null], default: null },
  accept: { type: String, default: 'image/*' },
  maxSizeKb: { type: Number, default: 5120 },
  disabled: { type: Boolean, default: false },
  error: { type: String, default: '' },
})

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

const initialUrl =
  typeof props.modelValue === 'string' ? props.modelValue : props.modelValue?.url || null

const previewUrl = ref(initialUrl)
const fileName = ref(
  props.modelValue instanceof File ? props.modelValue.name : props.modelValue?.name || ''
)
const fileInput = ref(null)

const revokePreview = () => {
  if (previewUrl.value && previewUrl.value.startsWith('blob:')) {
    URL.revokeObjectURL(previewUrl.value)
  }
}

const setFile = (file) => {
  revokePreview()
  previewUrl.value = URL.createObjectURL(file)
  fileName.value = file.name
  emit('update:modelValue', file)
}

const triggerFilePicker = () => fileInput.value?.click()

const onFileSelected = (event) => {
  const file = event.target?.files?.[0]
  if (event.target) event.target.value = ''
  if (!file) return
  if (file.size > props.maxSizeKb * 1024) {
    toast.error(`حجم فایل نباید بیشتر از ${props.maxSizeKb} کیلوبایت باشد.`)
    return
  }
  setFile(file)
}

const clear = () => {
  revokePreview()
  previewUrl.value = null
  fileName.value = ''
  emit('update:modelValue', null)
}

watch(
  () => props.modelValue,
  (val) => {
    if (val == null) {
      revokePreview()
      previewUrl.value = null
      fileName.value = ''
    }
  }
)

onBeforeUnmount(revokePreview)
</script>

<style lang="scss" scoped>
.image-uploader {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  padding: 1rem;
  background: #eee;
  border-radius: 1.5rem;
  min-height: 18rem;
  justify-content: space-between;

  &__stage {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.625rem;
    width: 100%;
  }

  &__main-btn {
    width: 8rem;
    height: 8rem;
    border-radius: 9999px;
    background: #fff;
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: transform 0.15s ease, box-shadow 0.15s ease;

    &:hover:enabled {
      transform: scale(1.02);
      box-shadow: 0 4px 14px rgba(0, 0, 0, 8%);
    }

    &:disabled {
      cursor: not-allowed;
      opacity: 0.6;
    }
  }

  &__preview {
    width: 8rem;
    height: 8rem;
    border-radius: 1rem;
    overflow: hidden;
    background: #fff;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 6%);

    img {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
  }

  &__name {
    max-width: 14rem;
    margin: 0;
    text-align: center;
    font-family: var(--font-family-fa);
    font-size: 0.75rem;
    color: #5d5d5d;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  &__actions {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
  }

  &__btn {
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 9999px;
    background: #fff;
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 6%);
    transition: transform 0.15s ease;

    &:hover:enabled {
      transform: scale(1.05);
    }

    &:disabled {
      cursor: not-allowed;
      opacity: 0.5;
    }
  }

  &__file-input {
    display: none;
  }

  &__error {
    margin: 0;
    font-family: var(--font-family-fa);
    font-size: 0.75rem;
    color: var(--color-error);
  }
}
</style>
