<template>
  <div>
    <el-button type="primary" @click="dialogVisible = true">选择文件</el-button>
    <div v-if="selectedFiles.length > 0" class="selected-files-list">
      <el-tag v-for="(file, idx) in selectedFiles" :key="file.id" closable @close="removeFile(idx)" style="margin: 2px">
        {{ file.name }}
      </el-tag>
    </div>
    <el-dialog title="选择媒资文件" v-model="dialogVisible" width="900px" append-to-body @close="restoreSelection">
      <el-form :inline="true" :model="queryParams" class="mb-2">
        <el-form-item label="名称">
          <el-input v-model="queryParams.originalName" placeholder="文件名" clearable style="width: 180px"
            @keyup.enter="getFileList" />
        </el-form-item>
        <el-form-item label="类型">
          <el-select v-model="queryParams.type" clearable placeholder="全部" style="width: 120px">
            <el-option label="全部" :value="''" />
            <el-option label="图片" :value="1" />
            <el-option label="视频" :value="2" />
            <el-option label="音频" :value="3" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="getFileList">搜索</el-button>
        </el-form-item>
      </el-form>
      <el-table v-loading="dialogLoading" ref="fileTable" :data="fileList" reserve-selection row-key="id"
        @selection-change="handleSelectionFile" @select="handleSelect" @select-all="handleSelectAll">
        <el-table-column type="selection" width="55" header-align="center" :selectable="isSelectableRow" />
        <el-table-column label="类型" header-align="left" prop="type" width="80">
          <template #default="scope">
            <dict-tag :options="smsb_source_type" :value="scope.row.type" />
          </template>
        </el-table-column>
        <el-table-column label="原名" header-align="left" prop="originalName" width="150" :show-overflow-tooltip="true" />
        <el-table-column label="大小" header-align="left" prop="size" />
        <el-table-column label="时长" header-align="left" prop="duration" />
        <el-table-column label="截图" header-align="left" prop="screenshot">
          <template #default="scope">
            <image-preview :src="scope.row.screenshot" style="width: 40px; height: 40px; cursor: pointer" />
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="fileTotal > 0" :total="fileTotal" v-model:page="queryParams.pageNum"
        v-model:limit="queryParams.pageSize" @pagination="getFileList" />
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmSelect">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { smsb_source_type } = toRefs<any>(proxy?.useDict('smsb_source_type'));
import { ref, watch, defineProps, defineEmits, nextTick } from 'vue';
import { listMinioData } from '@/api/smsb/source/minioData';
import type { MinioDataVO, MinioDataQuery } from '@/api/smsb/source/minioData_type';

const props = defineProps<{ modelValue: string; single?: boolean; onlyImage?: boolean }>();
const emit = defineEmits(['update:modelValue']);

const dialogVisible = ref(false);
const dialogLoading = ref(false);
const fileList = ref<MinioDataVO[]>([]);
const fileTotal = ref(0);
const selectedFiles = ref<any[]>([]);
// 控制哪些行可选
function isSelectableRow(row: any) {
  if (props.onlyImage) return row.type === 1;
  return true;
}
const fileTable = ref();

const queryParams = ref<MinioDataQuery>({
  pageNum: 1,
  pageSize: 10,
  originalName: '',
  type: ''
});

// 初始化时，如果有值，反序列化
watch(
  () => props.modelValue,
  (val) => {
    if (val) {
      try {
        selectedFiles.value = JSON.parse(val);
      } catch {
        selectedFiles.value = [];
      }
    } else {
      selectedFiles.value = [];
    }
  },
  { immediate: true }
);

