<template>
  <section class="risk-detail-section">
    <div class="section-card">
      <div class="section-header">
        <div>
          <div class="section-title">风险明细</div>
          <div class="section-subtitle">展示涉疑交易与异常账户关联人员信息</div>
        </div>
      </div>

      <div class="block">
        <div class="block-header">
          <div>
            <div class="block-title">未提交账户</div>
            <div class="block-subtitle">被调查主体未提交分析的同名账户</div>
          </div>
          <el-button
            size="mini"
            type="text"
            :disabled="!projectId || unsubmittedAccountTotal <= 0"
            @click="handleUnsubmittedAccountExport"
          >
            导出
          </el-button>
        </div>

        <div v-loading="unsubmittedAccountLoading" class="unsubmitted-panel">
          <template v-if="unsubmittedAccountTotal > 0">
            <div class="unsubmitted-metrics">
              <div class="unsubmitted-metric">
                <div class="metric-label">涉及主体数</div>
                <div class="metric-value">{{ unsubmittedSubjectTotal }}</div>
              </div>
              <div class="unsubmitted-metric">
                <div class="metric-label">未提交账户数</div>
                <div class="metric-value">{{ unsubmittedAccountTotal }}</div>
              </div>
              <div class="unsubmitted-metric">
                <div class="metric-label">流入总额</div>
                <div class="metric-value amount-in">{{ formatWanAmount(unsubmittedAccountSummary.totalAmountCr) }}</div>
              </div>
              <div class="unsubmitted-metric">
                <div class="metric-label">流出总额</div>
                <div class="metric-value amount-out">-{{ formatWanAmount(unsubmittedAccountSummary.totalAmountDr) }}</div>
              </div>
              <div class="unsubmitted-metric">
                <div class="metric-label">流入/流出差额</div>
                <div
                  class="metric-value"
                  :class="Number(unsubmittedAccountSummary.netAmount || 0) >= 0 ? 'amount-in' : 'amount-out'"
                >
                  {{ formatWanAmount(unsubmittedAccountSummary.netAmount) }}
                </div>
              </div>
            </div>

            <div
              v-for="subject in unsubmittedAccountSubjects"
              :key="subject.subjectName"
              class="unsubmitted-subject"
            >
              <div class="unsubmitted-subject-name">{{ formatField(subject.subjectName) }}</div>
              <div class="unsubmitted-account-grid">
                <div
                  v-for="account in subject.accounts"
                  :key="`${subject.subjectName}-${account.accountNo}`"
                  class="unsubmitted-account-card"
                  role="button"
                  tabindex="0"
                  @click="handleUnsubmittedAccountCardClick(subject, account)"
                  @keyup.enter="handleUnsubmittedAccountCardClick(subject, account)"
                >
                  <div class="unsubmitted-account-head">
                    <div class="unsubmitted-account-no">
                      <i class="el-icon-bank-card"></i>
                      <span>{{ maskAccountNo(account.accountNo) }}</span>
                    </div>
                    <el-tag
                      v-if="account.highRatio"
                      size="mini"
                      type="danger"
                      effect="plain"
                    >
                      交易占比较高
                    </el-tag>
                  </div>
                  <div class="unsubmitted-card-metrics">
                    <div>
                      <div class="card-metric-label">流入金额</div>
                      <div class="card-metric-value amount-in">{{ formatWanAmount(account.totalAmountCr) }}</div>
                    </div>
                    <div>
                      <div class="card-metric-label">流出金额</div>
                      <div class="card-metric-value amount-out">-{{ formatWanAmount(account.totalAmountDr) }}</div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </template>
          <el-empty v-else :image-size="96" description="当前项目暂无未提交账户" />
        </div>
      </div>

      <div class="block">
        <div class="block-header">
          <div>
            <div class="block-title">涉疑交易明细</div>
            <div class="block-subtitle">展示涉疑交易的关键字段与风险金额</div>
          </div>
        </div>
        <el-form :inline="true" size="mini" class="suspicious-filter-form" @submit.native.prevent>
          <el-form-item label="命中模型">
            <el-select
              v-model="selectedModelCode"
              class="suspicious-filter-select"
              :placeholder="allModelOptionLabel"
              filterable
              @change="handleSuspiciousModelSelectChange"
            >
              <el-option :label="allModelOptionLabel" value="" />
              <el-option
                v-for="item in displayRiskModelOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="预警类型">
            <el-select
              v-model="currentSuspiciousType"
              class="suspicious-filter-select suspicious-type-select"
              placeholder="全部预警类型"
              @change="handleSuspiciousTypeSelectChange"
            >
              <el-option
                v-for="item in suspiciousTypeOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" icon="el-icon-search" :loading="suspiciousLoading" @click="handleSuspiciousQuery">
              查询
            </el-button>
          </el-form-item>
          <el-form-item class="suspicious-export-action">
            <el-button size="mini" type="text" :disabled="!projectId" @click="handleSuspiciousTransactionExport">
              导出
            </el-button>
          </el-form-item>
        </el-form>

        <el-table
          v-loading="suspiciousLoading"
          :data="suspiciousTransactionList"
          class="result-table"
        >
          <template slot="empty">
            <el-empty :image-size="96" description="当前筛选条件下暂无涉疑交易明细" />
          </template>
          <el-table-column prop="trxDate" label="交易时间" min-width="180" />
          <el-table-column label="本方账户" min-width="220">
            <template slot-scope="scope">
              <div class="multi-line-cell">
                <div class="primary-text">{{ formatField(scope.row.leAccountNo) }}</div>
                <div class="secondary-text">{{ formatField(scope.row.leAccountName) }}</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">
                  {{ formatCounterpartyName(scope.row) }}
                </div>
                <div class="secondary-text">
                  {{ formatField(scope.row.customerAccountNo) }}
                </div>
              </div>
            </template>
          </el-table-column>
          <el-table-column label="关联员工" min-width="160">
            <template slot-scope="scope">
              <div class="multi-line-cell">
                <div class="primary-text">{{ formatRelatedStaff(scope.row) }}</div>
              </div>
            </template>
          </el-table-column>
          <el-table-column label="摘要 / 交易类型" min-width="200">
            <template slot-scope="scope">
              <div class="multi-line-cell">
                <div class="primary-text">{{ formatField(scope.row.userMemo) }}</div>
                <div class="secondary-text">{{ formatField(scope.row.cashType) }}</div>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="displayAmount" label="交易金额" width="120" align="right">
            <template slot-scope="scope">
              <span
                class="amount-text"
                :class="scope.row.displayAmount >= 0 ? 'amount-in' : 'amount-out'"
              >
                {{ formatAmount(scope.row.displayAmount) }}
              </span>
            </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="hit-tag-list">
                <el-tag
                  v-for="(tag, index) in scope.row.hitTags"
                  :key="`${scope.row.bankStatementId}-tag-${index}`"
                  size="mini"
                  :type="mapRiskLevelToTagType(tag.riskLevel)"
                  effect="plain"
                >
                  {{ tag.ruleName }}
                </el-tag>
              </div>
              <span v-else class="empty-text">-</span>
            </template>
          </el-table-column>
          <el-table-column label="详情" width="100" fixed="right" align="center">
            <template slot-scope="scope">
              <el-button type="text" size="mini" @click="handleViewDetail(scope.row)">
                详情
              </el-button>
            </template>
          </el-table-column>
        </el-table>

        <pagination
          v-show="suspiciousTotal > 0"
          :total="suspiciousTotal"
          :page.sync="suspiciousPageNum"
          :limit.sync="suspiciousPageSize"
          :page-sizes="riskDetailPageSizeOptions"
          layout="total, sizes, prev, pager, next, jumper"
          @pagination="handlePageChange"
        />
      </div>

      <div class="block">
        <div class="block-header">
          <div>
            <div class="block-title">员工负面征信信息</div>
            <div class="block-subtitle">展示当前项目员工的负面征信信息</div>
          </div>
        </div>

        <el-table
          v-loading="employeeCreditNegativeLoading"
          :data="employeeCreditNegativeList"
          class="result-table"
        >
          <template slot="empty">
            <el-empty :image-size="96" description="当前项目暂无员工负面征信信息" />
          </template>
          <el-table-column prop="personName" label="员工姓名" min-width="140" />
          <el-table-column label="身份证号" min-width="180" show-overflow-tooltip>
            <template slot-scope="scope">
              {{ formatIdCard(scope.row.personId) }}
            </template>
          </el-table-column>
          <el-table-column prop="queryDate" label="最近征信查询日期" min-width="160" />
          <el-table-column prop="civilCnt" label="民事案件笔数" min-width="120" align="center" />
          <el-table-column label="民事案件金额" min-width="140" align="right">
            <template slot-scope="scope">
              {{ formatAmount(scope.row.civilLmt) }}
            </template>
          </el-table-column>
          <el-table-column prop="enforceCnt" label="强制执行笔数" min-width="120" align="center" />
          <el-table-column label="强制执行金额" min-width="140" align="right">
            <template slot-scope="scope">
              {{ formatAmount(scope.row.enforceLmt) }}
            </template>
          </el-table-column>
          <el-table-column prop="admCnt" label="行政处罚笔数" min-width="120" align="center" />
          <el-table-column label="行政处罚金额" min-width="140" align="right">
            <template slot-scope="scope">
              {{ formatAmount(scope.row.admLmt) }}
            </template>
          </el-table-column>
        </el-table>

        <pagination
          v-show="employeeCreditNegativeTotal > 0"
          :total="employeeCreditNegativeTotal"
          :page.sync="employeeCreditNegativePageNum"
          :limit.sync="employeeCreditNegativePageSize"
          :page-sizes="riskDetailPageSizeOptions"
          layout="total, sizes, prev, pager, next, jumper"
          @pagination="handleEmployeeCreditNegativePageChange"
        />
      </div>

      <div class="block">
        <div class="block-header">
          <div>
            <div class="block-title">异常账户人员信息</div>
            <div class="block-subtitle">展示异常账户关联人员与处理状态</div>
          </div>
        </div>

        <el-table
          v-loading="abnormalAccountLoading"
          :data="abnormalAccountList"
          class="result-table"
        >
          <template slot="empty">
            <el-empty :image-size="96" description="当前项目暂无异常账户人员信息" />
          </template>
          <el-table-column prop="accountNo" label="账号" min-width="160" />
          <el-table-column prop="accountName" label="开户人" min-width="120" />
          <el-table-column prop="bankName" label="银行" min-width="180" />
          <el-table-column prop="abnormalType" label="异常类型" min-width="160" />
          <el-table-column prop="abnormalTime" label="异常发生时间" min-width="160" />
          <el-table-column prop="status" label="状态" min-width="120" />
          <el-table-column prop="reasonDetail" label="命中原因" min-width="260" show-overflow-tooltip />
          <el-table-column prop="involvedAmount" label="涉及金额" min-width="130" align="right">
            <template slot-scope="scope">{{ formatAmount(scope.row.involvedAmount) }}</template>
          </el-table-column>
        </el-table>

        <pagination
          v-show="abnormalAccountTotal > 0"
          :total="abnormalAccountTotal"
          :page.sync="abnormalAccountPageNum"
          :limit.sync="abnormalAccountPageSize"
          :page-sizes="riskDetailPageSizeOptions"
          layout="total, sizes, prev, pager, next, jumper"
          @pagination="handleAbnormalAccountPageChange"
        />
      </div>
    </div>

    <el-dialog
      :visible.sync="unsubmittedFlowVisible"
      append-to-body
      custom-class="unsubmitted-flow-dialog"
      width="88%"
      top="4vh"
      @close="closeUnsubmittedFlowDialog"
    >
      <template slot="title">
        <div class="unsubmitted-flow-title">
          <span>流水明细</span>
          <div v-if="selectedUnsubmittedAccount" class="unsubmitted-flow-title-tags">
            <span>{{ formatUnsubmittedFlowPeriod }}</span>
            <span>{{ formatField(selectedUnsubmittedAccount.subjectName) }}</span>
            <span>{{ formatField(selectedUnsubmittedAccount.accountNo) }}</span>
          </div>
        </div>
      </template>
      <div class="unsubmitted-flow-toolbar">
        <el-radio-group v-model="unsubmittedFlowType" size="small">
          <el-radio-button label="ALL">全部 · {{ unsubmittedFlowAllCount }}</el-radio-button>
          <el-radio-button label="INFLOW">流入 · {{ unsubmittedFlowInCount }}</el-radio-button>
          <el-radio-button label="OUTFLOW">流出 · {{ unsubmittedFlowOutCount }}</el-radio-button>
        </el-radio-group>
        <el-button
          size="small"
          type="text"
          icon="el-icon-download"
          :disabled="!selectedUnsubmittedAccount || unsubmittedFlowAllCount <= 0"
          @click="handleUnsubmittedFlowExport"
        >
          导出流水
        </el-button>
      </div>
      <el-table
        v-loading="unsubmittedFlowLoading"
        :data="unsubmittedFlowFilteredList"
        class="result-table unsubmitted-flow-table"
        height="640"
      >
        <template slot="empty">
          <el-empty :image-size="96" description="当前账号暂无流水明细" />
        </template>
        <el-table-column label="交易时间" min-width="150">
          <template slot-scope="scope">
            <div class="multi-line-cell">
              <div class="primary-text">{{ formatDatePart(scope.row.trxDate) }}</div>
              <div class="secondary-text">{{ formatTimePart(scope.row.trxDate) }}</div>
            </div>
          </template>
        </el-table-column>
        <el-table-column label="本方账户/主体" min-width="240">
          <template slot-scope="scope">
            <div class="multi-line-cell">
              <div class="primary-text">{{ formatField(scope.row.leAccountNo) }}</div>
              <div class="secondary-text">{{ formatField(scope.row.leAccountName) }}</div>
            </div>
          </template>
        </el-table-column>
        <el-table-column label="对方名称/账户" min-width="260">
          <template slot-scope="scope">
            <div class="multi-line-cell">
              <div class="primary-text link-text">{{ formatField(scope.row.customerAccountName) }}</div>
              <div class="secondary-text">{{ formatField(scope.row.customerAccountNo) }}</div>
            </div>
          </template>
        </el-table-column>
        <el-table-column label="摘要/交易类型" min-width="260" show-overflow-tooltip>
          <template slot-scope="scope">
            <div class="multi-line-cell">
              <div class="primary-text">{{ formatField(scope.row.userMemo) }}</div>
              <div class="secondary-text">{{ formatField(scope.row.cashType) }}</div>
            </div>
          </template>
        </el-table-column>
        <el-table-column label="交易金额" min-width="170" align="right">
          <template slot-scope="scope">
            <span class="flow-amount" :class="getUnsubmittedFlowAmountClass(scope.row)">
              {{ formatUnsubmittedFlowAmount(scope.row) }}
            </span>
          </template>
        </el-table-column>
        <el-table-column label="分类" min-width="130">
          <template>
            <span>未提交账户</span>
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>

    <el-dialog
      :visible.sync="detailVisible"
      append-to-body
      custom-class="detail-dialog"
      width="980px"
      @close="closeDetailDialog"
    >
      <template slot="title">
        <div class="detail-dialog-title">
          <span>流水详情</span>
          <el-button
            class="evidence-corner-btn"
            size="mini"
            plain
            :disabled="detailLoading || !buildFlowEvidenceFingerprint(detailData)"
            @click="handleAddEvidence"
          >
            加入证据库
          </el-button>
        </div>
      </template>
      <div v-loading="detailLoading" class="detail-dialog-body">
        <div class="detail-overview-grid">
          <div class="detail-field">
            <div class="detail-label">交易时间</div>
            <div class="detail-value">{{ formatField(detailData.trxDate) }}</div>
          </div>
          <div class="detail-field">
            <div class="detail-label">交易金额</div>
            <div class="detail-value amount-text" :class="getAmountClass(detailData.displayAmount)">
              {{ formatSignedAmount(detailData.displayAmount) }}
            </div>
          </div>
          <div class="detail-field">
            <div class="detail-label">交易后余额</div>
            <div class="detail-value">{{ formatAmount(detailData.amountBalance) }}</div>
          </div>

          <div class="detail-field">
            <div class="detail-label">本方主体</div>
            <div class="detail-value">{{ formatField(detailData.leAccountName) }}</div>
          </div>
          <div class="detail-field">
            <div class="detail-label">本方账号</div>
            <div class="detail-value">{{ formatField(detailData.leAccountNo) }}</div>
          </div>
          <div class="detail-field">
            <div class="detail-label">本方银行</div>
            <div class="detail-value">{{ formatField(detailData.bank) }}</div>
          </div>

          <div class="detail-field">
            <div class="detail-label">对方名称</div>
            <div class="detail-value">{{ formatCounterpartyName(detailData) }}</div>
          </div>
          <div class="detail-field">
            <div class="detail-label">对方账户</div>
            <div class="detail-value">{{ formatField(detailData.customerAccountNo) }}</div>
          </div>
          <div class="detail-field">
            <div class="detail-label">对方银行</div>
            <div class="detail-value">{{ formatField(detailData.customerBank) }}</div>
          </div>

          <div class="detail-field">
            <div class="detail-label">摘要</div>
            <div class="detail-value">{{ formatField(detailData.userMemo) }}</div>
          </div>
          <div class="detail-field">
            <div class="detail-label">交易类型</div>
            <div class="detail-value">{{ formatField(detailData.cashType) }}</div>
          </div>
          <div class="detail-field">
            <div class="detail-label">银行摘要</div>
            <div class="detail-value">{{ formatField(detailData.bankComments) }}</div>
          </div>

          <div class="detail-field detail-field--full">
            <div class="detail-label">原始文件</div>
            <div class="detail-file-block">
              <i class="el-icon-document detail-file-icon"></i>
              <div class="detail-file-meta">
                <div class="detail-file-name">{{ formatOriginalFileName(detailData) }}</div>
                <div class="detail-file-time">
                  上传时间：{{ formatOriginalFileUploadTime(detailData) }}
                </div>
              </div>
            </div>
          </div>
        </div>

        <div class="detail-hit-tag-section">
          <div class="detail-section-title">命中异常标签</div>
          <div
            v-if="detailData.hitTags && detailData.hitTags.length"
            class="detail-hit-tag-items"
          >
            <div
              v-for="(tag, index) in detailData.hitTags"
              :key="`detail-tag-${index}`"
              class="detail-hit-tag-item"
            >
              <div class="detail-hit-tag-header">
                <span class="detail-hit-tag-name">{{ formatField(tag.ruleName) }}</span>
                <el-tag size="mini" :type="mapRiskLevelToTagType(tag.riskLevel)" effect="plain">
                  {{ formatRiskLevel(tag.riskLevel) }}
                </el-tag>
              </div>
              <div class="detail-hit-tag-reason">{{ formatField(tag.reasonDetail) }}</div>
            </div>
          </div>
          <div v-else class="detail-hit-tag-empty">当前流水未命中异常标签</div>
        </div>
      </div>
      <div slot="footer" class="detail-dialog-footer">
        <el-button @click="closeDetailDialog">取消</el-button>
        <el-button type="primary" @click="closeDetailDialog">确定</el-button>
      </div>
    </el-dialog>
  </section>
