<script lang="ts" setup>
import { Upload } from "@icon-park/vue-next";
import BaseForm from "../base-form/BaseForm.vue";
import { ElMessage, type UploadInstance, type UploadUserFile } from "element-plus";
import * as XLSX from "xlsx";
import { type ExcelDataMapping } from "./type";
import { Delete } from "@element-plus/icons-vue";
interface Emits {
  (e: "update:mappedData", data: any[]): void;
  (e: "error", msg: string): void;
}
const props = defineProps({
  baseTitle: String,
  tableTitle: String,
  uploadDesc: String,
  itemArrayName: { type: String, required: true },
  mappingConfig: { type: Object, required: true },
});
const emit = defineEmits<Emits>();
const form = defineModel<any>("form");
const uploadRef = ref<UploadInstance>();
const baseFormComponentRef = ref<InstanceType<typeof BaseForm> | null>(null);

const getValue = (row: any, config: ExcelDataMapping) => {
  const { sourceKey, defaultValue, transform } = config;
  let rawValue: any;

  // 1. 处理 sourceKey 是数组的情况 (多对一 / 降级策略)
  if (Array.isArray(sourceKey)) {
    for (const key of sourceKey) {
      const val = row[key];
      // 只要找到非 undefined 且非 null 的值，就立即停止查找
      if (val !== undefined && val !== null) {
        rawValue = val;
        break;
      }
    }
  }
  // 2. 处理 sourceKey 是字符串的情况 (一对一)
  else if (typeof sourceKey === "string") {
    rawValue = row[sourceKey];
  }

  // 3. 如果没找到值，使用默认值
  if (rawValue === undefined || rawValue === null) {
    rawValue = defaultValue;
  }

  // 4. 执行转换函数 (如果有)
  if (transform && typeof transform === "function") {
    try {
      return transform(rawValue);
    } catch (e) {
      console.warn(`Transform error for key ${Array.isArray(sourceKey) ? sourceKey.join("/") : sourceKey}:`, e);
      return defaultValue;
    }
  }

  return rawValue;
};

const convertData = (jsonData: any) => {
  if (!Array.isArray(jsonData)) {
    emit("error", "jsonData 必须是数组");
    return [];
  }

  const result = jsonData.map(row => {
    const newRow: any = {};

    // Object.entries 返回的是 [string, any][]，我们需要断言为正确的类型
    // 或者直接在循环内部使用 config 变量
    for (const [targetKey, config] of Object.entries(props.mappingConfig)) {
      // 显式断言 config 的类型，防止 entries 推断丢失泛型信息
      const fieldConfig = config as ExcelDataMapping;
      newRow[targetKey] = getValue(row, fieldConfig);
    }

    return newRow;
  });

  emit("update:mappedData", result);
  return result;
};
const clearAllData = () => {
  // 1. 清空文件引用
  currentFile.value = null;

  // 2. 清空上传组件列表
  uploadRef.value?.clearFiles();

  // 3. 清空表格数据
  if (form.value && Array.isArray(form.value[props.itemArrayName])) {
    form.value[props.itemArrayName].splice(0, form.value[props.itemArrayName].length);
  }

  // 4. 清空验证
  if (baseFormComponentRef.value) {
    baseFormComponentRef.value.clearValidate();
  }
};
const handleFileChange = (file: any) => {
  // 文件大小校验
  const maxSize = 10 * 1024 * 1024; // 10MB
  if (file.size > maxSize) {
    ElMessage.error("文件大小不能超过 10MB");
    clearAllData();
    return;
  }

  clearAllData();

  // 更新当前文件显示
  currentFile.value = file;

  // 解析 Excel
  parseExcel(file.raw);
};
const parseExcel = (file: any) => {
  const reader = new FileReader();

  reader.onload = e => {
    if (!(e.target?.result instanceof ArrayBuffer)) {
      return;
    }
    try {
      const data = new Uint8Array(e.target.result);
      const workbook = XLSX.read(data, { type: "array" });

      // 获取第一个 sheet
      const firstSheetName = workbook.SheetNames[0];
      const worksheet = workbook.Sheets[firstSheetName];

      // 转换为 JSON（保留原始表头映射）
      const jsonData = XLSX.utils.sheet_to_json(worksheet, { defval: "" });

      if (jsonData.length === 0) {
        ElMessage.warning("Excel 文件为空");
        removeFile(); // 清空刚选的文件
        return;
      }

      // 映射字段（支持多种列名）
      const mappedData = convertData(jsonData);

      if (form.value) {
        // 如果 form.value[itemArrayName] 不存在，先初始化为空数组
        if (!Array.isArray(form.value[props.itemArrayName])) {
          form.value[props.itemArrayName] = [];
        }

        // 使用 splice 替换所有内容，这是最安全的触发数组更新的方式
        form.value[props.itemArrayName].splice(0, form.value[props.itemArrayName].length, ...mappedData);
      }

      ElMessage.success(`解析成功，共 ${mappedData.length} 条物料数据`);
    } catch (error) {
      console.error(error);
      ElMessage.error("文件解析失败，请检查文件格式");
    }
  };
  reader.readAsArrayBuffer(file);
};

