<template>
  <v-row no-gutters class="w-100 pb-5" @click="resetErrorMessage">

    <!-- VIEW MODE -->
    <template v-if="viewMode">
      <div class="w-100">
        <v-file-upload-item v-for="({ file }, idx) in filesCollection" :key="fileKey(file)" :file="file" lines="one" nav
          @click="handleClickItem(file)">
          <template #prepend>
            <v-avatar size="32" rounded></v-avatar>
          </template>

          <!-- delete hidden in view mode -->
          <template #clear>
            <!-- empty on purpose -->
          </template>
        </v-file-upload-item>
      </div>
    </template>

    <!-- NORMAL MODE -->
    <template v-else>
      <v-file-upload v-model="uploadFiles" density="compact" @update:model-value="handleUpdateValue"
        :loading="processing" :disabled="processing" :height="height" :title="title" :accept="accept"
        :name="`upload_images`" class="text-caption w-100" clearable :multiple="multiple">
        <template #item="{ props: itemProps, file }">
          <v-file-upload-item v-bind="itemProps" lines="one" nav @click="handleClickItem(file)">
            <template #prepend>
              <v-avatar size="32" rounded></v-avatar>
            </template>

            <!-- delete button NOT shown in view mode -->
            <template #clear="{ props: clearProps }">
              <v-btn v-if="!viewMode" color="primary" @click.stop="handleRemove(file)"></v-btn>
            </template>
          </v-file-upload-item>
        </template>
      </v-file-upload>
    </template>

    <v-row no-gutters class="w-100" v-if="errorMessage">
      <p class="text-error w-100 text-center text-subtitle-2">{{ errorMessage }}</p>
    </v-row>

    <ImageCarousel v-model="showImageCarousel" :files="idsArray" :active-file-id="activeImageId" />
  </v-row>
</template>


<script setup lang="ts">
import { nextTick, ref, onMounted, watch } from 'vue'

const props = defineProps({
  height: {
    type: [Number, String],
    default: 68,
  },
  multiple: {
    type: Boolean,
    default: false,
  },
  maxLength: {
    type: Number,
    default: 10,
  },
  title: {
    type: String,
    default: 'Upload Images'
  },
  accept: {
    type: String,
    default: "image/*"
  },
  viewMode: {
    type: Boolean,
    default: false
  }
})

const { addFile, deleteFile, getFileUrl, getFileById, urlToFile } = useFile()

const showImageCarousel = ref(false)
const activeImageId = ref("")

// The parent v-model binding
const idsArray = defineModel<string[]>({ default: [] })

const uploadFiles = ref<File[]>([])
const filesCollection = ref<{ file: File; id: string }[]>([])
const errorMessage = ref('')
const processing = ref(false)

function fileKey(f: File) {
  return `${f.name}_${f.size}_${f.lastModified}`
}

async function handleRemove(removedFile: File) {
  const key = fileKey(removedFile)
  const arr = [...filesCollection.value]

  const removedItem = arr.find((item) => fileKey(item.file) === key)
  if (!removedItem) return

  filesCollection.value = arr.filter((item) => item.id !== removedItem.id)
  uploadFiles.value = uploadFiles.value.filter((f) => fileKey(f) !== key)


  idsArray.value = filesCollection.value.map((x) => x.id)

}

async function handleClickItem(file: File) {
  const isImageOrVideo =
    file.type.startsWith('image/') ||
    /\.(jpg|jpeg|png|gif|webp|bmp|svg|mp4|mov|mkv|avi)$/i.test(file.name)


  const found = filesCollection.value.find((item) => fileKey(item.file) === fileKey(file))
  if (!found) return


  if (isImageOrVideo) {
    activeImageId.value = found.id
    showImageCarousel.value = true
    return;
  }

  await downloadFile(found.id, file.name)
}

async function downloadFile(id: string, filename: string) {
  try {
    const url = await getFileUrl(id)
    const link = document.createElement('a')
    link.href = url
    link.download = filename
    link.target = '_blank'

    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
  } catch (err) {
    console.error('Failed to download file', err)
    errorMessage.value = 'Failed to download file.'
  }
}





  async function handleUpdateValue(value: File[]) {
    await nextTick()
    const max = props.maxLength
    const existingLength = filesCollection.value.length
    errorMessage.value = ''

    if (existingLength + value.length > max) {
      value = value.slice(0, max - existingLength)
      errorMessage.value = `Max allowed images is ${max}`
    }

    const collectionKeys = filesCollection.value.map((x) => fileKey(x.file))
    const addedFiles = value.filter((f) => !collectionKeys.includes(fileKey(f)))

    processing.value = true
    try {
      for (const file of addedFiles) {
        const res = await addFile(file) // should return { id, url }
        if (res?.id) {
          filesCollection.value = [...filesCollection.value, { file, id: res.id }]
        }
      }

      uploadFiles.value = filesCollection.value.map((x) => x.file)

    } catch (err) {
      console.error('Upload failed', err)
      errorMessage.value = 'Failed to upload some files.'
    } finally {
      processing.value = false
    }
  }


  async function loadFilesFromIds(ids: string[]) {
    const result: { file: File; id: string }[] = []
    for (const id of ids) {
      try {
        const meta = await getFileById(id) as any
        const name: string = meta?.data?.name || meta?.name || `file_${id}`
        const url = getFileUrl(id)
        const file = await urlToFile(url, name)
        result.push({ file, id })
      } catch (err) {
        console.warn('Failed to load file from ID:', id, err)
      }
    }
    return result
  }


  function resetErrorMessage() {
    errorMessage.value = ''
  }


  onMounted(async () => {
    setTimeout(async () => {
      if (idsArray.value.length > 0) {
        const loadedFiles = await loadFilesFromIds(idsArray.value)
        filesCollection.value = loadedFiles
        uploadFiles.value = loadedFiles.map((x) => x.file)
      }
    }, 200)
  })

  watch(filesCollection, () => {
    idsArray.value = [...filesCollection.value.map(x => x.id)]
  }, { deep: true })


</script>


<style scoped>
* :deep(.v-file-upload-title) {
  font-size: 1rem;
  font-weight: 500;
}

* :deep(.v-file-upload-items) {
  min-width: 100%;
}
</style>