</template>

<script>
import {
  getOverviewAbnormalAccountPeople,
  getOverviewEmployeeCreditNegative,
  getOverviewSuspiciousTransactions,
  getOverviewUnsubmittedAccountFlows,
  getOverviewUnsubmittedAccounts,
} from "@/api/ccdi/projectOverview";
import { getBankStatementDetail } from "@/api/ccdiProjectBankStatement";
import { buildFlowEvidenceFingerprint, buildFlowEvidenceSnapshot } from "@/utils/ccdiEvidence";

const SUSPICIOUS_TYPE_OPTIONS = [
  { value: "ALL", label: "全部预警类型" },
  { value: "MODEL_RULE", label: "员工规则命中" },
  { value: "EXTERNAL_PERSON", label: "外部人员预警" },
];
const EXTERNAL_RISK_MODEL_OPTIONS = [
  { value: "EXTERNAL_LARGE_TRANSACTION", label: "外部人员大额交易" },
  { value: "EXTERNAL_SUSPICIOUS_GAMBLING", label: "外部人员可疑赌博" },
  { value: "EXTERNAL_SUSPICIOUS_RELATION", label: "外部人员可疑关系" },
];
const DEFAULT_SUSPICIOUS_PAGE_SIZE = 10;
const DEFAULT_RISK_DETAIL_PAGE_SIZE = 5;
const RISK_DETAIL_PAGE_SIZE_OPTIONS = [5, 10, 20, 50];