// 查询文件资源列表
const getFileList = async () => {
  dialogLoading.value = true;
  try {
    const res = await listMinioData(queryParams.value);
    console.log('[getFileList] raw:', res);
    console.log('[getFileList] rows:', res.rows);
    const mapped = (res.rows || []).map((item: any, idx: number) => {
      const sizeNum = Number(item.size);
      const sizeStr = !isNaN(sizeNum) && sizeNum > 0 ? (sizeNum / 1024).toFixed(3) + 'MB' : '0MB';
      if (isNaN(sizeNum)) {
        console.warn(`[getFileList] row[${idx}] 非法size:`, item.size, item);
      }
      return {
        ...item,
        size: sizeStr
      };
    });
    fileList.value = mapped;
    console.log('[getFileList] mapped fileList:', mapped);
    console.log('[getFileList] fileList.value:', fileList.value, 'isArray:', Array.isArray(fileList.value), 'length:', fileList.value.length);

    fileTotal.value = res.total || 0;
    await nextTick();
    restoreSelection();
  } finally {
    dialogLoading.value = false;
  }
};

// 多选框选中文件数据
function handleSelectionFile(selection: MinioDataVO[]) {
  console.log('[handleSelectionFile] selection:', selection);
  if (props.single && props.onlyImage) {
    // 单选且仅图片
    if (selection.length > 0) {
      const img = selection.find((item) => item.type === 1);
      if (img) {
        selectedFiles.value = [
          {
            id: img.id,
            name: img.originalName,
            type: img.type,
            duration: 10,
            order: 1,
            url: img.fileUrl,
            md5: img.md5
          }
        ];
      } else {
        selectedFiles.value = [];
      }
    } else {
      selectedFiles.value = [];
    }
  } else if (props.single) {
    // 单选任意类型
    if (selection.length > 0) {
      selectedFiles.value = [
        {
          id: selection[0].id,
          name: selection[0].originalName,
          type: selection[0].type,
          duration: selection[0].duration,
          order: 1,
          url: selection[0].fileUrl,
          md5: selection[0].md5
        }
      ];
    } else {
      selectedFiles.value = [];
    }
  } else {
    // 多选多类型
    selectedFiles.value = selection.map((item, idx) => ({
      id: item.id,
      name: item.originalName,
      type: item.type,
      duration: item.duration,
      order: idx + 1,
      url: item.fileUrl,
      md5: item.md5
    }));
  }
}
// 取消单个选中
function handleSelect(selection: MinioDataVO[], row: MinioDataVO) {
  if (!selection.some((item) => String(item.id) === String(row.id))) {
    selectedFiles.value = selectedFiles.value.filter((f) => String(f.id) !== String(row.id));
    selectedFiles.value = selectedFiles.value.map((f, idx) => ({ ...f, order: idx + 1 }));
  }
}
// 取消全选
function handleSelectAll(selection: MinioDataVO[]) {
  const currentPageIds = new Set(fileList.value.map((item) => String(item.id)));
  const selectedIds = new Set(selection.map((item) => String(item.id)));
  selectedFiles.value = selectedFiles.value.filter((f) => !currentPageIds.has(String(f.id)) || selectedIds.has(String(f.id)));
  selectedFiles.value = selectedFiles.value.map((f, idx) => ({ ...f, order: idx + 1 }));
}

function removeFile(idx: number) {
  selectedFiles.value.splice(idx, 1);
  emitChange();
}
function confirmSelect() {
  if (props.single && props.onlyImage) {
    if (selectedFiles.value.length === 0 || selectedFiles.value[0].type !== 1) {
      ElMessage.error('只能选择图片文件作为背景');
      return;
    }
  }
  dialogVisible.value = false;
  emitChange();
}
function emitChange() {
  emit('update:modelValue', JSON.stringify(selectedFiles.value));
}
// 弹窗关闭时还原选中状态
function restoreSelection() {
  nextTick(() => {
    if (!fileTable.value) return;
    const selectedIds = new Set(selectedFiles.value.map((f) => String(f.id)));
    fileList.value.forEach((row) => {
      fileTable.value.toggleRowSelection(row, selectedIds.has(String(row.id)));
    });
  });
}

// 弹窗首次打开时自动加载
watch(dialogVisible, (val) => {
  if (val) getFileList();
});
</script>

<style scoped>
.selected-files-list {
  margin: 8px 0;
}
</style>
