<template>
  <div class="compare-view-wrap">
    <compareBasicSection
      sectionTitle="基础信息"
      headerLabel="查看数据表定义模板"
      :objType="objType"
      :objCode="objCode"
      :compareHData1="compareHData1"
      :compareHData2="compareHData2"
      :preVersion="preVersion"
      :curVersion="curVersion"
      :fields="basicFields"
      @reverCallback="$emit('reverCallback')"
    />
    <div
      class="compare-cont compare-detail-section"
      :class="{ 'is-section-fullscreen': detailFullscreen }"
    >
      <div class="compare-detail-header">
        <div class="compare-header-main">
          <div class="title">
            <b>{{ $t1("明细") }}</b>
          </div>
        </div>
        <el-tooltip
          class="item"
          effect="dark"
          :content="$t1('全屏')"
          placement="top"
        >
          <el-link
            class="is-full"
            :underline="false"
            @click="detailFullscreen = !detailFullscreen"
          >
            <i class="iconfont icon-quanping"></i>
          </el-link>
        </el-tooltip>
      </div>
      <div class="compare-detail-grid">
        <span class="version-blue">{{ $t1("版本号") }}：{{ preVersion }}</span>
        <div
          class="grid-height"
          :class="{ 'is-fullscreen-grid': detailFullscreen }"
        >
          <vxe-grid ref="table-pre" v-bind="preGridOption" />
        </div>
      </div>
      <div class="compare-detail-grid">
        <span class="version-green">{{ $t1("版本号") }}：{{ curVersion }}</span>
        <div
          class="grid-height"
          :class="{ 'is-fullscreen-grid': detailFullscreen }"
        >
          <vxe-grid ref="table-cur" v-bind="curGridOption" />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import compareMixin from "./compareMixin";
import compareBasicSection from "./compareBasicSection.vue";
import {
  buildDetailDiffMaps,
  buildRowDiffMaps,
  getDetailRowKey,
  sortDetailRowsByZdEn,
} from "./tableDetailDiff";

const zdTypeMap = {
  Boolean: "布尔",
  Integer: "整数",
  Long: "长整数",
  Decimal: "精度小数",
  Money: "金额",
  Text: "文本",
  TextArea: "长文本",
  DateTime: "日期时间",
  Reference: "关联表(文本)",
  ReferenceLong: "关联表(长整型)",
};

const treeFlagMap = {
  name: "名称",
  wbs: "WBS码",
  parent: "上级ID",
  treePath: "树ID路径",
  treePathName: "树名称路径",
  hasChild: "是否有下级",
  grade: "层级",
};