const normalizeSuspiciousType = (value) => (
  SUSPICIOUS_TYPE_OPTIONS.some((item) => item.value === value) ? value : "ALL"
);

const normalizeRiskModelOptions = (rows) => {
  if (!Array.isArray(rows)) {
    return [];
  }
  const seen = new Set();
  return rows
    .map((item) => ({
      value: item && (item.value || item.modelCode || item.key),
      label: item && (item.label || item.modelName || item.title),
    }))
    .filter((item) => {
      if (!item.value || seen.has(item.value)) {
        return false;
      }
      seen.add(item.value);
      return true;
    });
};

const mergeRiskModelOptions = (...optionGroups) => {
  const seen = new Set();
  return optionGroups
    .flat()
    .filter((item) => {
      if (!item || !item.value || seen.has(item.value)) {
        return false;
      }
      seen.add(item.value);
      return true;
    });
};

const isExternalModelCode = (value) => (
  typeof value === "string" && value.indexOf("EXTERNAL_") === 0
);

const ABNORMAL_CUSTOMER_TRANSACTION_RULE_CODE = "ABNORMAL_CUSTOMER_TRANSACTION";
const ABNORMAL_CUSTOMER_TRANSACTION_RULE_NAME = "与客户之间非正常资金往来";

const resolveAbnormalCustomerTransactionRuleName = (nameListHitType) => {
  if (nameListHitType === "中介") {
    return "疑似与中介往来";
  }
  if (nameListHitType === "信贷客户") {
    return "与信贷客户之间非正常资金往来";
  }
  return ABNORMAL_CUSTOMER_TRANSACTION_RULE_NAME;
};

