<script setup lang="ts">
import { onBeforeUnmount, ref, watch } from 'vue'
import { fetchAdminFileBlob, fetchFileBlobByURL } from '@/shared/api/files'

const props = defineProps<{
  source: string
  admin?: boolean
}>()

const objectURL = ref('')
const failed = ref(false)

function extractObjectKey(value: string) {
  try {
    const parsed = new URL(value, window.location.origin)
    return parsed.searchParams.get('key') || ''
  } catch {
    return ''
  }
}

function revokeCurrentURL() {
  if (!objectURL.value) return
  URL.revokeObjectURL(objectURL.value)
  objectURL.value = ''
}

async function loadImage() {
  revokeCurrentURL()
  failed.value = false
  if (!props.source) {
    failed.value = true
    return
  }
  try {
    const key = extractObjectKey(props.source)
    const blob = props.admin && key
      ? await fetchAdminFileBlob(key)
      : await fetchFileBlobByURL(props.source)
    objectURL.value = URL.createObjectURL(blob)
  } catch {
    failed.value = true
  }
}

function openImage() {
  if (!objectURL.value) return
  window.open(objectURL.value, '_blank')
}

watch(() => [props.source, props.admin] as const, loadImage, { immediate: true })

onBeforeUnmount(revokeCurrentURL)
</script>

<template>
  <button v-if="objectURL" class="chat-image-button" type="button" @click="openImage">
    <img :src="objectURL" alt="聊天图片" loading="lazy" decoding="async">
  </button>
  <span v-else class="chat-image-fallback">{{ failed ? '图片加载失败' : '图片加载中' }}</span>
</template>

<style scoped>
.chat-image-button {
  display: block;
  max-width: 220px;
  padding: 0;
  overflow: hidden;
  border: 0;
  border-radius: 8px;
  background: transparent;
  cursor: zoom-in;
}

.chat-image-button img {
  display: block;
  width: 100%;
  max-height: 260px;
  object-fit: cover;
}

.chat-image-fallback {
  display: inline-block;
  padding: 8px 10px;
  border-radius: 8px;
  background: #eef2f7;
  color: #6b7280;
  font-size: 12px;
}
</style>