// 【新增】存储当前上传的文件信息，用于显示和移除
const currentFile = ref<UploadUserFile | null>(null);

// 【新增】深度清理函数
const resetFormData = () => {
  // 1. 清空表单验证
  if (baseFormComponentRef.value) {
    // 方式 A: 调用暴露的 clearValidate 方法
    baseFormComponentRef.value.clearValidate();
    // 方式 B: 或者访问内部 formRef (如果暴露了)
    // baseFormComponentRef.value.formRef?.clearValidate();
  }

  // 2. 重置 form 对象 (保留非表格字段？通常重置是全部清空或设为初始值，这里设为空对象)
  if (form.value) {
    // 只清空表格数据，保留其他表单字段？还是全部重置？
    // 根据需求“数据清理不干净”，通常指表格和文件。
    // 这里我们清空表格数组和文件，其他字段由 BaseForm 的 reset 逻辑处理或手动置空
    if (Array.isArray(form.value[props.itemArrayName])) {
      form.value[props.itemArrayName].splice(0, form.value[props.itemArrayName].length);
    }
  }

  // 3. 清空文件状态
  currentFile.value = null;
  uploadRef.value?.clearFiles();

  // 4. 如果需要完全重置 form 为初始空对象，取消下面注释
  form.value = {};
};

// 【新增】增加一行
const addRow = () => {
  if (!form.value) form.value = {};
  if (!Array.isArray(form.value[props.itemArrayName])) {
    form.value[props.itemArrayName] = [];
  }
  // 创建一个空行，根据 mappingConfig 生成默认结构
  const newRow: any = {};
  for (const [key, config] of Object.entries(props.mappingConfig)) {
    const fieldConfig = config as ExcelDataMapping;
    newRow[key] = fieldConfig.defaultValue !== undefined ? fieldConfig.defaultValue : "";
  }
  form.value[props.itemArrayName].push(newRow);
};

// 【新增】删除指定行
const deleteRow = (index: number) => {
  if (form.value && Array.isArray(form.value[props.itemArrayName])) {
    form.value[props.itemArrayName].splice(index, 1);
  }
};