const normalizeRuleName = (tag, context) => {
  if (!tag) {
    return "";
  }
  if (
    tag.ruleCode === ABNORMAL_CUSTOMER_TRANSACTION_RULE_CODE
    || tag.ruleName === "异常交易"
    || tag.ruleName === ABNORMAL_CUSTOMER_TRANSACTION_RULE_NAME
  ) {
    return resolveAbnormalCustomerTransactionRuleName(context && context.nameListHitType);
  }
  return tag.ruleName || "";
};

const normalizeHitTags = (hitTags, context = {}) => {
  if (!Array.isArray(hitTags)) {
    return [];
  }
  const seen = new Set();
  return hitTags
    .map((tag) => ({
      ...tag,
      ruleName: normalizeRuleName(tag, context),
    }))
    .filter((tag) => {
      const key = `${tag.ruleCode || ""}|${tag.ruleName || ""}`;
      if (seen.has(key)) {
        return false;
      }
      seen.add(key);
      return true;
    })
    .sort((left, right) => {
      const leftPriority = left.ruleCode === ABNORMAL_CUSTOMER_TRANSACTION_RULE_CODE ? 0 : 1;
      const rightPriority = right.ruleCode === ABNORMAL_CUSTOMER_TRANSACTION_RULE_CODE ? 0 : 1;
      return leftPriority - rightPriority;
    });
};

const createEmptyDetailData = () => ({
  bankStatementId: "",
  projectId: "",
  currency: "",
  trxDate: "",
  leAccountNo: "",
  leAccountName: "",
  customerAccountName: "",
  customerAccountNo: "",
  customerBank: "",
  customerReference: "",
  userMemo: "",
  bankComments: "",
  bankTrxNumber: "",
  bank: "",
  cashType: "",
  amountDr: "",
  amountCr: "",
  amountBalance: "",
  displayAmount: "",
  trxFlag: "",
  trxType: "",
  exceptionType: "",
  internalFlag: "",
  paymentMethod: "",
  cretNo: "",
  createDate: "",
  originalFileName: "",
  uploadTime: "",
  sourceFileName: "",
  fileName: "",
  hitTags: [],
});

const normalizeDetailData = (detail) => ({
  ...createEmptyDetailData(),
  ...(detail || {}),
  hitTags: normalizeHitTags(detail && detail.hitTags),
});

const normalizeSuspiciousRows = (rows) => (
  Array.isArray(rows)
    ? rows.map((row) => ({
      ...row,
      hitTags: normalizeHitTags(row && row.hitTags, row),
    }))
    : []
);

