<script lang='ts' setup>
import { documentAttachOutline, trashOutline } from "ionicons/icons";

interface FileItem {
  name: string;
  size: number;
  url?: string;
}

const props = withDefaults(defineProps<{
  modelValue?: string[];
  label?: string;
  placeholder?: string;
  accept?: string;
  multiple?: boolean;
  maxSize?: number; // MB
  maxFiles?: number;
}>(), {
  modelValue: () => [],
  accept: "*/*",
  multiple: true,
  maxSize: 10,
  maxFiles: 5,
});

const emit = defineEmits<{
  (e: "update:modelValue", value: string[]): void;
}>();

const { t } = useI18n();
const fileInput = ref<HTMLInputElement>();
const files = ref<FileItem[]>([]);

// 初始化已有文件
watchEffect(() => {
  if (props.modelValue && props.modelValue.length > 0) {
    files.value = props.modelValue.map(url => ({
      name: url.split("/").pop() || "file",
      size: 0,
      url,
    }));
  }
});

function handleFileSelect(event: Event) {
  const input = event.target as HTMLInputElement;
  const selectedFiles = Array.from(input.files || []);

  if (!selectedFiles.length)
    return;

  // 检查文件数量限制
  if (files.value.length + selectedFiles.length > props.maxFiles) {
    // TODO: 显示错误提示
    console.warn(`最多只能上传 ${props.maxFiles} 个文件`);
    return;
  }

  selectedFiles.forEach((file) => {
    // 检查文件大小
    if (file.size > props.maxSize * 1024 * 1024) {
      console.warn(`文件 ${file.name} 超过 ${props.maxSize}MB 限制`);
      return;
    }

    // 创建预览 URL
    const url = URL.createObjectURL(file);
    files.value.push({
      name: file.name,
      size: file.size,
      url,
    });
  });

  // 更新值
  updateValue();

  // 重置 input
  if (fileInput.value) {
    fileInput.value.value = "";
  }
}

function removeFile(index: number) {
  const file = files.value[index];
  if (file.url && file.url.startsWith("blob:")) {
    URL.revokeObjectURL(file.url);
  }
  files.value.splice(index, 1);
  updateValue();
}

function updateValue() {
  const urls = files.value.map(f => f.url || "").filter(Boolean);
  emit("update:modelValue", urls);
}

function formatFileSize(bytes: number): string {
  if (bytes === 0)
    return "0 B";
  const k = 1024;
  const sizes = ["B", "KB", "MB", "GB"];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return `${Number.parseFloat((bytes / k ** i).toFixed(2))} ${sizes[i]}`;
}

function triggerFileInput() {
  fileInput.value?.click();
}
</script>

<template>
  <div class="file-upload">
    <div v-if="label" class="file-upload-label">
      {{ label }}
    </div>

    <input
      ref="fileInput"
      type="file"
      :accept="accept"
      :multiple="multiple"
      class="file-input-hidden"
      @change="handleFileSelect"
    >

    <!-- 上传按钮 -->
    <ion-button
      v-if="files.length < maxFiles"
      expand="block"
      fill="outline"
      class="upload-button"
      @click="triggerFileInput"
    >
      <ion-icon slot="start" :icon="documentAttachOutline" />
      {{ placeholder || t('common.uploadFile') }}
    </ion-button>

    <!-- 文件列表 -->
    <div v-if="files.length > 0" class="file-list">
      <div v-for="(file, index) in files" :key="index" class="file-item">
        <div class="file-info">
          <ion-icon :icon="documentAttachOutline" class="file-icon" />
          <div class="file-details">
            <div class="file-name">
              {{ file.name }}
            </div>
            <div v-if="file.size" class="file-size">
              {{ formatFileSize(file.size) }}
            </div>
          </div>
        </div>
        <ion-button fill="clear" size="small" color="danger" @click="removeFile(index)">
          <ion-icon slot="icon-only" :icon="trashOutline" />
        </ion-button>
      </div>
    </div>

    <div v-if="files.length > 0" class="file-count">
      {{ files.length }} / {{ maxFiles }} {{ t('common.files') }}
    </div>
  </div>
</template>

<style scoped>
.file-upload {
  width: 100%;
}

.file-upload-label {
  font-size: 14px;
  font-weight: 500;
  margin-bottom: 8px;
  color: var(--ion-text-color);
}

.file-input-hidden {
  display: none;
}

.upload-button {
  --border-style: dashed;
  --border-width: 2px;
  margin-bottom: 12px;
}

.file-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 12px;
}

.file-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px;
  background: var(--ion-color-light);
  border-radius: 8px;
  transition: background-color 0.2s;
}

.file-item:hover {
  background: var(--ion-color-light-shade);
}

.file-info {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1;
  min-width: 0;
}

.file-icon {
  font-size: 24px;
  color: var(--ion-color-primary);
  flex-shrink: 0;
}

.file-details {
  flex: 1;
  min-width: 0;
}

.file-name {
  font-size: 14px;
  font-weight: 500;
  color: var(--ion-text-color);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-size {
  font-size: 12px;
  color: var(--ion-color-medium);
  margin-top: 2px;
}

.file-count {
  font-size: 12px;
  color: var(--ion-color-medium);
  text-align: right;
  margin-top: 8px;
}
</style>
