<template>
  <div class="mixed-table-wrap">
    <!-- 调试用：可删除 -->
    <!-- {{ tableDataRef }}tableData -->
    <el-table
      :data="tableDataRef"
      style="width: 100%"
      border
      :cell-style="tableCellStyle"
      row-key="serialNumber"
      v-if="validConfig"
    >
      <!-- 序号列：保留原逻辑 -->
      <el-table-column
        prop="serialNumber"
        label="序号"
        width="80"
        align="center"
      />
      <!-- 指标项列（层级缩进）：保留原逻辑 -->
      <el-table-column
        prop="indicatorName"
        label="名称"
        align="left"
        width="260"
      >
        <template #default="{ row }">
          <div style="text-align: left">{{ row.indicatorName }}</div>
        </template>
      </el-table-column>
      <!-- 合计列：文本行隐藏合计值，不显示0.00 → 从内部数据取值 -->
      <el-table-column label="合计" width="140" align="right">
        <template #default="{ row }">
          <span v-if="!row.noTotal">
            {{ row.total ? Number(row.total).toFixed(2) : "0.00" }}万元
          </span>
          <span v-else>&nbsp;</span>
        </template>
      </el-table-column>
      <!-- 动态时间列：改用【处理后的有效时间列表】，保留原条件渲染逻辑 -->
      <el-table-column
        v-for="time in validDynamicTimeList"
        :key="`time-col-${time}`"
        :label="time"
        width="140"
        align="center"
      >
        <template #default="{ row }">
          <!-- 1. 文本行：多行文本输入框，支持字符串 → 绑定内部数据 -->
          <el-input
            v-if="row.isTextRow"
            v-model="row[time]"
            type="textarea"
            :rows="2"
            :disabled="isPreview"
            placeholder="请输入说明"
            style="width: 100%"
            @input="() => handleTextInput(row)"
          />
          <!-- 2. 数字行：金额输入框（0+、2位小数）→ 绑定内部数据 -->
          <el-input-number
            v-else
            v-model="row[time]"
            :min="0"
            :precision="2"
            controls-position="right"
            :disabled="isPreview"
            placeholder="请输入金额"
            style="width: 100%"
            @change="() => handleFinancialChange(row)"
          />
        </template>
      </el-table-column>
    </el-table>
    <!-- 配置不合法提示：保留原逻辑 -->
    <div v-else style="text-align: center; padding: 20px; color: #909399">
      请传入合法的表格配置（包含indicatorList、dynamicTimeList）
    </div>
  </div>
</template>

<script setup>
import { ref, computed, watch, nextTick, defineProps, defineEmits } from "vue";

// 1. 重构Props/Emit：对齐参考组件，改用defineProps+defineEmits，隔离v-model循环
// 替代原defineModel，避免对象式v-model的循环更新问题，和参考组件统一
const props = defineProps({
  // 核心配置对象：包含indicatorList/dynamicTimeList/tableData
  modelValue: {
    type: Object,
    default: () => ({ indicatorList: [], dynamicTimeList: [], tableData: [] }),
    validator: (val) =>
      val &&
      Array.isArray(val.indicatorList) &&
      Array.isArray(val.dynamicTimeList),
  },
  // 预览模式：保留原配置
  isPreview: {
    type: Boolean,
    default: false,
  },
});

// 定义发射事件：双向绑定+业务事件，和参考组件一致
const emit = defineEmits([
  "update:modelValue", // v-model双向绑定更新
  "handleTableChange", // 自定义业务变化事件（可让父组件监听）
]);

// 2. 核心：创建组件内部响应式数据，完全隔离外部Props → 参考组件核心设计
// 所有数据操作先改内部，再统一发射，避免直接修改Props导致的循环更新
const tableDataRef = ref([]);

// 3. 处理动态时间列表：对齐参考组件，做【去重/去空/trim/兜底】→ 关键健壮性改造
// 解决原组件直接用props中可能的无效时间列（空值/空格/重复）问题
const validDynamicTimeList = computed(() => {
  const rawTimeList = props.modelValue.dynamicTimeList || [];
  if (!Array.isArray(rawTimeList) || rawTimeList.length === 0) {
    // 兜底默认值：保证表格至少有列渲染，不会空白
    return ["2025", "2026", "2027"];
  }
  return [...new Set(rawTimeList)]
    .map((time) => (typeof time === "string" ? time.trim() : "")) // 去除隐形空白
    .filter((time) => !!time); // 过滤空值
});

// 4. 配置合法性校验：基于【处理后的有效时间列表】重构，更严谨
const validConfig = computed(() => {
  const { indicatorList } = props.modelValue;
  return (
    Array.isArray(indicatorList) &&
    indicatorList.length > 0 &&
    validDynamicTimeList.value.length > 0
  );
});

// 5. 工具方法：初始化行的时间字段 → 对齐参考组件initRowTimeField
// 针对【文本行/数字行】做差异化初始化，避免类型混乱
const initRowTimeField = (row) => {
  if (!row || typeof row !== "object") return;
  validDynamicTimeList.value.forEach((time) => {
    if (row.isTextRow) {
      // 文本行：无值则置空字符串，保留原有字符串
      row[time] =
        row[time] === undefined || row[time] === null ? "" : String(row[time]);
    } else {
      // 数字行：无值/非数字则置0，确保数字类型
      row[time] =
        row[time] === undefined ||
        row[time] === null ||
        isNaN(Number(row[time]))
          ? 0
          : Number(row[time]);
    }
  });
};