export default {
  name: "RiskDetailSection",
  props: {
    sectionData: {
      type: Object,
      default: () => ({}),
    },
  },
  data() {
    return {
      suspiciousLoading: false,
      detailLoading: false,
      detailVisible: false,
      detailData: createEmptyDetailData(),
      currentSuspiciousType: "ALL",
      selectedModelCode: "",
      suspiciousPageNum: 1,
      suspiciousPageSize: DEFAULT_SUSPICIOUS_PAGE_SIZE,
      suspiciousTotal: 0,
      suspiciousTransactionList: [],
      riskModelOptions: [],
      employeeCreditNegativeLoading: false,
      employeeCreditNegativePageNum: 1,
      employeeCreditNegativePageSize: DEFAULT_RISK_DETAIL_PAGE_SIZE,
      employeeCreditNegativeTotal: 0,
      employeeCreditNegativeList: [],
      abnormalAccountLoading: false,
      abnormalAccountPageNum: 1,
      abnormalAccountPageSize: DEFAULT_RISK_DETAIL_PAGE_SIZE,
      abnormalAccountTotal: 0,
      abnormalAccountList: [],
      unsubmittedAccountLoading: false,
      unsubmittedAccountSummary: {
        totalAmountCr: 0,
        totalAmountDr: 0,
        netAmount: 0,
      },
      unsubmittedAccountTotal: 0,
      unsubmittedAccountSubjects: [],
      unsubmittedFlowVisible: false,
      unsubmittedFlowLoading: false,
      unsubmittedFlowType: "ALL",
      selectedUnsubmittedAccount: null,
      unsubmittedFlowList: [],
      projectId: null,
      statementDetailCache: {},
      suspiciousRequestSeq: 0,
      detailRequestSeq: 0,
    };
  },
  computed: {
    riskDetailPageSizeOptions() {
      return RISK_DETAIL_PAGE_SIZE_OPTIONS;
    },
    suspiciousTypeOptions() {
      return SUSPICIOUS_TYPE_OPTIONS;
    },
    isExternalSuspiciousType() {
      return this.currentSuspiciousType === "EXTERNAL_PERSON";
    },
    displayRiskModelOptions() {
      if (this.isExternalSuspiciousType) {
        return EXTERNAL_RISK_MODEL_OPTIONS;
      }
      if (this.currentSuspiciousType === "ALL") {
        return mergeRiskModelOptions(this.riskModelOptions, EXTERNAL_RISK_MODEL_OPTIONS);
      }
      return this.riskModelOptions;
    },
    allModelOptionLabel() {
      return this.isExternalSuspiciousType ? "全部外部模型" : "全部模型";
    },
    unsubmittedFlowFilteredList() {
      if (this.unsubmittedFlowType === "INFLOW") {
        return this.unsubmittedFlowList.filter((row) => this.isUnsubmittedFlowIn(row));
      }
      if (this.unsubmittedFlowType === "OUTFLOW") {
        return this.unsubmittedFlowList.filter((row) => this.isUnsubmittedFlowOut(row));
      }
      return this.unsubmittedFlowList;
    },
    unsubmittedFlowAllCount() {
      return this.unsubmittedFlowList.length;
    },
    unsubmittedSubjectTotal() {
      return this.unsubmittedAccountSubjects.length;
    },
    unsubmittedFlowInCount() {
      return this.unsubmittedFlowList.filter((row) => this.isUnsubmittedFlowIn(row)).length;
    },
    unsubmittedFlowOutCount() {
      return this.unsubmittedFlowList.filter((row) => this.isUnsubmittedFlowOut(row)).length;
    },
    formatUnsubmittedFlowPeriod() {
      if (!this.selectedUnsubmittedAccount) {
        return "-";
      }
      return `${this.formatDatePart(this.selectedUnsubmittedAccount.startDate)} ~ ${this.formatDatePart(this.selectedUnsubmittedAccount.endDate)}`;
    },
  },
  watch: {
    sectionData: {
      immediate: true,
      handler(value) {
        const nextProjectId = value && value.projectId ? value.projectId : null;
        const projectChanged = String(nextProjectId || "") !== String(this.projectId || "");
        this.projectId = nextProjectId;
        this.riskModelOptions = normalizeRiskModelOptions(value && value.riskModelOptions);
        this.employeeCreditNegativePageNum = 1;
        this.employeeCreditNegativePageSize = DEFAULT_RISK_DETAIL_PAGE_SIZE;
        this.employeeCreditNegativeTotal = Number(value && value.employeeCreditNegativeTotal) || 0;
        this.abnormalAccountPageNum = 1;
        this.abnormalAccountPageSize = DEFAULT_RISK_DETAIL_PAGE_SIZE;
        this.abnormalAccountTotal = 0;
        this.abnormalAccountList = [];
        this.unsubmittedAccountTotal = 0;
        this.unsubmittedAccountSubjects = [];
        this.employeeCreditNegativeList = Array.isArray(value && value.employeeCreditNegativeList)
          ? value.employeeCreditNegativeList
          : [];
        if (projectChanged) {
          this.suspiciousRequestSeq += 1;
          this.detailRequestSeq += 1;
          this.currentSuspiciousType = normalizeSuspiciousType(value && value.suspiciousType);
          this.selectedModelCode = "";
          this.suspiciousPageNum = 1;
          this.suspiciousPageSize = DEFAULT_SUSPICIOUS_PAGE_SIZE;
          this.suspiciousTotal = Number(value && value.total) || 0;
          this.suspiciousTransactionList = normalizeSuspiciousRows(
            value && value.suspiciousTransactionList
          );
          this.suspiciousLoading = false;
          this.statementDetailCache = {};
          this.closeDetailDialog();
          this.closeUnsubmittedFlowDialog();
        }
        this.loadAbnormalAccountPeople();
        this.loadUnsubmittedAccounts();
      },
    },
  },
  methods: {
    buildFlowEvidenceFingerprint,
    handleSuspiciousModelSelectChange() {
      this.resetSuspiciousFilterResults();
    },
    handleSuspiciousTypeSelectChange(value) {
      if (value === "EXTERNAL_PERSON") {
        const hasExternalModel = EXTERNAL_RISK_MODEL_OPTIONS
          .some((item) => item.value === this.selectedModelCode);
        if (!hasExternalModel) {
          this.selectedModelCode = "";
        }
      } else if (value === "MODEL_RULE" && isExternalModelCode(this.selectedModelCode)) {
        this.selectedModelCode = "";
      }
      this.resetSuspiciousFilterResults();
    },
    resetSuspiciousFilterResults() {
      this.suspiciousRequestSeq += 1;
      this.detailRequestSeq += 1;
      this.suspiciousPageNum = 1;
      this.suspiciousTotal = 0;
      this.suspiciousTransactionList = [];
      this.suspiciousLoading = false;
      this.statementDetailCache = {};
      this.closeDetailDialog();
    },
    async handleSuspiciousQuery() {
      this.suspiciousPageNum = 1;
      await this.loadSuspiciousTransactions();
    },
    async refreshAfterRiskExcluded() {
      this.statementDetailCache = {};
      await this.loadSuspiciousTransactions();
      if (this.detailVisible && this.detailData && this.detailData.bankStatementId) {
        try {
          this.detailLoading = true;
          this.detailData = await this.fetchStatementDetail(this.detailData.bankStatementId, false);
        } catch (error) {
          this.$message.error("刷新流水详情失败");
          console.error("刷新流水详情失败", error);
        } finally {
          this.detailLoading = false;
        }
      }
    },
    async handlePageChange(pageInfo) {
      if (typeof pageInfo === "number") {
        this.suspiciousPageNum = pageInfo;
      } else {
        this.suspiciousPageNum = pageInfo.page;
        this.suspiciousPageSize = pageInfo.limit || this.suspiciousPageSize;
      }
      await this.loadSuspiciousTransactions();
    },
    async handleEmployeeCreditNegativePageChange(pageInfo) {
      if (typeof pageInfo === "number") {
        this.employeeCreditNegativePageNum = pageInfo;
      } else {
        this.employeeCreditNegativePageNum = pageInfo.page;
        this.employeeCreditNegativePageSize = pageInfo.limit || this.employeeCreditNegativePageSize;
      }
      await this.loadEmployeeCreditNegative();
    },
    async handleAbnormalAccountPageChange(pageInfo) {
      if (typeof pageInfo === "number") {
        this.abnormalAccountPageNum = pageInfo;
      } else {
        this.abnormalAccountPageNum = pageInfo.page;
        this.abnormalAccountPageSize = pageInfo.limit || this.abnormalAccountPageSize;
      }
      await this.loadAbnormalAccountPeople();
    },
    async loadSuspiciousTransactions() {
      const requestSeq = ++this.suspiciousRequestSeq;
      if (!this.projectId) {
        this.suspiciousTransactionList = [];
        this.suspiciousTotal = 0;
        this.suspiciousLoading = false;
        return;
      }

      const query = {
        projectId: this.projectId,
        modelCode: this.selectedModelCode,
        suspiciousType: this.currentSuspiciousType,
        pageNum: this.suspiciousPageNum,
        pageSize: this.suspiciousPageSize,
      };
      this.suspiciousLoading = true;
      try {
        const response = await getOverviewSuspiciousTransactions(query);
        if (requestSeq !== this.suspiciousRequestSeq) {
          return;
        }
        const data = (response && response.data) || {};
        this.suspiciousTotal = Number(data.total) || 0;
        this.suspiciousTransactionList = normalizeSuspiciousRows(data.rows);
      } catch (error) {
        if (requestSeq !== this.suspiciousRequestSeq) {
          return;
        }
        this.suspiciousTransactionList = [];
        this.suspiciousTotal = 0;
        this.$message.error("加载涉疑交易明细失败");
        console.error("加载涉疑交易明细失败", error);
      } finally {
        if (requestSeq === this.suspiciousRequestSeq) {
          this.suspiciousLoading = false;
        }
      }
    },
    async loadEmployeeCreditNegative() {
      if (!this.projectId) {
        this.employeeCreditNegativeList = [];
        this.employeeCreditNegativeTotal = 0;
        this.employeeCreditNegativeLoading = false;
        return;
      }

      this.employeeCreditNegativeLoading = true;
      try {
        const response = await getOverviewEmployeeCreditNegative({
          projectId: this.projectId,
          pageNum: this.employeeCreditNegativePageNum,
          pageSize: this.employeeCreditNegativePageSize,
        });
        const data = (response && response.data) || {};
        this.employeeCreditNegativeList = Array.isArray(data.rows) ? data.rows : [];
        this.employeeCreditNegativeTotal = Number(data.total) || 0;
      } catch (error) {
        this.employeeCreditNegativeList = [];
        this.employeeCreditNegativeTotal = 0;
        this.$message.error("加载员工负面征信信息失败");
        console.error("加载员工负面征信信息失败", error);
      } finally {
        this.employeeCreditNegativeLoading = false;
      }
    },
    async loadAbnormalAccountPeople() {
      if (!this.projectId) {
        this.abnormalAccountList = [];
        this.abnormalAccountTotal = 0;
        this.abnormalAccountLoading = false;
        return;
      }

      this.abnormalAccountLoading = true;
      try {
        const response = await getOverviewAbnormalAccountPeople({
          projectId: this.projectId,
          pageNum: this.abnormalAccountPageNum,
          pageSize: this.abnormalAccountPageSize,
        });
        const data = (response && response.data) || {};
        this.abnormalAccountList = Array.isArray(data.rows) ? data.rows : [];
        this.abnormalAccountTotal = Number(data.total) || 0;
      } catch (error) {
        this.abnormalAccountList = [];
        this.abnormalAccountTotal = 0;
        this.$message.error("加载异常账户人员信息失败");
        console.error("加载异常账户人员信息失败", error);
      } finally {
        this.abnormalAccountLoading = false;
      }
    },
    async loadUnsubmittedAccounts() {
      if (!this.projectId) {
        this.unsubmittedAccountSummary = {
          totalAmountCr: 0,
          totalAmountDr: 0,
          netAmount: 0,
        };
        this.unsubmittedAccountTotal = 0;
        this.unsubmittedAccountSubjects = [];
        this.unsubmittedAccountLoading = false;
        return;
      }

      this.unsubmittedAccountLoading = true;
      try {
        const response = await getOverviewUnsubmittedAccounts(this.projectId);
        const data = (response && response.data) || {};
        this.unsubmittedAccountSummary = {
          totalAmountCr: Number(data.totalAmountCr) || 0,
          totalAmountDr: Number(data.totalAmountDr) || 0,
          netAmount: Number(data.netAmount) || 0,
        };
        this.unsubmittedAccountTotal = Number(data.accountCount) || 0;
        this.unsubmittedAccountSubjects = Array.isArray(data.subjects) ? data.subjects : [];
      } catch (error) {
        this.unsubmittedAccountSummary = {
          totalAmountCr: 0,
          totalAmountDr: 0,
          netAmount: 0,
        };
        this.unsubmittedAccountTotal = 0;
        this.unsubmittedAccountSubjects = [];
        this.$message.error("加载未提交账户失败");
        console.error("加载未提交账户失败", error);
      } finally {
        this.unsubmittedAccountLoading = false;
      }
    },
    async handleUnsubmittedAccountCardClick(subject, account) {
      if (!this.projectId || !subject || !account || !account.accountNo) {
        return;
      }

      const selectedAccount = {
        ...account,
        subjectName: subject.subjectName,
      };
      this.selectedUnsubmittedAccount = selectedAccount;
      this.unsubmittedFlowType = "ALL";
      this.unsubmittedFlowList = [];
      this.unsubmittedFlowVisible = true;
      this.unsubmittedFlowLoading = true;
      try {
        const response = await getOverviewUnsubmittedAccountFlows({
          projectId: this.projectId,
          subjectName: selectedAccount.subjectName,
          accountNo: selectedAccount.accountNo,
        });
        this.unsubmittedFlowList = Array.isArray(response && response.data) ? response.data : [];
      } catch (error) {
        this.unsubmittedFlowList = [];
        this.$message.error("加载未提交账户流水失败");
        console.error("加载未提交账户流水失败", error);
      } finally {
        this.unsubmittedFlowLoading = false;
      }
    },
    closeUnsubmittedFlowDialog() {
      this.unsubmittedFlowVisible = false;
      this.unsubmittedFlowLoading = false;
      this.unsubmittedFlowType = "ALL";
      this.selectedUnsubmittedAccount = null;
      this.unsubmittedFlowList = [];
    },
    async fetchStatementDetail(bankStatementId, silent, scope = {}) {
      if (!bankStatementId) {
        return createEmptyDetailData();
      }

      const modelCode = scope.modelCode !== undefined ? scope.modelCode : this.selectedModelCode;
      const suspiciousType = scope.suspiciousType || this.currentSuspiciousType;
      const cacheKey = `${bankStatementId}|${suspiciousType || "ALL"}|${modelCode || "ALL"}`;
      if (this.statementDetailCache[cacheKey]) {
        return this.statementDetailCache[cacheKey];
      }

      try {
        const response = await getBankStatementDetail(bankStatementId, {
          modelCode,
          suspiciousType,
        });
        const detail = normalizeDetailData(response && response.data);
        this.$set(this.statementDetailCache, cacheKey, detail);
        return detail;
      } catch (error) {
        if (!silent) {
          throw error;
        }
        return createEmptyDetailData();
      }
    },
    async handleViewDetail(row) {
      if (!row || !row.bankStatementId) {
        return;
      }

      const requestSeq = ++this.detailRequestSeq;
      const scope = {
        modelCode: this.selectedModelCode,
        suspiciousType: this.currentSuspiciousType,
      };
      this.detailVisible = true;
      this.detailLoading = true;
      try {
        const detail = await this.fetchStatementDetail(row.bankStatementId, false, scope);
        if (requestSeq !== this.detailRequestSeq) {
          return;
        }
        this.detailData = {
          ...detail,
          ...row,
          hitTags: row && Array.isArray(row.hitTags) && row.hitTags.length
            ? normalizeHitTags(row.hitTags, row)
            : normalizeHitTags(detail.hitTags, row),
        };
      } catch (error) {
        if (requestSeq !== this.detailRequestSeq) {
          return;
        }
        this.detailData = createEmptyDetailData();
        this.$message.error("加载流水详情失败");
        console.error("加载流水详情失败", error);
      } finally {
        if (requestSeq === this.detailRequestSeq) {
          this.detailLoading = false;
        }
      }
    },
    closeDetailDialog() {
      this.detailVisible = false;
      this.detailLoading = false;
      this.detailData = createEmptyDetailData();
    },
    handleAddEvidence() {
      const detail = this.detailData || {};
      const sourceRecordId = buildFlowEvidenceFingerprint(detail);
      const amountText = this.formatSignedAmount(detail.displayAmount);
      const counterparty = this.formatCounterpartyName(detail);
      const relatedPersonName = this.resolveFlowRelatedPerson(detail);
      const hitTagText = Array.isArray(detail.hitTags) && detail.hitTags.length
        ? `，命中${detail.hitTags.map((tag) => tag.ruleName).filter(Boolean).join("、")}标签`
        : "";
      this.$emit("evidence-confirm", {
        evidenceType: "FLOW",
        relatedPersonName,
        relatedPersonId: detail.cretNo || "",
        evidenceTitle: `${relatedPersonName} / ${this.formatField(detail.leAccountNo)}`,
        evidenceSummary: `${this.formatField(detail.trxDate)}，${relatedPersonName}账户与${counterparty}发生交易，金额${amountText}${hitTagText}。`,
        sourceType: "BANK_STATEMENT",
        sourceRecordId,
        sourcePage: "流水详情",
        snapshotJson: JSON.stringify(buildFlowEvidenceSnapshot(detail)),
      });
    },
    resolveFlowRelatedPerson(detail) {
      const value = this.formatField(detail.leAccountName);
      return value === "-" ? "关联人员" : value;
    },
    handleSuspiciousTransactionExport() {
      if (!this.projectId) {
        return;
      }
      this.download(
        "ccdi/project/overview/suspicious-transactions/export",
        {
          projectId: this.projectId,
          modelCode: this.selectedModelCode,
          suspiciousType: this.currentSuspiciousType,
        },
        `涉疑交易明细_${this.projectId}_${new Date().getTime()}.xlsx`
      );
    },
    handleUnsubmittedAccountExport() {
      if (!this.projectId || this.unsubmittedAccountTotal <= 0) {
        return;
      }
      this.download(
        "ccdi/project/overview/unsubmitted-accounts/export",
        { projectId: this.projectId },
        `未提交账户流水_${this.projectId}_${new Date().getTime()}.xlsx`
      );
    },
    handleUnsubmittedFlowExport() {
      if (!this.projectId || !this.selectedUnsubmittedAccount) {
        return;
      }
      this.download(
        "ccdi/project/overview/unsubmitted-accounts/export",
        {
          projectId: this.projectId,
          subjectName: this.selectedUnsubmittedAccount.subjectName,
          accountNo: this.selectedUnsubmittedAccount.accountNo,
        },
        `未提交账户流水_${this.projectId}_${this.selectedUnsubmittedAccount.accountNo}_${new Date().getTime()}.xlsx`
      );
    },
    formatRelatedStaff(row) {
      if (!row || !row.relatedStaffName) {
        return "-";
      }
      return row.relatedStaffCode
        ? `${row.relatedStaffName}(${row.relatedStaffCode})`
        : row.relatedStaffName;
    },
    formatSummaryAndCashType(row) {
      const summary = row && row.userMemo ? row.userMemo : "";
      const cashType = row && row.cashType ? row.cashType : "";
      return `${summary}/${cashType}`;
    },
    formatCounterpartyName(detail) {
      if (!detail) {
        return "-";
      }
      return this.formatField(detail.customerAccountName);
    },
    formatField(value) {
      if (value === null || value === undefined || value === "") {
        return "-";
      }
      return String(value);
    },
    formatIdCard(value) {
      if (value === null || value === undefined || value === "") {
        return "-";
      }
      return String(value);
    },
    formatAmount(value) {
      if (value === null || value === undefined || value === "") {
        return "-";
      }
      const amount = Number(value);
      if (Number.isNaN(amount)) {
        return "-";
      }
      return amount.toLocaleString("zh-CN", {
        minimumFractionDigits: 2,
        maximumFractionDigits: 2,
      });
    },
    formatWanAmount(value) {
      if (value === null || value === undefined || value === "") {
        return "0.00 万元";
      }
      const amount = Number(value);
      if (Number.isNaN(amount)) {
        return "0.00 万元";
      }
      return `${(amount / 10000).toLocaleString("zh-CN", {
        minimumFractionDigits: 2,
        maximumFractionDigits: 2,
      })} 万元`;
    },
    maskAccountNo(value) {
      if (value === null || value === undefined || value === "") {
        return "-";
      }
      const text = String(value);
      if (text.length <= 10) {
        return text;
      }
      return `${text.slice(0, 8)} ... ${text.slice(-6)}`;
    },
    formatDatePart(value) {
      if (value === null || value === undefined || value === "") {
        return "-";
      }
      return String(value).split(" ")[0] || "-";
    },
    formatTimePart(value) {
      if (value === null || value === undefined || value === "") {
        return "-";
      }
      const parts = String(value).split(" ");
      return parts.length > 1 && parts[1] ? parts[1] : "-";
    },
    isUnsubmittedFlowIn(row) {
      return Number(row && row.amountCr) > 0;
    },
    isUnsubmittedFlowOut(row) {
      return Number(row && row.amountDr) > 0;
    },
    getUnsubmittedFlowAmountValue(row) {
      if (this.isUnsubmittedFlowIn(row)) {
        return Number(row.amountCr) || 0;
      }
      if (this.isUnsubmittedFlowOut(row)) {
        return -Number(row.amountDr || 0);
      }
      return 0;
    },
    formatUnsubmittedFlowAmount(row) {
      const amount = this.getUnsubmittedFlowAmountValue(row);
      const prefix = amount < 0 ? "-¥" : "¥";
      return `${prefix}${this.formatAmount(Math.abs(amount))}`;
    },
    getUnsubmittedFlowAmountClass(row) {
      return this.getUnsubmittedFlowAmountValue(row) >= 0 ? "amount-in" : "amount-out";
    },
    formatSignedAmount(value) {
      if (value === null || value === undefined || value === "") {
        return "-";
      }
      const amount = Number(value);
      if (Number.isNaN(amount)) {
        return "-";
      }
      const text = this.formatAmount(amount);
      return amount >= 0 ? `+${text}` : `-${this.formatAmount(Math.abs(amount))}`;
    },
    getAmountClass(value) {
      if (value === null || value === undefined || value === "") {
        return "";
      }
      return Number(value) >= 0 ? "amount-in" : "amount-out";
    },
    formatOriginalFileName(detail) {
      if (!detail) {
        return "暂无原始文件";
      }
      return (
        detail.originalFileName ||
        detail.sourceFileName ||
        detail.fileName ||
        "暂无原始文件"
      );
    },
    formatOriginalFileUploadTime(detail) {
      if (!detail || !detail.uploadTime) {
        return "-";
      }
      return String(detail.uploadTime);
    },
    formatRiskLevel(value) {
      const level = String(value || "").toUpperCase();
      if (level === "HIGH") {
        return "高风险";
      }
      if (level === "MEDIUM") {
        return "中风险";
      }
      if (level === "LOW") {
        return "低风险";
      }
      return "未标注";
    },
    mapRiskLevelToTagType(riskLevel) {
      const level = String(riskLevel || "").toUpperCase();
      if (level === "HIGH") {
        return "danger";
      }
      if (level === "MEDIUM") {
        return "warning";
      }
      return "info";
    },
  },
};
</script>