export default {
  name: "tableModelCompareView",
  mixins: [compareMixin],
  components: {
    compareBasicSection,
  },
  data() {
    return {
      detailFullscreen: false,
      preRows: [],
      curRows: [],
      preGridOption: {},
      curGridOption: {},
      detailDiff: {
        preCellDiff: {},
        curCellDiff: {},
      },
      detailRowDiff: {
        pre: {},
        cur: {},
      },
    };
  },
  computed: {
    basicFields() {
      return [
        { key: "taBm", label: "数据库表名" },
        { key: "taEn", label: "实体名称" },
        { key: "taCh", label: "表描述" },
        {
          key: "taType",
          label: "是否明细",
          formatter: (val) => this.formatBool(val),
        },
        { key: "sszstEn", label: "所属主实体" },
        {
          key: "taRule",
          label: "是否树结构",
          formatter: (val) => this.formatBool(val),
        },
        {
          key: "dataRange",
          label: "数据范围",
          formatter: (val) => this.formatDataRange(val),
        },
        { key: "menuKindName", label: "表单分类" },
        {
          key: "szTaMbTagDTOs",
          label: "项目标签",
          formatter: (val) => this.formatTags(val),
        },
        {
          key: "enabled",
          label: "是否启用",
          formatter: (val) => this.formatBool(val, "启用", "禁用"),
        },
        { key: "serviceName", label: "服务名" },
        { key: "sid", label: "唯一标识" },
        ...this.auditFields(),
      ];
    },
  },
  mounted() {
    this.initDetailGrids();
  },
  watch: {
    detailFullscreen() {
      this.updateDetailGridLayout();
    },
  },
  methods: {
    formatYesNo(cellValue) {
      return this.$t1(cellValue ? "是" : "否");
    },
    formatZdType(cellValue) {
      return this.$t1(zdTypeMap[cellValue] || cellValue || "");
    },
    formatTreeFlag(cellValue) {
      return this.$t1(treeFlagMap[cellValue] || cellValue || "");
    },
    getDetailColumns(side) {
      const rowDiffMap = this.detailRowDiff[side] || {};
      return [
        {
          title: "",
          field: "_diffFlag",
          width: 32,
          fixed: "left",
          align: "center",
          slots: {
            default: ({ row, rowIndex }) => {
              const rowKey = getDetailRowKey(row, rowIndex);
              if (!rowDiffMap[rowKey]) return [null];
              return [
                <el-tooltip
                  enterable={false}
                  effect="dark"
                  content={this.$t1("存在差异项")}
                  placement="top"
                >
                  <i class="el-icon-warning compare-row-diff-icon" />
                </el-tooltip>,
              ];
            },
          },
        },
        {
          title: this.$t1("实体字段名称"),
          field: "zdEn",
          width: 150,
          fixed: "left",
        },
        {
          title: this.$t1("数据库表字段名"),
          field: "taZdMc",
          width: 150,
          fixed: "left",
        },
        {
          title: this.$t1("字段描述"),
          field: "zdCh",
          width: 150,
        },
        {
          title: this.$t1("字段类型"),
          field: "zdType",
          width: 150,
          formatter: ({ cellValue }) => this.formatZdType(cellValue),
        },
        {
          title: this.$t1("字段长度"),
          field: "zdLength",
          width: 150,
        },
        {
          title: this.$t1("树标识"),
          field: "treeFlag",
          width: 150,
          formatter: ({ cellValue }) => this.formatTreeFlag(cellValue),
        },
        {
          title: this.$t1("关联字段"),
          field: "referenceZd",
          width: 250,
        },
        {
          title: this.$t1("来源关联字段"),
          field: "relationZd",
          width: 250,
        },
        {
          title: this.$t1("关联表对应服务名"),
          field: "refServiceName",
          width: 200,
        },
        {
          title: this.$t1("数据值对应表的字段"),
          field: "toTaBmZd",
          width: 250,
        },
        {
          title: this.$t1("字段类型对应的默认值"),
          field: "zdTypeValues",
          width: 200,
        },
        {
          title: this.$t1("是否必填项"),
          field: "required",
          width: 140,
          formatter: ({ cellValue }) => this.formatYesNo(cellValue),
        },
        {
          title: this.$t1("是否启用"),
          field: "enabled",
          width: 120,
          formatter: ({ cellValue }) => this.formatYesNo(cellValue),
        },
        {
          title: this.$t1("是否自动生成编码"),
          field: "generateCode",
          width: 180,
          formatter: ({ cellValue }) => this.formatYesNo(cellValue),
        },
        {
          title: this.$t1("数据库字段加密"),
          field: "atened",
          width: 180,
          formatter: ({ cellValue }) => this.formatYesNo(cellValue),
        },
        {
          title: this.$t1("是否更新忽略字段"),
          field: "updateIgnore",
          width: 180,
          formatter: ({ cellValue }) => this.formatYesNo(cellValue),
        },
        {
          title: this.$t1("编码类型"),
          field: "codeType",
          width: 150,
        },
        {
          title: this.$t1("序号"),
          field: "orders",
          width: 150,
        },
      ];
    },
    getGridSizeConfig() {
      if (this.detailFullscreen) {
        return {
          height: "100%",
          maxHeight: null,
        };
      }
      return {
        height: "auto",
        maxHeight: 320,
      };
    },
    initDetailGrids() {
      const rawPreRows = this.compareHData1?.szTaZdMbDTOs || [];
      const rawCurRows = this.compareHData2?.szTaZdMbDTOs || [];
      this.detailDiff = buildDetailDiffMaps(rawPreRows, rawCurRows);
      const { preRowDiff, curRowDiff } = buildRowDiffMaps(
        this.detailDiff.preCellDiff,
        this.detailDiff.curCellDiff
      );
      this.detailRowDiff = { pre: preRowDiff, cur: curRowDiff };
      this.preRows = sortDetailRowsByZdEn(rawPreRows);
      this.curRows = sortDetailRowsByZdEn(rawCurRows);

      const baseConfig = {
        border: true,
        resizable: true,
        showOverflow: true,
        scrollX: { enabled: true },
        ...this.getGridSizeConfig(),
      };
      this.preGridOption = {
        ...baseConfig,
        columns: this.getDetailColumns("pre"),
        data: this.preRows,
        cellClassName: (params) => this.getPreCellClassName(params),
      };
      this.curGridOption = {
        ...baseConfig,
        columns: this.getDetailColumns("cur"),
        data: this.curRows,
        cellClassName: (params) => this.getCurCellClassName(params),
      };
    },
    updateDetailGridLayout() {
      const sizeConfig = this.getGridSizeConfig();
      Object.assign(this.preGridOption, sizeConfig);
      Object.assign(this.curGridOption, sizeConfig);
      this.$nextTick(() => {
        this.refreshDetailGrids();
      });
    },
    refreshDetailGrids() {
      [
        { ref: "table-pre", rows: this.preRows },
        { ref: "table-cur", rows: this.curRows },
      ].forEach(({ ref, rows }) => {
        const grid = this.$refs[ref];
        if (!grid) return;
        if (typeof grid.loadData === "function") {
          grid.loadData(rows);
        }
        if (typeof grid.recalculate === "function") {
          grid.recalculate(true);
        }
      });
    },
    getPreCellClassName({ row, column, rowIndex }) {
      return this.getDetailCellClassName("pre", row, column, rowIndex);
    },
    getCurCellClassName({ row, column, rowIndex }) {
      return this.getDetailCellClassName("cur", row, column, rowIndex);
    },
    getDetailCellClassName(side, row, column, rowIndex) {
      const field = column.field;
      if (!field || !row) return "";
      const diffKey = `${getDetailRowKey(row, rowIndex)}__${field}`;
      const diffMap =
        side === "pre"
          ? this.detailDiff.preCellDiff
          : this.detailDiff.curCellDiff;
      const diffType = diffMap[diffKey];
      if (!diffType) return "";
      if (diffType === "add") {
        return "compare-diff-new";
      }
      return "compare-diff-old";
    },
  },
};
</script>

