<template>
  <div class="project-analysis-abnormal-tab">
    <template v-if="detailGroups.length">
      <section
        v-for="(group, groupIndex) in detailGroups"
        :key="`${group.groupCode || group.groupType || groupIndex}-group`"
        class="abnormal-card"
      >
        <div class="abnormal-card__header">
          <div class="abnormal-card__title">{{ group.groupName || "异常明细" }}</div>
          <el-button
            v-if="shouldShowExportButton(group)"
            size="mini"
            type="primary"
            plain
            icon="el-icon-download"
            @click="handleExportAbnormalDetail"
          >
            导出
          </el-button>
        </div>

        <div class="abnormal-card__content">
          <el-table
            v-if='group.groupType === "BANK_STATEMENT"'
            :data="getStatementPageRecords(group)"
            class="abnormal-table"
          >
            <el-table-column prop="trxDate" label="交易时间" min-width="160" />
            <el-table-column label="本方信息" min-width="220">
              <template slot-scope="scope">
                <div class="multi-line-cell">
                  <div class="primary-text">{{ scope.row.leAccountName || "-" }}</div>
                  <div class="secondary-text">{{ scope.row.leAccountNo || "-" }}</div>
                </div>
              </template>
            </el-table-column>
            <el-table-column label="对方信息" min-width="220">
              <template slot-scope="scope">
                <div class="multi-line-cell">
                  <div class="primary-text">{{ scope.row.customerAccountName || "-" }}</div>
                  <div class="secondary-text">{{ scope.row.customerAccountNo || "-" }}</div>
                </div>
              </template>
            </el-table-column>
            <el-table-column label="摘要/交易类型" min-width="220">
              <template slot-scope="scope">
                <div class="multi-line-cell">
                  <div class="primary-text">{{ scope.row.userMemo || "-" }}</div>
                  <div class="secondary-text">{{ scope.row.cashType || "-" }}</div>
                </div>
              </template>
            </el-table-column>
            <el-table-column label="异常标签" min-width="220">
              <template slot-scope="scope">
                <div v-if="scope.row.hitTags && scope.row.hitTags.length" class="tag-list">
                  <span
                    v-for="(tag, index) in scope.row.hitTags"
                    :key="`${scope.row.bankStatementId || index}-tag-${index}`"
                    class="tag-with-action"
                  >
                    <el-tag size="mini" effect="plain">
                      {{ tag.ruleName }}
                    </el-tag>
                    <el-button
                      v-if="canOperate"
                      class="exclude-risk-btn"
                      type="text"
                      size="mini"
                      :loading="isExcluding(buildStatementExcludeKey(scope.row, tag))"
                      :disabled="!tag.ruleCode"
                      @click="handleExcludeStatementRisk(scope.row, tag)"
                    >
                      排除可疑
                    </el-button>
                  </span>
                </div>
                <span v-else class="summary-row__label">-</span>
              </template>
            </el-table-column>
            <el-table-column prop="displayAmount" label="交易金额" min-width="140" />
          </el-table>
          <div
            v-if='group.groupType === "BANK_STATEMENT" && getStatementTotal(group) > statementPageSize'
            class="abnormal-pagination"
          >
            <el-pagination
              background
              layout="prev, pager, next"
              :current-page="getStatementPage(group)"
              :page-size="statementPageSize"
              :total="getStatementTotal(group)"
              @current-change="handleStatementPageChange(group, $event)"
            />
          </div>

          <div v-else-if='group.groupType === "OBJECT"' class="object-card-grid">
            <article
              v-for="(item, index) in group.records || []"
              :key="`${resolveGroupKey(group, groupIndex)}-${item.title || 'object'}-${index}`"
              class="object-card"
            >
              <div class="object-card__header">
                <div>
                  <div class="object-card__title">{{ item.title || "-" }}</div>
                  <div class="object-card__subtitle">{{ item.subtitle || "-" }}</div>
                </div>
                <div class="object-card__actions">
                  <el-button
                    v-if="canOperate"
                    class="evidence-corner-btn"
                    size="mini"
                    plain
                    :loading="isExcluding(buildObjectExcludeKey(item))"
                    :disabled="!item.ruleCode"
                    @click="handleExcludeObjectRisk(item)"
                  >
                    排除可疑
                  </el-button>
                  <el-button
                    class="evidence-corner-btn"
                    size="mini"
                    plain
                    :disabled="!buildModelEvidenceFingerprint(resolvePersonIdCard(), item.modelCode)"
                    @click="handleAddModelEvidence(item, group)"
                  >
                    加入证据库
                  </el-button>
                </div>
              </div>
              <div v-if="item.riskTags && item.riskTags.length" class="tag-list">
                <el-tag
                  v-for="(tag, tagIndex) in item.riskTags"
                  :key="`${resolveGroupKey(group, groupIndex)}-${item.title || index}-risk-${tagIndex}`"
                  size="mini"
                  effect="plain"
                >
                  {{ tag }}
                </el-tag>
              </div>
              <div class="object-card__snapshot">
                <div class="object-card__snapshot-label">异常原因快照</div>
                <p class="object-card__snapshot-value">{{ item.reasonDetail || "-" }}</p>
              </div>
              <p class="object-card__summary">{{ item.summary || "-" }}</p>
              <div
                v-for="(field, fieldIndex) in item.extraFields || []"
                :key="`${resolveGroupKey(group, groupIndex)}-${item.title || index}-field-${fieldIndex}`"
                class="summary-row"
              >
                <span class="summary-row__label">{{ field.label }}</span>
                <span class="summary-row__value">{{ field.value }}</span>
              </div>
            </article>
          </div>
        </div>
      </section>
    </template>
    <el-empty v-else :image-size="80" description="暂无异常明细" />
  </div>