<style lang="scss" scoped>
.risk-detail-section {
  margin-bottom: 16px;
}

.section-card {
  padding: 20px;
  border-radius: 0;
  background: #fff;
  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.06);
}

.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 18px;
  padding-left: 12px;
  border-left: 4px solid #2563eb;
}

.section-title {
  font-size: 20px;
  line-height: 28px;
  font-weight: 700;
  color: #0f172a;
}

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

.block + .block {
  margin-top: 24px;
}

.block-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 14px;
}

.block-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

.el-dropdown-link {
  font-size: 12px;
  color: #2563eb;
  cursor: pointer;
}

.block-title {
  position: relative;
  padding-left: 10px;
  font-size: 15px;
  font-weight: 600;
  color: #334155;
}

.block-title::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 4px;
  height: 14px;
  border-radius: 999px;
  background: #94a3b8;
  transform: translateY(-50%);
}

.block-subtitle {
  margin-top: 4px;
  padding-left: 10px;
  font-size: 12px;
  color: #94a3b8;
}

.suspicious-filter-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  margin-bottom: 14px;
  padding: 10px 12px;
  background: #f8fafc;
  border: 1px solid #e2e8f0;
}

.suspicious-filter-form :deep(.el-form-item) {
  margin-right: 0;
  margin-bottom: 0;
}