// 6. 工具方法：计算单行合计 → 对齐参考组件calcRowTotal
// 仅数字行生效，自动过滤文本行/非数字，解决浮点精度问题
const calculateRowTotal = (row) => {
  if (!row || typeof row !== "object" || row.noTotal || row.isTextRow) return 0;
  const total = validDynamicTimeList.value.reduce((sum, time) => {
    return sum + (Number(row[time]) || 0);
  }, 0);
  return Number(total.toFixed(2)); // 保留2位小数，避免0.1+0.2=0.30000000000000004
};

// 7. 核心工具方法：深拷贝+数据处理 → 对齐参考组件handleTableData
// 强制保留所有原有字段，仅【初始化时间字段/计算合计】，避免字段丢失
const handleTableData = (sourceIndicatorList, sourceTableData) => {
  if (!validConfig.value) return [];
  const newData = [];
  sourceIndicatorList.forEach((item, index) => {
    const { name, isTextRow = false, noTotal = false } = item;
    // 深拷贝源数据行：保留所有原有字段（serialNumber/level/indicatorName等）
    const originRow =
      sourceTableData.find((row) => row.indicatorName === name) || {};
    const rowData = JSON.parse(
      JSON.stringify({
        serialNumber: index + 1,
        level: 0,
        indicatorName: name,
        isTextRow,
        noTotal,
        total: 0,
        ...originRow, // 源数据行覆盖默认值，保留原有配置
      }),
    );
    // 初始化时间字段：差异化处理文本/数字行
    initRowTimeField(rowData);
    // 计算合计：仅数字行/需要合计的行生效
    rowData.total = calculateRowTotal(rowData);
    newData.push(rowData);
  });
  return newData;
};

// 8. 工具方法：数据变化后统一发射 → 对齐参考组件emitDataChange
// 深拷贝后发射，保留所有字段，避免父组件修改影响内部数据，统一发射逻辑
const emitDataChange = (newInnerData) => {
  if (props.isPreview) return; // 预览模式不发射
  // 深拷贝内部数据，避免引用传递
  const emitData = JSON.parse(JSON.stringify(newInnerData));
  // 构造父组件需要的完整配置对象，保持原数据结构
  const newModelValue = {
    ...props.modelValue,
    tableData: emitData,
  };
  // 统一发射：双向绑定更新 + 业务事件
  emit("update:modelValue", newModelValue);
  emit("handleTableChange", newModelValue);
};

// 9. 监听Props变化：同步到内部数据 → 对齐参考组件的watch逻辑
// 仅同步，不发射；nextTick确保有效时间列表先处理完成
watch(
  () => props.modelValue,
  async (newVal) => {
    if (!validConfig.value) return;
    await nextTick(); // 等待有效时间列表计算完成
    const newTableData = handleTableData(
      newVal.indicatorList,
      newVal.tableData,
    );
    tableDataRef.value = newTableData; // 只更新内部数据，不直接修改Props
  },
  { deep: true, immediate: true }, // 深度监听+立即执行，组件挂载即初始化
);

// 监听有效时间列表变化：更新内部数据后统一发射 → 对齐参考组件
watch(
  () => validDynamicTimeList.value,
  () => {
    if (!validConfig.value || tableDataRef.value.length === 0) return;
    // 重新初始化时间字段+计算合计
    tableDataRef.value.forEach((row) => {
      initRowTimeField(row);
      row.total = calculateRowTotal(row);
    });
    emitDataChange(tableDataRef.value);
  },
  { deep: true, immediate: true },
);

// 10. 数字行输入回调 → 重构，仅更新内部数据，再统一发射
const handleFinancialChange = (currentRow) => {
  if (props.isPreview || !currentRow || currentRow.noTotal) return;
  currentRow.total = calculateRowTotal(currentRow); // 仅更新内部数据的合计
  emitDataChange(tableDataRef.value); // 统一发射所有数据
};

// 11. 文本行输入回调 → 重构，同步内部数据后统一发射（可扩展）
const handleTextInput = (currentRow) => {
  if (props.isPreview || !currentRow) return;
  emitDataChange(tableDataRef.value); // 文本输入仅同步，统一发射
};

// 12. 表格单元格样式 → 保留原逻辑，微调健壮性
const tableCellStyle = ({ row }) => {
  // 合计行高亮
  if (row?.isTotal) {
    return { background: "#f5f7fa", fontWeight: "bold", textAlign: "right" };
  }
  // 所有行右对齐，文本行输入框单独左对齐（样式层处理）
  return { textAlign: "right" };
};
</script>

<style scoped lang="scss">
// 外层容器：适配滚动，和参考组件样式统一
.mixed-table-wrap {
  width: 100%;
  box-sizing: border-box;
  overflow-x: auto;
}

// 数字输入框样式：对齐参考组件，填满单元格
:deep(.el-input-number) {
  width: 100%;
}
:deep(.el-input-number__input) {
  text-align: right;
  padding-right: 25px;
  width: 100% !important;
}

// 文本输入框样式：适配表格，和数字框高度对齐，保留原逻辑
:deep(.el-input__textarea) {
  resize: none; // 禁止手动拉伸
  text-align: left !important; // 文本左对齐，符合阅读习惯
  min-height: 40px !important; // 固定最小高度，和数字框对齐
}

// 表格列头样式：统一对齐，保留原逻辑
:deep(.el-table__header-cell) {
  text-align: right !important;
  &.el-table__header-cell--align-center {
    text-align: center !important;
  }
}

// 表格单元格：优化内边距，避免输入框溢出，保留原逻辑
:deep(.el-table__cell) {
  padding: 4px 8px !important;
  height: 48px !important; // 统一行高，和参考组件一致
  vertical-align: middle !important;
}

// 表格行高：统一设置，避免行高混乱
:deep(.el-table__row) {
  height: 48px !important;
}
</style>