// 【新增】移除文件
const removeFile = () => {
  clearAllData();
  ElMessage.success("文件已移除，表格数据已清空");
};
// 监听 BaseForm 发出的 reset 事件
const handleBaseFormReset = () => {
  resetFormData();
};
defineExpose({
  innerFormRef: computed(() => baseFormComponentRef.value?.formRef),
  resetFormData,
  addRow,
  deleteRow,
});
</script>
<template>
  <BaseForm ref="baseFormRef" v-bind="$attrs" class="form-dialog" v-model:form="form" @reset="handleBaseFormReset">
    <template #form-items>
      <el-divider content-position="left" v-if="props.baseTitle">
        <el-icon><Document /></el-icon>
        {{ props.baseTitle }}
      </el-divider>
      <slot name="form-items"></slot>

      <el-divider content-position="left" v-if="props.tableTitle">
        <el-icon><Document /></el-icon>
        {{ props.tableTitle }}
      </el-divider>

      <el-form-item label="上传 Excel" :prop="`${itemArrayName}`">
        <div class="upload-row">
          <el-upload
            ref="uploadRef"
            class="upload-excel"
            :auto-upload="false"
            :limit="1"
            accept=".xlsx,.xls,.csv"
            :on-change="handleFileChange"
            :show-file-list="false"
          >
            <el-button type="primary">
              <el-icon><Upload /></el-icon>
              选择 Excel 文件
            </el-button>
            <span class="upload-tip-side">
              只能上传 xlsx/xls/csv 文件，且不超过 10MB
              <br v-if="props.uploadDesc" />
              <span class="tip-desc" v-if="props.uploadDesc">{{ uploadDesc }}</span>
            </span>
          </el-upload>
        </div>
      </el-form-item>

      <el-table :data="form[itemArrayName]" border style="width: 100%" max-height="400" class="form-item-table">
        <slot name="form-table-columns"></slot>

        <!-- 【新增】固定操作列：删除行 -->
        <el-table-column label="操作" width="80" align="center">
          <template #default="{ $index }">
            <el-button type="danger" link size="small" @click="deleteRow($index)">
              <el-icon><Delete /></el-icon>
            </el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 【新增】表格下方操作栏 -->
      <div class="table-actions">
        <el-button type="primary" link @click="addRow">
          <el-icon><Plus /></el-icon>
          增加一行
        </el-button>
        <el-button type="warning" link @click="resetFormData">
          <el-icon><Delete /></el-icon>
          清空表格
        </el-button>
      </div>
    </template>
  </BaseForm>
</template>
<style>
.form-dialog {
  --el-dialog-width: fit-content !important;
}

.form-dialog :deep(.el-dialog) {
  overflow: hidden;
  border-radius: 8px;
}

.form-dialog :deep(.el-dialog__header) {
  padding: 16px 20px;
  margin-right: 0;
  background-color: var(--el-fill-color-light);
  border-bottom: 1px solid var(--el-border-color-lighter);
}

.form-dialog :deep(.el-dialog__title) {
  font-size: 16px;
  font-weight: 600;
  color: var(--el-text-color-primary);
}

.form-dialog :deep(.el-dialog__headerbtn) {
  top: 16px;
}

.form-dialog :deep(.el-dialog__body) {
  max-height: 70vh;
  padding: 10px 20px;
  overflow-y: auto;
}

.form-item-table {
  height: 40vh;
}

.upload-row {
  display: flex;
  gap: 12px;
  align-items: center;
  width: 100%;
}

.upload-tip-side {
  margin-left: 4px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--el-text-color-secondary);
  white-space: nowrap;
  opacity: 0.8;
}

.tip-desc {
  font-weight: 500;
  color: var(--el-color-primary);
}

.form-dialog .el-dialog__header {
  padding-bottom: 0;
}

.form-dialog .el-dialog__body {
  padding: 0 !important;
}

.el-dialog {
  --el-dialog-margin-top: 5vh !important;
}

.table-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 5px 0;
  margin-top: 10px;
  text-align: right;
}

.ml-2 {
  margin-left: 8px;
}

.el-icon {
  vertical-align: middle;
}

:deep(.el-divider__text) {
  font-weight: 600;
  color: var(--el-text-color-primary);
}

:deep(.el-divider__text .el-icon) {
  margin-right: 6px;
}

:deep(.el-table) {
  font-size: 13px;
}

:deep(.el-table th.el-table__cell) {
  font-weight: 600;
  background-color: var(--el-fill-color-light);
}

:deep(.el-upload) {
  display: inline-flex;
}

:deep(.el-upload__input) {
  display: none;
}
</style>