<style scoped lang="scss">
@import "./compareContMixin.scss";

.compare-detail-section {
  @include compare-cont-shell;
  @include compare-cont-full-link;
  @include compare-version-label;

  .compare-detail-grid {
    margin-top: 8px;

    .grid-height {
      height: 320px !important;
    }

    .version-blue,
    .version-green {
      margin-bottom: 8px;
    }
  }

  .compare-detail-header {
    position: relative;
    min-height: 28px;
    margin-bottom: 4px;
    padding-right: 24px;
  }

  .compare-header-main {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0 16px;
  }

  .title {
    margin-bottom: 0 !important;
  }

  .compare-diff-legend {
    display: inline-flex;
    align-items: center;
    font-size: 12px;

    .legend-item {
      display: inline-block;
      margin-right: 12px;
      padding: 2px 8px;
      border-radius: 2px;

      &.legend-old {
        background: rgba(245, 108, 108, 0.2);
        color: #f56c6c;
      }

      &.legend-new {
        background: rgba(103, 194, 58, 0.2);
        color: #67c23a;
      }
    }
  }

  ::v-deep .compare-diff-old {
    background-color: rgba(245, 108, 108, 0.2) !important;
    color: #f56c6c;
  }

  ::v-deep .compare-diff-new {
    background-color: rgba(103, 194, 58, 0.2) !important;
    color: #67c23a;
  }

  ::v-deep .compare-row-diff-icon {
    color: #e6a23c;
    font-size: 14px;
    cursor: default;
  }

  &.is-section-fullscreen {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 9999;
    display: flex;
    flex-direction: column;
    margin: 0;
    overflow: hidden;
    padding: 12px 16px 16px;
    background: #fff;

    .compare-detail-header {
      flex-shrink: 0;
    }

    .compare-detail-grid {
      flex: 1;
      min-height: 0;
      display: flex;
      flex-direction: column;

      .grid-height.is-fullscreen-grid {
        flex: 1;
        min-height: 0;
        height: auto !important;
      }
    }
  }
}

.compare-detail-grid + .compare-detail-grid {
  margin-top: 16px;
}

.compare-detail-section.is-section-fullscreen {
  .compare-detail-grid + .compare-detail-grid {
    margin-top: 12px;
  }
}
</style>