.suspicious-filter-form :deep(.el-form-item__label) {
  color: #475569;
  font-weight: 500;
}

.suspicious-filter-form :deep(.el-button) {
  min-width: 88px;
}

.suspicious-export-action {
  margin-left: auto;
}

.suspicious-filter-select {
  width: 240px;
}

.suspicious-type-select {
  width: 240px;
}

.unsubmitted-panel {
  min-height: 120px;
}

.unsubmitted-metrics {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 18px;
  margin-bottom: 24px;
}

.unsubmitted-metric {
  min-width: 0;
}

.metric-label {
  color: #64748b;
  font-size: 13px;
  line-height: 20px;
}

.metric-value {
  margin-top: 6px;
  color: #0f172a;
  font-size: 24px;
  line-height: 32px;
  font-weight: 700;
  overflow-wrap: anywhere;
}

.unsubmitted-subject + .unsubmitted-subject {
  margin-top: 22px;
}

.unsubmitted-subject-name {
  margin-bottom: 12px;
  color: #111827;
  font-size: 15px;
  line-height: 22px;
  font-weight: 700;
}

.unsubmitted-account-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(220px, 1fr));
  gap: 16px;
}

.unsubmitted-account-card {
  min-width: 0;
  min-height: 132px;
  padding: 18px 20px;
  border: 1px solid #e5e7eb;
  background: #fff;
  cursor: pointer;
  transition: border-color 0.16s ease, box-shadow 0.16s ease, transform 0.16s ease;
}