</template>

<script>
import { saveAs } from "file-saver";
import { excludeOverviewRisk } from "@/api/ccdi/projectOverview";
import { buildModelEvidenceFingerprint, MODEL_EVIDENCE_FINGERPRINT_RULE } from "@/utils/ccdiEvidence";

export default {
  name: "ProjectAnalysisAbnormalTab",
  props: {
    detailData: {
      type: Object,
      default: () => ({
        groups: [],
      }),
    },
    person: {
      type: Object,
      default: () => ({}),
    },
    projectId: {
      type: [String, Number],
      default: null,
    },
    canOperate: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {
      statementPageSize: 5,
      statementPageMap: {},
      excludingKey: "",
    };
  },
  watch: {
    detailGroups: {
      immediate: true,
      handler(groups) {
        const nextPageMap = {};
        groups
          .filter((group) => group && group.groupType === "BANK_STATEMENT")
          .forEach((group, index) => {
            const groupKey = this.resolveGroupKey(group, index);
            nextPageMap[groupKey] = 1;
          });
        this.statementPageMap = nextPageMap;
      },
    },
  },
  computed: {
    detailGroups() {
      return Array.isArray(this.detailData && this.detailData.groups) ? this.detailData.groups : [];
    },
  },
  methods: {
    buildModelEvidenceFingerprint,
    resolveGroupKey(group, index = 0) {
      return group.groupCode || group.groupName || `BANK_STATEMENT_${index}`;
    },
    getStatementPage(group) {
      const groupKey = this.resolveGroupKey(group);
      return this.statementPageMap[groupKey] || 1;
    },
    getStatementTotal(group) {
      return Array.isArray(group && group.records) ? group.records.length : 0;
    },
    getStatementPageRecords(group) {
      const records = Array.isArray(group && group.records) ? group.records : [];
      const currentPage = this.getStatementPage(group);
      const startIndex = (currentPage - 1) * this.statementPageSize;
      return records.slice(startIndex, startIndex + this.statementPageSize);
    },
    handleStatementPageChange(group, page) {
      const groupKey = this.resolveGroupKey(group);
      this.$set(this.statementPageMap, groupKey, page);
    },
    buildStatementExcludeKey(row, tag) {
      return `STATEMENT:${row && row.bankStatementId}:${tag && tag.ruleCode}`;
    },
    buildObjectExcludeKey(item) {
      return `OBJECT:${this.resolvePersonIdCard()}:${item && item.ruleCode}`;
    },
    isExcluding(key) {
      return Boolean(key && this.excludingKey === key);
    },
    async handleExcludeStatementRisk(row, tag) {
      if (!this.canOperate) {
        this.$message.warning("当前项目仅可查看，不能排除可疑");
        return;
      }
      if (!this.projectId || !row || !row.bankStatementId || !tag || !tag.ruleCode) {
        this.$message.warning("缺少流水或规则信息，暂不能排除可疑");
        return;
      }
      const ruleName = tag.ruleName || "当前规则";
      await this.submitRiskExclusion({
        key: this.buildStatementExcludeKey(row, tag),
        message: `确认将当前流水的“${ruleName}”标记为排除可疑吗？该操作只影响当前流水上的这一个规则标签。`,
        payload: {
          projectId: this.projectId,
          exclusionType: "STATEMENT",
          ruleCode: tag.ruleCode,
          bankStatementId: row.bankStatementId,
          staffIdCard: this.resolvePersonIdCard(),
        },
      });
    },
    async handleExcludeObjectRisk(item) {
      if (!this.canOperate) {
        this.$message.warning("当前项目仅可查看，不能排除可疑");
        return;
      }
      const staffIdCard = this.resolvePersonIdCard();
      if (!this.projectId || !staffIdCard || !item || !item.ruleCode) {
        this.$message.warning("缺少人员或规则信息，暂不能排除可疑");
        return;
      }
      const ruleName = item.summary || item.title || "当前规则";
      await this.submitRiskExclusion({
        key: this.buildObjectExcludeKey(item),
        message: `确认将“${this.resolvePersonName()}”的“${ruleName}”标记为排除可疑吗？该操作只影响当前人员的这一个规则预警。`,
        payload: {
          projectId: this.projectId,
          exclusionType: "OBJECT",
          ruleCode: item.ruleCode,
          staffIdCard,
        },
      });
    },
    async submitRiskExclusion({ key, message, payload }) {
      if (this.excludingKey) {
        return;
      }
      try {
        const { value } = await this.$prompt(message, "排除可疑", {
          confirmButtonText: "确认排除",
          cancelButtonText: "取消",
          inputType: "textarea",
          inputPlaceholder: "请输入排除原因",
          inputValidator: (value) => {
            if (!value || !value.trim()) {
              return "排除原因不能为空";
            }
            if (value.trim().length > 1000) {
              return "排除原因不能超过1000个字符";
            }
            return true;
          },
        });
        this.excludingKey = key;
        await excludeOverviewRisk({
          ...payload,
          excludeReason: value.trim(),
        });
        this.$message.success("排除成功");
        this.$emit("risk-excluded", payload);
      } catch (error) {
        if (error !== "cancel" && error !== "close") {
          const message = error && error.msg ? error.msg : "排除失败，请稍后重试";
          this.$message.error(message);
        }
      } finally {
        this.excludingKey = "";
      }
    },
    shouldShowExportButton(group) {
      return group && group.groupType === "BANK_STATEMENT";
    },
    handleExportAbnormalDetail() {
      const rows = this.buildAbnormalExportRows();
      if (!rows.length) {
        this.$message.warning("暂无可导出的异常流水明细");
        return;
      }
      const headers = [
        "分组",
        "交易时间",
        "本方名称",
        "本方账号",
        "对手方名称",
        "对手方账号",
        "摘要",
        "交易类型",
        "异常标签",
        "交易金额",
      ];
      const csvContent = [headers, ...rows]
        .map((row) => row.map((cell) => this.escapeCsvCell(cell)).join(","))
        .join("\r\n");
      const blob = new Blob([`\uFEFF${csvContent}`], { type: "text/csv;charset=utf-8;" });
      const fileName = `${this.sanitizeFileName(`异常流水明细_${this.resolvePersonName()}`)}.csv`;
      saveAs(blob, fileName);
    },
    buildAbnormalExportRows() {
      const rows = [];
      this.detailGroups.forEach((group) => {
        if (!group || group.groupType !== "BANK_STATEMENT") {
          return;
        }
        const records = Array.isArray(group && group.records) ? group.records : [];
        records.forEach((record) => {
          rows.push([
            group.groupName || "",
            record.trxDate,
            record.leAccountName,
            record.leAccountNo,
            record.customerAccountName,
            record.customerAccountNo,
            record.userMemo,
            record.cashType,
            this.formatRiskTags(record.hitTags),
            record.displayAmount,
          ]);
        });
      });
      return rows;
    },
    formatRiskTags(tags) {
      if (!Array.isArray(tags)) {
        return "";
      }
      return tags
        .map((tag) => {
          if (tag && typeof tag === "object") {
            return tag.ruleName || tag.name || tag.label || tag.title || "";
          }
          return tag;
        })
        .filter((tag) => tag !== null && tag !== undefined && `${tag}`.trim() !== "")
        .join("、");
    },
    escapeCsvCell(value) {
      const text = value === null || value === undefined ? "" : `${value}`;
      return `"${text.replace(/"/g, '""')}"`;
    },
    sanitizeFileName(value) {
      return `${value || "异常明细"}`.replace(/[\\/:*?"<>|]/g, "_");
    },
    resolvePersonName() {
      return (this.person && (this.person.name || this.person.staffName || this.person.personName)) || "项目分析";
    },
    handleAddModelEvidence(item, group) {
      const safeItem = item || {};
      const safeGroup = group || {};
      const relatedPersonName = this.resolveRelatedPersonName(safeItem);
      const personIdCard = this.resolvePersonIdCard();
      const sourceRecordId = buildModelEvidenceFingerprint(personIdCard, safeItem.modelCode);
      if (!sourceRecordId) {
        this.$message.warning("缺少人员身份证或模型编码，暂不能加入证据库");
        return;
      }
      const riskTags = Array.isArray(safeItem.riskTags) ? safeItem.riskTags.join("、") : "";
      const reason = safeItem.reasonDetail || safeItem.summary || "-";
      const payload = {
        evidenceType: "MODEL",
        relatedPersonName,
        relatedPersonId: personIdCard,
        evidenceTitle: `${relatedPersonName} / ${safeItem.title || safeGroup.groupName || "模型异常"}`,
        evidenceSummary: `${safeItem.title || safeGroup.groupName || "模型异常"}：${reason}`,
        sourceType: "MODEL_DETAIL",
        sourceRecordId,
        sourcePage: "模型详情",
        snapshotJson: JSON.stringify({
          group: safeGroup,
          item: safeItem,
          person: this.person,
          riskTags,
          evidenceFingerprint: sourceRecordId,
          evidenceFingerprintRule: MODEL_EVIDENCE_FINGERPRINT_RULE,
        }),
      };
      this.$emit("evidence-confirm", payload);
      this.$root.$emit("ccdi-evidence-confirm", payload);
    },
    resolvePersonIdCard() {
      return (this.person && (this.person.idNo || this.person.staffIdCard)) || "";
    },
    resolveRelatedPersonName(item) {
      if (this.person && (this.person.name || this.person.staffName)) {
        return this.person.name || this.person.staffName;
      }
      return item.title || "关联人员";
    },
  },
};
</script>

<style lang="scss" scoped>
.project-analysis-abnormal-tab {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.abnormal-card {
  border: 1px solid #d9e1ed;
  border-radius: 6px;
  background: #fff;
  overflow: hidden;
}

.abnormal-card__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 0;
  padding: 22px 30px;
  border-bottom: 1px solid #e3eaf3;
}

.abnormal-card__title {
  font-size: 18px;
  font-weight: 700;
  color: #0f172a;
}

.abnormal-card__content {
  display: grid;
  gap: 0;
  background: #ffffff;
}

.abnormal-card__subtitle {
  font-size: 12px;
  color: #64748b;
}

.abnormal-table {
  border: 1px solid #e2e8f0;
  border-radius: 6px;
  overflow: hidden;
}

.abnormal-pagination {
  display: flex;
  justify-content: flex-end;
  padding: 18px 24px 20px;
  border-top: 1px solid #e8eef6;
}

.multi-line-cell {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.primary-text {
  color: #0f172a;
}

.secondary-text,
.summary-row__label {
  font-size: 12px;
  color: #64748b;
}

.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.tag-with-action {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.exclude-risk-btn {
  padding: 0;
  font-size: 12px;
}

.object-card-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
}

.object-card {
  padding: 16px;
  border: 1px solid #d9e1ed;
  background: #ffffff;
  border-radius: 6px;
}

.object-card__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}

.object-card__actions {
  display: inline-flex;
  flex: 0 0 auto;
  gap: 6px;
}

.object-card__title {
  font-size: 15px;
  font-weight: 600;
  color: #0f172a;
}

.evidence-corner-btn {
  flex: 0 0 auto;
  padding: 4px 9px;
  font-size: 12px;
  color: #5b7fb8;
  border-color: #d6e4f7;
  background: #f8fbff;

  &:hover {
    color: #2474e8;
    border-color: #9fc3ff;
    background: #edf5ff;
  }
}

.object-card__subtitle {
  margin-top: 6px;
  font-size: 12px;
  color: #64748b;
}

.object-card__summary {
  margin: 12px 0;
  font-size: 13px;
  line-height: 1.7;
  color: #1e293b;
}

.object-card__snapshot {
  margin-top: 12px;
  padding: 12px;
  border: 1px solid #dbeafe;
  border-left: 3px solid #245b8f;
  border-radius: 6px;
  background: #f4f8fd;
}

.object-card__snapshot-label {
  font-size: 12px;
  color: #475569;
}

.object-card__snapshot-value {
  margin: 8px 0 0;
  font-size: 13px;
  line-height: 1.7;
  color: #1e293b;
}

.summary-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 4px;
  margin-top: 8px;
}

.summary-row__value {
  font-size: 13px;
  color: #1e293b;
  text-align: right;
}

.abnormal-table ::v-deep(.el-table__header-wrapper th) {
  height: 58px;
  padding: 0 22px;
  border-bottom: 1px solid #d9e1ed;
  background: #f3f6fa;
  color: #5f7592;
  font-size: 16px;
  font-weight: 700;
}

.abnormal-table ::v-deep(.el-table__body-wrapper td) {
  padding: 22px;
  border-bottom: 1px solid #e6edf5;
}

.abnormal-table ::v-deep(.cell) {
  padding-left: 0;
  padding-right: 0;
}

.tag-list ::v-deep(.el-tag) {
  height: 28px;
  padding: 0 10px;
  border: 1px solid #c8d6e8;
  border-radius: 6px;
  background: #ffffff;
  color: #245b8f;
  font-size: 12px;
  font-weight: 600;
  line-height: 26px;
}
</style>
