<template>
  <div class="file-preview" @click="handleClick">
    <div class="file-preview__icon">
      <FileOutlined v-if="!isImage" style="font-size: 24px; color: var(--color-primary)" />
      <img
        v-else
        :src="url"
        :alt="name"
        class="file-preview__thumbnail"
        loading="lazy"
        @click.stop="showPreview = true"
      />
    </div>
    <div class="file-preview__info">
      <span class="file-preview__name">{{ name }}</span>
      <span v-if="size" class="file-preview__size">{{ size }}</span>
    </div>
    <a-button type="link" size="small" class="file-preview__download" @click.stop="download">
      <DownloadOutlined />
    </a-button>
    <!-- Image preview modal -->
    <div v-if="showPreview && isImage" class="file-preview__overlay" @click.stop="showPreview = false">
      <img :src="url" :alt="name" class="file-preview__full" />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { Button as AButton } from 'ant-design-vue'
import { FileOutlined, DownloadOutlined } from '@ant-design/icons-vue'

const props = defineProps<{
  url: string
  name: string
  size?: string
}>()

const showPreview = ref(false)

const imageExtensions = ['png', 'jpg', 'jpeg', 'gif', 'svg', 'webp', 'bmp', 'ico']
const isImage = computed(() => {
  const ext = props.name.split('.').pop()?.toLowerCase() || ''
  return imageExtensions.includes(ext)
})

/** Validate URL protocol — only allow http/https to prevent javascript:/data: injection */
function isSafeUrl(url: string): boolean {
  return /^https?:\/\//i.test(url)
}

function handleClick() {
  if (isImage.value && isSafeUrl(props.url)) {
    showPreview.value = true
  }
}

function download() {
  if (!isSafeUrl(props.url)) return
  const a = document.createElement('a')
  a.href = props.url
  a.download = props.name
  a.target = '_blank'
  a.rel = 'noopener noreferrer'
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
}
</script>

<style scoped>
.file-preview {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  background: var(--bg-secondary);
  cursor: pointer;
  transition: border-color var(--transition-fast);
  max-width: 320px;
}

.file-preview:hover {
  border-color: var(--color-primary-light);
}

.file-preview__icon {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  background: var(--bg-tertiary);
  overflow: hidden;
}

.file-preview__thumbnail {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--radius-sm);
}

.file-preview__info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.file-preview__name {
  font-size: var(--font-sm);
  font-weight: var(--font-weight-medium);
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-preview__size {
  font-size: var(--font-xs);
  color: var(--text-tertiary);
}

.file-preview__download {
  flex-shrink: 0;
  padding: 0;
}

.file-preview__overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 9999;
  background: rgba(0, 0, 0, 0.8);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.file-preview__full {
  max-width: 90vw;
  max-height: 90vh;
  object-fit: contain;
  border-radius: var(--radius-md);
}
</style>