.unsubmitted-account-card:hover,
.unsubmitted-account-card:focus {
  border-color: #93c5fd;
  box-shadow: 0 10px 24px rgba(37, 99, 235, 0.1);
  outline: none;
  transform: translateY(-1px);
}

.unsubmitted-account-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  min-height: 28px;
}

.unsubmitted-account-no {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  color: #111827;
  font-size: 14px;
  line-height: 22px;
  font-weight: 600;
}

.unsubmitted-account-no i {
  flex: 0 0 auto;
  color: #9ca3af;
}

.unsubmitted-account-no span {
  min-width: 0;
  overflow-wrap: anywhere;
}

.unsubmitted-card-metrics {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  margin-top: 24px;
}

.card-metric-label {
  color: #64748b;
  font-size: 13px;
  line-height: 20px;
}

.card-metric-value {
  margin-top: 4px;
  font-size: 16px;
  line-height: 24px;
  font-weight: 700;
  overflow-wrap: anywhere;
}

.unsubmitted-flow-title {
  display: flex;
  align-items: center;
  gap: 18px;
  min-width: 0;
}

.unsubmitted-flow-title > span {
  flex: 0 0 auto;
  color: #111827;
  font-size: 18px;
  font-weight: 700;
}

.unsubmitted-flow-title-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  min-width: 0;
}

.unsubmitted-flow-title-tags span {
  max-width: 260px;
  padding: 4px 10px;
  color: #409eff;
  background: #ecf5ff;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.unsubmitted-flow-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
}

.unsubmitted-flow-table :deep(.el-table__header th) {
  background: #fff;
  color: #606266;
  font-size: 14px;
}

.flow-amount {
  font-size: 16px;
  font-weight: 600;
}

.link-text {
  color: #409eff;
}

.result-table {
  width: 100%;
}

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

.primary-text {
  color: #303133;
  line-height: 20px;
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: break-word;
}

.secondary-text {
  color: #909399;
  font-size: 12px;
  line-height: 18px;
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: break-word;
}

.hit-tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  min-width: 0;
}

.hit-tag-list ::v-deep .el-tag {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}

.empty-text {
  color: var(--ccdi-text-muted);
  font-size: 13px;
  line-height: 20px;
}

.amount-text {
  font-weight: 600;
}

.amount-in {
  color: #67c23a;
}

.amount-out {
  color: #f56c6c;
}

.detail-dialog-body {
  min-height: 280px;
}

.detail-overview-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px 32px;
  margin-bottom: 24px;
}

.detail-field {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}

.detail-field--full {
  grid-column: 1 / -1;
}

.detail-label {
  font-size: 14px;
  line-height: 20px;
  color: var(--ccdi-text-muted);
}

.detail-value {
  color: var(--ccdi-text-primary);
  line-height: 22px;
  font-size: 16px;
  font-weight: 500;
  word-break: break-all;
}

.detail-file-block {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 2px 0;
}

.detail-file-icon {
  margin-top: 2px;
  font-size: 20px;
  color: #a56a2a;
}

.detail-file-meta {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.detail-file-name {
  color: var(--ccdi-text-primary);
  line-height: 22px;
  word-break: break-all;
}

.detail-file-time {
  color: var(--ccdi-text-muted);
  font-size: 12px;
  line-height: 18px;
}

.detail-hit-tag-section {
  border-top: 1px solid var(--ccdi-line);
  padding-top: 24px;
}

.detail-section-title {
  margin-bottom: 16px;
  font-size: 16px;
  font-weight: 600;
  color: var(--ccdi-text-primary);
}

.detail-hit-tag-items {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.detail-hit-tag-item {
  padding: 12px 16px;
  border: 1px solid var(--ccdi-border);
  border-radius: 12px;
  background: #fbfcfe;
}

.detail-hit-tag-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.detail-hit-tag-name {
  color: var(--ccdi-text-primary);
  font-size: 14px;
  font-weight: 600;
  line-height: 22px;
  word-break: break-all;
}

.detail-hit-tag-reason {
  margin-top: 8px;
  color: var(--ccdi-text-secondary);
  font-size: 13px;
  line-height: 20px;
  word-break: break-word;
}

.detail-hit-tag-empty {
  color: var(--ccdi-text-muted);
  font-size: 13px;
  line-height: 20px;
}

.detail-dialog-footer {
  display: flex;
  justify-content: center;
  gap: 12px;
}

.detail-dialog-title {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

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

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

:deep(.detail-dialog) {
  border-radius: 8px;

  .el-dialog__header {
    padding: 20px 24px;
    border-bottom: 1px solid var(--ccdi-line);
  }

  .el-dialog__title {
    font-size: 20px;
    font-weight: 600;
    color: var(--ccdi-text-primary);
  }

  .el-dialog__body {
    padding: 24px;
  }

  .el-dialog__footer {
    padding: 8px 24px 24px;
  }

  .el-button {
    min-width: 180px;
  }
}

@media (max-width: 992px) {
  .unsubmitted-metrics {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .unsubmitted-account-grid {
    grid-template-columns: repeat(2, minmax(220px, 1fr));
  }

  .detail-overview-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 20px 24px;
  }
}

@media (max-width: 768px) {
  .unsubmitted-metrics,
  .unsubmitted-account-grid,
  .unsubmitted-card-metrics {
    grid-template-columns: 1fr;
  }

  .suspicious-filter-form {
    align-items: stretch;
  }

  .suspicious-filter-form :deep(.el-form-item) {
    width: 100%;
  }

  .suspicious-filter-form :deep(.el-form-item__content),
  .suspicious-filter-select,
  .suspicious-type-select,
  .suspicious-filter-form :deep(.el-button) {
    width: 100%;
  }

  .detail-overview-grid {
    grid-template-columns: 1fr;
    gap: 18px;
  }

  .detail-dialog-footer {
    flex-direction: column;
  }

  .detail-hit-tag-header {
    flex-direction: column;
    align-items: stretch;
  }

  :deep(.detail-dialog) {
    width: calc(100vw - 24px) !important;
    margin-top: 8vh !important;

    .el-dialog__header,
    .el-dialog__body,
    .el-dialog__footer {
      padding-left: 16px;
      padding-right: 16px;
    }

    .el-button {
      width: 100%;
      min-width: 0;
    }
  }
}
</style>
