<script setup lang="ts">
import { computed, ref } from 'vue';

import { ElButton, ElLink, ElMessage } from 'element-plus';

import { api } from '#/api/request';
import { $t } from '#/locales';
import ChooseResource from '#/views/ai/resource/ChooseResource.vue';

import {
  appendWorkflowFileValues,
  buildWorkflowFileValueFromResource,
  buildWorkflowFileValueFromUpload,
  formatWorkflowFileSize,
  normalizeWorkflowFileValues,
  validateWorkflowFileSelection,
  validateWorkflowFileValues,
  WORKFLOW_FILE_LIMITS,
} from './workflowFileValue';

const props = defineProps({
  modelValue: {
    type: [Array, Object],
    default: undefined,
  },
});

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

const uploadLoading = ref(false);
const fileInputRef = ref<HTMLInputElement | null>(null);

const currentFiles = computed(() => normalizeWorkflowFileValues(props.modelValue));

function triggerSelectFile() {
  if (uploadLoading.value) {
    return;
  }
  fileInputRef.value?.click();
}

async function handleNativeFileChange(event: Event) {
  const input = event.target as HTMLInputElement;
  const files = Array.from(input.files || []);
  if (files.length === 0) {
    return;
  }

  uploadLoading.value = true;
  try {
    validateWorkflowFileSelection(currentFiles.value, files);
    const uploadedFiles = [];
    for (const file of files) {
      const res = await api.upload('/api/v1/commons/upload', { file }, {});
      uploadedFiles.push(buildWorkflowFileValueFromUpload(file, res?.data?.path));
    }
    const nextFiles = appendWorkflowFileValues(currentFiles.value, uploadedFiles);
    validateWorkflowFileValues(nextFiles);
    emit('update:modelValue', nextFiles);
  } catch (error: any) {
    ElMessage.error(error?.message || '文件上传失败');
    console.error('工作流文件上传失败', error);
  } finally {
    uploadLoading.value = false;
    input.value = '';
  }
}

function handleChooseResource(resources: any) {
  try {
    const resourceList = Array.isArray(resources) ? resources : [resources];
    const fileValues = resourceList
      .map((resource) => buildWorkflowFileValueFromResource(resource || {}))
      .filter(Boolean);
    const nextFiles = appendWorkflowFileValues(currentFiles.value, fileValues);
    validateWorkflowFileValues(nextFiles);
    emit('update:modelValue', nextFiles);
  } catch (error: any) {
    ElMessage.error(error?.message || '素材文件选择失败');
  }
}

function removeFile(filePath: string) {
  const nextFiles = currentFiles.value.filter((item) => item.filePath !== filePath);
  emit('update:modelValue', nextFiles);
}

function clearFiles() {
  emit('update:modelValue', []);
}
</script>

<template>
  <div class="workflow-file-input">
    <input
      ref="fileInputRef"
      class="workflow-file-input__native"
      type="file"
      multiple
      @change="handleNativeFileChange"
    />

    <div class="workflow-file-input__hint">
      最多 {{ WORKFLOW_FILE_LIMITS.maxCount }} 个文件，单个不超过
      {{ formatWorkflowFileSize(WORKFLOW_FILE_LIMITS.maxSingleSize) }}，总计不超过
      {{ formatWorkflowFileSize(WORKFLOW_FILE_LIMITS.maxTotalSize) }}
    </div>

    <div v-if="currentFiles.length > 0" class="workflow-file-input__list">
      <div
        v-for="item in currentFiles"
        :key="item.filePath"
        class="workflow-file-input__summary"
      >
        <div class="workflow-file-input__content">
          <div class="workflow-file-input__name">
            {{ item.fileName }}
          </div>
          <div class="workflow-file-input__meta">
            <span>{{ formatWorkflowFileSize(item.size) }}</span>
            <ElLink
              v-if="item.url || item.filePath"
              :href="item.url || item.filePath"
              target="_blank"
              type="primary"
            >
              {{ $t('button.view') }}
            </ElLink>
          </div>
        </div>
        <ElButton text type="danger" @click="removeFile(item.filePath)">
          {{ $t('button.delete') }}
        </ElButton>
      </div>
    </div>

    <div class="workflow-file-input__actions">
      <ElButton
        type="primary"
        plain
        :loading="uploadLoading"
        @click="triggerSelectFile"
      >
        {{ currentFiles.length > 0 ? '继续上传' : $t('button.upload') }}
      </ElButton>
      <ChooseResource attr-name="file" multiple @choose="handleChooseResource" />
      <ElButton
        v-if="currentFiles.length > 0"
        text
        type="danger"
        @click="clearFiles"
      >
        清空
      </ElButton>
    </div>
  </div>
</template>

<style scoped>
.workflow-file-input {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.workflow-file-input__native {
  display: none;
}

.workflow-file-input__hint {
  font-size: 12px;
  color: var(--el-text-color-secondary);
  line-height: 1.5;
}

.workflow-file-input__list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.workflow-file-input__summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px;
  border: 1px solid var(--el-border-color-light);
  border-radius: 10px;
  background: var(--el-fill-color-blank);
}

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

.workflow-file-input__name {
  font-size: 13px;
  font-weight: 600;
  color: var(--el-text-color-primary);
  word-break: break-word;
}

.workflow-file-input__meta {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
  font-size: 12px;
  color: var(--el-text-color-secondary);
}

.workflow-file-input__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
</style>
