package com.ruoyi.security.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.security.domain.DataConsistencyCheck;
import com.ruoyi.security.domain.RiskEvent;
import com.ruoyi.security.domain.RiskEventTracking;
import com.ruoyi.security.mapper.DataConsistencyCheckMapper;
import com.ruoyi.security.mapper.RiskEventMapper;
import com.ruoyi.security.mapper.RiskEventTrackingMapper;
import com.ruoyi.security.service.IRiskMonitorService;

/**
 * 风险监控服务实现
 * 
 * @author ruoyi
 * @date 2025-12-22
 */
@Service
public class RiskMonitorServiceImpl implements IRiskMonitorService
{
    private static final Logger log = LoggerFactory.getLogger(RiskMonitorServiceImpl.class);

    @Autowired
    private RiskEventMapper riskEventMapper;

    @Autowired
    private RiskEventTrackingMapper riskEventTrackingMapper;

    @Autowired
    private DataConsistencyCheckMapper dataConsistencyCheckMapper;

    // Note: Notification service integration will be implemented when the notification module is available

    /**
     * 检查合同金额与服务确认单金额一致性
     */
    @Override
    @Transactional
    public DataConsistencyCheck checkContractAmountConsistency(Long contractId, Long serviceConfirmationId)
    {
        log.info("开始检查合同金额一致性: contractId={}, serviceConfirmationId={}", contractId, serviceConfirmationId);
        
        DataConsistencyCheck check = new DataConsistencyCheck();
        check.setCheckType(DataConsistencyCheck.CHECK_TYPE_CONTRACT_AMOUNT);
        check.setSourceEntityId(contractId);
        check.setTargetEntityId(serviceConfirmationId);
        check.setCheckTime(DateUtils.getNowDate());
        check.setCheckedBy(SecurityUtils.getUsername());
        check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_PENDING);
        
        try {
            // TODO: 实际的金额比较逻辑需要从合同和服务确认单表中获取数据
            // 这里先模拟检查逻辑
            BigDecimal contractAmount = getContractAmount(contractId);
            BigDecimal confirmationAmount = getServiceConfirmationAmount(serviceConfirmationId);
            
            if (contractAmount != null && confirmationAmount != null) {
                if (contractAmount.compareTo(confirmationAmount) == 0) {
                    check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_PASS);
                    check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
                    log.info("合同金额一致性检查通过: contractAmount={}, confirmationAmount={}", contractAmount, confirmationAmount);
                } else {
                    check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_FAIL);
                    check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
                    check.setInconsistencyDetails(String.format("合同金额(%s)与服务确认单金额(%s)不一致", contractAmount, confirmationAmount));
                    
                    // 创建风险事件
                    createRiskEventForAmountInconsistency(contractId, serviceConfirmationId, contractAmount, confirmationAmount);
                    log.warn("合同金额一致性检查失败: contractAmount={}, confirmationAmount={}", contractAmount, confirmationAmount);
                }
            } else {
                check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_FAIL);
                check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
                check.setInconsistencyDetails("无法获取合同或服务确认单金额信息");
                log.error("无法获取金额信息进行一致性检查");
            }
            
            dataConsistencyCheckMapper.insertDataConsistencyCheck(check);
            
        } catch (Exception e) {
            log.error("合同金额一致性检查异常", e);
            check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_FAIL);
            check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
            check.setInconsistencyDetails("检查过程中发生异常: " + e.getMessage());
            dataConsistencyCheckMapper.insertDataConsistencyCheck(check);
        }
        
        return check;
    }

    /**
     * 检查服务确认单与发票金额一致性
     */
    @Override
    @Transactional
    public DataConsistencyCheck checkInvoiceAmountConsistency(Long serviceConfirmationId, Long invoiceId)
    {
        log.info("开始检查发票金额一致性: serviceConfirmationId={}, invoiceId={}", serviceConfirmationId, invoiceId);
        
        DataConsistencyCheck check = new DataConsistencyCheck();
        check.setCheckType(DataConsistencyCheck.CHECK_TYPE_INVOICE_AMOUNT);
        check.setSourceEntityId(serviceConfirmationId);
        check.setTargetEntityId(invoiceId);
        check.setCheckTime(DateUtils.getNowDate());
        check.setCheckedBy(SecurityUtils.getUsername());
        check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_PENDING);
        
        try {
            // TODO: 实际的金额比较逻辑需要从服务确认单和发票表中获取数据
            BigDecimal confirmationAmount = getServiceConfirmationAmount(serviceConfirmationId);
            BigDecimal invoiceAmount = getInvoiceAmount(invoiceId);
            
            if (confirmationAmount != null && invoiceAmount != null) {
                if (confirmationAmount.compareTo(invoiceAmount) == 0) {
                    check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_PASS);
                    check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
                    log.info("发票金额一致性检查通过: confirmationAmount={}, invoiceAmount={}", confirmationAmount, invoiceAmount);
                } else {
                    check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_FAIL);
                    check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
                    check.setInconsistencyDetails(String.format("服务确认单金额(%s)与发票金额(%s)不一致", confirmationAmount, invoiceAmount));
                    
                    // 创建高风险事件，需要推送给银行和平台管理员
                    createRiskEventForInvoiceInconsistency(serviceConfirmationId, invoiceId, confirmationAmount, invoiceAmount);
                    log.warn("发票金额一致性检查失败: confirmationAmount={}, invoiceAmount={}", confirmationAmount, invoiceAmount);
                }
            } else {
                check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_FAIL);
                check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
                check.setInconsistencyDetails("无法获取服务确认单或发票金额信息");
                log.error("无法获取金额信息进行发票一致性检查");
            }
            
            dataConsistencyCheckMapper.insertDataConsistencyCheck(check);
            
        } catch (Exception e) {
            log.error("发票金额一致性检查异常", e);
            check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_FAIL);
            check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
            check.setInconsistencyDetails("检查过程中发生异常: " + e.getMessage());
            dataConsistencyCheckMapper.insertDataConsistencyCheck(check);
        }
        
        return check;
    }

    /**
     * 验证开票方与收票方主体信息
     */
    @Override
    @Transactional
    public DataConsistencyCheck validatePartyInformation(String invoiceParty, String contractParty)
    {
        log.info("开始验证主体信息: invoiceParty={}, contractParty={}", invoiceParty, contractParty);
        
        DataConsistencyCheck check = new DataConsistencyCheck();
        check.setCheckType(DataConsistencyCheck.CHECK_TYPE_PARTY_INFO);
        check.setCheckTime(DateUtils.getNowDate());
        check.setCheckedBy(SecurityUtils.getUsername());
        check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_PENDING);
        
        try {
            if (StringUtils.isNotEmpty(invoiceParty) && StringUtils.isNotEmpty(contractParty)) {
                // 进行主体信息匹配验证
                if (invoiceParty.trim().equals(contractParty.trim())) {
                    check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_PASS);
                    check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
                    log.info("主体信息验证通过: invoiceParty={}, contractParty={}", invoiceParty, contractParty);
                } else {
                    check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_FAIL);
                    check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
                    check.setInconsistencyDetails(String.format("开票方(%s)与收票方(%s)主体信息不匹配", invoiceParty, contractParty));
                    
                    // 创建阻断性风险事件
                    createRiskEventForPartyMismatch(invoiceParty, contractParty);
                    log.warn("主体信息验证失败: invoiceParty={}, contractParty={}", invoiceParty, contractParty);
                }
            } else {
                check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_FAIL);
                check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
                check.setInconsistencyDetails("开票方或收票方信息为空");
                log.error("主体信息验证失败: 信息为空");
            }
            
            dataConsistencyCheckMapper.insertDataConsistencyCheck(check);
            
        } catch (Exception e) {
            log.error("主体信息验证异常", e);
            check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_FAIL);
            check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
            check.setInconsistencyDetails("验证过程中发生异常: " + e.getMessage());
            dataConsistencyCheckMapper.insertDataConsistencyCheck(check);
        }
        
        return check;
    }

    /**
     * 检查服务期限与实际服务周期一致性
     */
    @Override
    @Transactional
    public DataConsistencyCheck checkServicePeriodConsistency(Long contractId, String actualServicePeriods)
    {
        log.info("开始检查服务期限一致性: contractId={}, actualServicePeriods={}", contractId, actualServicePeriods);
        
        DataConsistencyCheck check = new DataConsistencyCheck();
        check.setCheckType(DataConsistencyCheck.CHECK_TYPE_SERVICE_PERIOD);
        check.setSourceEntityId(contractId);
        check.setCheckTime(DateUtils.getNowDate());
        check.setCheckedBy(SecurityUtils.getUsername());
        check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_PENDING);
        
        try {
            // TODO: 实际的期限比较逻辑需要从合同表中获取服务期限数据
            String contractPeriod = getContractServicePeriod(contractId);
            
            if (StringUtils.isNotEmpty(contractPeriod) && StringUtils.isNotEmpty(actualServicePeriods)) {
                if (contractPeriod.equals(actualServicePeriods)) {
                    check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_PASS);
                    check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
                    log.info("服务期限一致性检查通过: contractPeriod={}, actualServicePeriods={}", contractPeriod, actualServicePeriods);
                } else {
                    check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_FAIL);
                    check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
                    check.setInconsistencyDetails(String.format("合同服务期限(%s)与实际服务周期(%s)不一致", contractPeriod, actualServicePeriods));
                    
                    // 创建提醒性风险事件
                    createRiskEventForPeriodInconsistency(contractId, contractPeriod, actualServicePeriods);
                    log.warn("服务期限一致性检查失败: contractPeriod={}, actualServicePeriods={}", contractPeriod, actualServicePeriods);
                }
            } else {
                check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_FAIL);
                check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
                check.setInconsistencyDetails("无法获取合同服务期限或实际服务周期信息");
                log.error("无法获取期限信息进行一致性检查");
            }
            
            dataConsistencyCheckMapper.insertDataConsistencyCheck(check);
            
        } catch (Exception e) {
            log.error("服务期限一致性检查异常", e);
            check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_FAIL);
            check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
            check.setInconsistencyDetails("检查过程中发生异常: " + e.getMessage());
            dataConsistencyCheckMapper.insertDataConsistencyCheck(check);
        }
        
        return check;
    }

    /**
     * 验证融资申请数据一致性
     */
    @Override
    @Transactional
    public DataConsistencyCheck validateFinancingDataConsistency(Long applicationId)
    {
        log.info("开始验证融资申请数据一致性: applicationId={}", applicationId);
        
        DataConsistencyCheck check = new DataConsistencyCheck();
        check.setCheckType("FINANCING_DATA");
        check.setSourceEntityId(applicationId);
        check.setCheckTime(DateUtils.getNowDate());
        check.setCheckedBy(SecurityUtils.getUsername());
        check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_PENDING);
        
        try {
            // 执行多项一致性检查
            List<String> inconsistencies = new ArrayList<>();
            
            // 1. 检查债权凭证有效性
            if (!validateCreditCertificateValidity(applicationId)) {
                inconsistencies.add("债权凭证无效或已过期");
            }
            
            // 2. 检查申请金额与债权金额的合理性
            if (!validateApplicationAmountReasonableness(applicationId)) {
                inconsistencies.add("申请金额超出债权金额或不合理");
            }
            
            // 3. 检查相关合同状态
            if (!validateRelatedContractStatus(applicationId)) {
                inconsistencies.add("关联合同状态不符合融资条件");
            }
            
            // 4. 检查申请人权限
            if (!validateApplicantPermissions(applicationId)) {
                inconsistencies.add("申请人无权对该债权申请融资");
            }
            
            // 5. 检查历史风险记录
            if (!validateHistoricalRiskRecord(applicationId)) {
                inconsistencies.add("申请人存在未解决的历史风险事件");
            }
            
            // 6. 检查数据完整性
            if (!validateDataCompleteness(applicationId)) {
                inconsistencies.add("融资申请数据不完整");
            }
            
            if (inconsistencies.isEmpty()) {
                check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_PASS);
                check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
                log.info("融资申请数据一致性验证通过: applicationId={}", applicationId);
            } else {
                check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_FAIL);
                check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
                String details = String.join("; ", inconsistencies);
                check.setInconsistencyDetails(details);
                
                // 创建数据异常风险事件
                recordDataAnomaly("融资申请数据不一致: " + details);
                log.warn("融资申请数据一致性验证失败: applicationId={}, details={}", applicationId, details);
            }
            
            dataConsistencyCheckMapper.insertDataConsistencyCheck(check);
            
        } catch (Exception e) {
            log.error("融资申请数据一致性验证异常", e);
            check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_FAIL);
            check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
            check.setInconsistencyDetails("验证过程中发生异常: " + e.getMessage());
            dataConsistencyCheckMapper.insertDataConsistencyCheck(check);
        }
        
        return check;
    }

    /**
     * 生成风险评估报告
     */
    @Override
    public String generateRiskAssessmentReport(Long applicationId)
    {
        log.info("开始生成风险评估报告: applicationId={}", applicationId);
        
        StringBuilder report = new StringBuilder();
        report.append("=== 风险评估报告 ===\n");
        report.append("申请ID: ").append(applicationId).append("\n");
        report.append("评估时间: ").append(DateUtils.getTime()).append("\n");
        report.append("评估人: ").append(SecurityUtils.getUsername()).append("\n\n");
        
        try {
            // 1. 分析历史风险事件
            report.append("1. 历史风险事件分析\n");
            List<RiskEvent> historicalEvents = getHistoricalRiskEvents(applicationId);
            if (historicalEvents.isEmpty()) {
                report.append("   - 无历史风险事件记录\n");
            } else {
                report.append("   - 发现 ").append(historicalEvents.size()).append(" 个历史风险事件\n");
                for (RiskEvent event : historicalEvents) {
                    report.append("     * ").append(event.getEventType())
                           .append(" (").append(event.getRiskLevel()).append("): ")
                           .append(event.getEventDescription()).append("\n");
                }
            }
            report.append("\n");
            
            // 2. 评估数据一致性检查结果
            report.append("2. 数据一致性检查结果\n");
            List<DataConsistencyCheck> consistencyChecks = getRelatedConsistencyChecks(applicationId);
            int passCount = 0;
            int failCount = 0;
            for (DataConsistencyCheck check : consistencyChecks) {
                if (DataConsistencyCheck.CHECK_RESULT_PASS.equals(check.getCheckResult())) {
                    passCount++;
                } else {
                    failCount++;
                    report.append("   - 失败: ").append(check.getCheckType())
                           .append(" - ").append(check.getInconsistencyDetails()).append("\n");
                }
            }
            report.append("   - 通过检查: ").append(passCount).append(" 项\n");
            report.append("   - 失败检查: ").append(failCount).append(" 项\n\n");
            
            // 3. 计算风险评分
            report.append("3. 风险评分计算\n");
            int riskScore = calculateRiskScore(historicalEvents, consistencyChecks);
            String riskLevel = getRiskLevelByScore(riskScore);
            report.append("   - 风险评分: ").append(riskScore).append("/100\n");
            report.append("   - 风险等级: ").append(riskLevel).append("\n\n");
            
            // 4. 提供风险建议
            report.append("4. 风险建议\n");
            List<String> recommendations = generateRiskRecommendations(riskScore, failCount, historicalEvents);
            for (String recommendation : recommendations) {
                report.append("   - ").append(recommendation).append("\n");
            }
            report.append("\n");
            
            // 5. 结论
            report.append("5. 评估结论\n");
            if (riskScore <= 30) {
                report.append("   建议批准融资申请，风险可控\n");
            } else if (riskScore <= 60) {
                report.append("   建议谨慎审批，需要额外风险控制措施\n");
            } else {
                report.append("   建议拒绝融资申请，风险过高\n");
            }
            
        } catch (Exception e) {
            log.error("生成风险评估报告异常", e);
            report.append("风险评估异常: ").append(e.getMessage()).append("\n");
        }
        
        return report.toString();
    }

    /**
     * 记录数据异常
     */
    @Override
    @Transactional
    public RiskEvent recordDataAnomaly(String anomalyInfo)
    {
        log.info("记录数据异常: anomalyInfo={}", anomalyInfo);
        
        RiskEvent riskEvent = new RiskEvent();
        riskEvent.setEventNumber(generateEventNumber());
        riskEvent.setEventType(RiskEvent.EVENT_TYPE_DATA_ANOMALY);
        riskEvent.setRiskLevel(RiskEvent.RISK_LEVEL_MEDIUM);
        riskEvent.setEventSource("SYSTEM");
        riskEvent.setEntityType("DATA_ANOMALY");
        riskEvent.setEventDescription("检测到数据异常");
        riskEvent.setAnomalyDetails(anomalyInfo);
        riskEvent.setEventStatus(RiskEvent.EVENT_STATUS_OPEN);
        riskEvent.setDetectedTime(DateUtils.getNowDate());
        
        riskEventMapper.insertRiskEvent(riskEvent);
        
        // 创建跟踪记录
        createRiskEventTracking(riskEvent.getEventId());
        
        log.info("数据异常记录完成: eventId={}", riskEvent.getEventId());
        return riskEvent;
    }

    /**
     * 建立风险事件跟踪
     */
    @Override
    @Transactional
    public RiskEventTracking createRiskEventTracking(Long riskEventId)
    {
        log.info("建立风险事件跟踪: riskEventId={}", riskEventId);
        
        RiskEventTracking tracking = new RiskEventTracking();
        tracking.setEventId(riskEventId);
        tracking.setTrackingStatus(RiskEventTracking.TRACKING_STATUS_PENDING);
        tracking.setActionTaken("风险事件已创建，等待处理");
        tracking.setActionTime(DateUtils.getNowDate());
        tracking.setActionBy(SecurityUtils.getUsername());
        tracking.setNextAction("分析风险事件并制定处理方案");
        
        riskEventTrackingMapper.insertRiskEventTracking(tracking);
        
        log.info("风险事件跟踪创建完成: trackingId={}", tracking.getTrackingId());
        return tracking;
    }

    /**
     * 按用户角色发送风险提示
     */
    @Override
    public boolean sendRiskAlert(RiskEvent riskEvent, String userRole)
    {
        log.info("发送风险提示: eventId={}, userRole={}", riskEvent.getEventId(), userRole);
        
        try {
            String alertMessage = buildAlertMessage(riskEvent, userRole);
            String alertLevel = mapRiskLevelToAlertLevel(riskEvent.getRiskLevel());
            
            // 根据用户角色确定通知渠道和接收者
            List<String> recipients = getRecipientsByRole(userRole);
            boolean allSent = true;
            
            for (String recipient : recipients) {
                // TODO: 集成通知服务发送系统通知
                // 当通知模块可用时，取消注释以下代码：
                // boolean systemNotificationSent = notificationService.sendSystemAlert(
                //     riskEvent.getEventType(), 
                //     alertLevel, 
                //     alertMessage, 
                //     "RISK_EVENT", 
                //     riskEvent.getEventId().toString()
                // );
                
                // 暂时记录日志作为通知发送的替代
                log.info("风险提示发送: recipient={}, eventType={}, level={}, message={}", 
                        recipient, riskEvent.getEventType(), alertLevel, alertMessage);
                boolean systemNotificationSent = true; // 暂时设为true
                
                if (!systemNotificationSent) {
                    allSent = false;
                    log.warn("系统通知发送失败: recipient={}, eventId={}", recipient, riskEvent.getEventId());
                }
                
                // 根据风险级别决定是否发送额外通知
                if (RiskEvent.RISK_LEVEL_HIGH.equals(riskEvent.getRiskLevel())) {
                    // 高风险事件发送邮件和短信
                    sendHighRiskAlert(riskEvent, recipient, alertMessage);
                }
            }
            
            // 记录风险提示发送日志
            logRiskAlertSent(riskEvent, userRole, allSent);
            
            return allSent;
            
        } catch (Exception e) {
            log.error("发送风险提示异常", e);
            return false;
        }
    }

    /**
     * 数据修正后重新验证
     */
    @Override
    @Transactional
    public DataConsistencyCheck revalidateAfterCorrection(Long dataId, String correctionInfo)
    {
        log.info("数据修正后重新验证: dataId={}, correctionInfo={}", dataId, correctionInfo);
        
        DataConsistencyCheck check = new DataConsistencyCheck();
        check.setCheckType("REVALIDATION");
        check.setSourceEntityId(dataId);
        check.setCheckTime(DateUtils.getNowDate());
        check.setCheckedBy(SecurityUtils.getUsername());
        check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_PENDING);
        
        try {
            // TODO: 实现具体的重新验证逻辑
            // 根据修正信息重新执行相关的一致性检查
            
            check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_PASS);
            check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
            check.setInconsistencyDetails("数据修正后验证通过: " + correctionInfo);
            
            dataConsistencyCheckMapper.insertDataConsistencyCheck(check);
            
            log.info("重新验证完成: checkId={}", check.getCheckId());
            
        } catch (Exception e) {
            log.error("重新验证异常", e);
            check.setCheckResult(DataConsistencyCheck.CHECK_RESULT_FAIL);
            check.setCheckStatus(DataConsistencyCheck.CHECK_STATUS_COMPLETED);
            check.setInconsistencyDetails("重新验证过程中发生异常: " + e.getMessage());
            dataConsistencyCheckMapper.insertDataConsistencyCheck(check);
        }
        
        return check;
    }

    /**
     * 更新风险状态
     */
    @Override
    @Transactional
    public boolean updateRiskStatus(Long riskEventId, String newStatus)
    {
        log.info("更新风险状态: riskEventId={}, newStatus={}", riskEventId, newStatus);
        
        try {
            RiskEvent riskEvent = riskEventMapper.selectRiskEventByEventId(riskEventId);
            if (riskEvent != null) {
                String oldStatus = riskEvent.getEventStatus();
                riskEvent.setEventStatus(newStatus);
                
                if (RiskEvent.EVENT_STATUS_RESOLVED.equals(newStatus) || RiskEvent.EVENT_STATUS_CLOSED.equals(newStatus)) {
                    riskEvent.setResolvedTime(DateUtils.getNowDate());
                    riskEvent.setHandledBy(SecurityUtils.getUsername());
                }
                
                int result = riskEventMapper.updateRiskEvent(riskEvent);
                
                // 创建状态变更跟踪记录
                RiskEventTracking tracking = new RiskEventTracking();
                tracking.setEventId(riskEventId);
                tracking.setTrackingStatus(RiskEventTracking.TRACKING_STATUS_COMPLETED);
                tracking.setActionTaken("风险状态从 " + oldStatus + " 更新为 " + newStatus);
                tracking.setActionResult("状态更新成功");
                tracking.setActionTime(DateUtils.getNowDate());
                tracking.setActionBy(SecurityUtils.getUsername());
                
                // 根据新状态设置下一步行动
                if (RiskEvent.EVENT_STATUS_RESOLVED.equals(newStatus)) {
                    tracking.setNextAction("验证风险解决效果");
                } else if (RiskEvent.EVENT_STATUS_CLOSED.equals(newStatus)) {
                    tracking.setNextAction("归档风险事件");
                } else {
                    tracking.setNextAction("继续监控风险状态");
                }
                
                riskEventTrackingMapper.insertRiskEventTracking(tracking);
                
                // 发送状态变更通知
                sendStatusChangeNotification(riskEvent, oldStatus, newStatus);
                
                log.info("风险状态更新完成: result={}", result);
                return result > 0;
            } else {
                log.warn("风险事件不存在: riskEventId={}", riskEventId);
                return false;
            }
            
        } catch (Exception e) {
            log.error("更新风险状态异常", e);
            return false;
        }
    }

    /**
     * 查询风险事件列表
     */
    @Override
    public List<RiskEvent> selectRiskEventList(RiskEvent riskEvent)
    {
        return riskEventMapper.selectRiskEventList(riskEvent);
    }

    /**
     * 查询风险事件跟踪列表
     */
    @Override
    public List<RiskEventTracking> selectRiskEventTrackingList(Long eventId)
    {
        return riskEventTrackingMapper.selectRiskEventTrackingByEventId(eventId);
    }

    /**
     * 查询数据一致性检查记录列表
     */
    @Override
    public List<DataConsistencyCheck> selectDataConsistencyCheckList(DataConsistencyCheck dataConsistencyCheck)
    {
        return dataConsistencyCheckMapper.selectDataConsistencyCheckList(dataConsistencyCheck);
    }

    // 私有辅助方法

    /**
     * 验证债权凭证有效性
     */
    private boolean validateCreditCertificateValidity(Long applicationId)
    {
        // TODO: 实现债权凭证有效性验证逻辑
        // 1. 检查债权凭证是否存在
        // 2. 检查债权凭证是否已过期
        // 3. 检查债权凭证状态是否有效
        log.debug("验证债权凭证有效性: applicationId={}", applicationId);
        return true; // 暂时返回true，实际需要实现具体逻辑
    }

    /**
     * 验证申请金额合理性
     */
    private boolean validateApplicationAmountReasonableness(Long applicationId)
    {
        // TODO: 实现申请金额合理性验证逻辑
        // 1. 获取申请金额和债权金额
        // 2. 检查申请金额是否超出债权金额
        // 3. 检查申请金额是否符合最小/最大限制
        log.debug("验证申请金额合理性: applicationId={}", applicationId);
        return true; // 暂时返回true，实际需要实现具体逻辑
    }

    /**
     * 验证相关合同状态
     */
    private boolean validateRelatedContractStatus(Long applicationId)
    {
        // TODO: 实现合同状态验证逻辑
        // 1. 获取关联的合同信息
        // 2. 检查合同状态是否符合融资条件
        // 3. 检查合同是否已确认
        log.debug("验证相关合同状态: applicationId={}", applicationId);
        return true; // 暂时返回true，实际需要实现具体逻辑
    }

    /**
     * 验证申请人权限
     */
    private boolean validateApplicantPermissions(Long applicationId)
    {
        // TODO: 实现申请人权限验证逻辑
        // 1. 获取申请人信息
        // 2. 检查申请人是否有权对该债权申请融资
        // 3. 检查申请人的身份和权限
        log.debug("验证申请人权限: applicationId={}", applicationId);
        return true; // 暂时返回true，实际需要实现具体逻辑
    }

    /**
     * 验证历史风险记录
     */
    private boolean validateHistoricalRiskRecord(Long applicationId)
    {
        // TODO: 实现历史风险记录验证逻辑
        // 1. 查询申请人的历史风险事件
        // 2. 检查是否存在未解决的高风险事件
        // 3. 评估历史风险对当前申请的影响
        log.debug("验证历史风险记录: applicationId={}", applicationId);
        return true; // 暂时返回true，实际需要实现具体逻辑
    }

    /**
     * 验证数据完整性
     */
    private boolean validateDataCompleteness(Long applicationId)
    {
        // TODO: 实现数据完整性验证逻辑
        // 1. 检查融资申请的必填字段
        // 2. 检查关联数据的完整性
        // 3. 验证数据格式和有效性
        log.debug("验证数据完整性: applicationId={}", applicationId);
        return true; // 暂时返回true，实际需要实现具体逻辑
    }

    /**
     * 获取历史风险事件
     */
    private List<RiskEvent> getHistoricalRiskEvents(Long applicationId)
    {
        // TODO: 实现获取历史风险事件逻辑
        // 根据申请ID或申请人获取相关的历史风险事件
        log.debug("获取历史风险事件: applicationId={}", applicationId);
        return new ArrayList<>(); // 暂时返回空列表
    }

    /**
     * 获取相关的一致性检查记录
     */
    private List<DataConsistencyCheck> getRelatedConsistencyChecks(Long applicationId)
    {
        // TODO: 实现获取相关一致性检查记录逻辑
        // 根据申请ID获取相关的数据一致性检查记录
        log.debug("获取相关一致性检查记录: applicationId={}", applicationId);
        return new ArrayList<>(); // 暂时返回空列表
    }

    /**
     * 计算风险评分
     */
    private int calculateRiskScore(List<RiskEvent> historicalEvents, List<DataConsistencyCheck> consistencyChecks)
    {
        int score = 0;
        
        // 基于历史风险事件计算分数
        for (RiskEvent event : historicalEvents) {
            switch (event.getRiskLevel()) {
                case RiskEvent.RISK_LEVEL_HIGH:
                    score += 30;
                    break;
                case RiskEvent.RISK_LEVEL_MEDIUM:
                    score += 15;
                    break;
                case RiskEvent.RISK_LEVEL_LOW:
                    score += 5;
                    break;
            }
        }
        
        // 基于一致性检查失败计算分数
        for (DataConsistencyCheck check : consistencyChecks) {
            if (DataConsistencyCheck.CHECK_RESULT_FAIL.equals(check.getCheckResult())) {
                score += 10;
            }
        }
        
        return Math.min(score, 100); // 最高100分
    }

    /**
     * 根据评分获取风险等级
     */
    private String getRiskLevelByScore(int score)
    {
        if (score <= 30) {
            return "低风险";
        } else if (score <= 60) {
            return "中风险";
        } else {
            return "高风险";
        }
    }

    /**
     * 生成风险建议
     */
    private List<String> generateRiskRecommendations(int riskScore, int failCount, List<RiskEvent> historicalEvents)
    {
        List<String> recommendations = new ArrayList<>();
        
        if (riskScore <= 30) {
            recommendations.add("风险可控，建议正常审批");
            recommendations.add("建议定期监控债权状态");
        } else if (riskScore <= 60) {
            recommendations.add("存在一定风险，建议谨慎审批");
            recommendations.add("建议增加担保措施或降低融资金额");
            recommendations.add("建议加强贷后管理和监控");
        } else {
            recommendations.add("风险较高，建议拒绝申请或要求整改");
            recommendations.add("建议申请人先解决现有风险问题");
            recommendations.add("建议等待风险缓解后重新申请");
        }
        
        if (failCount > 0) {
            recommendations.add("建议申请人修正数据不一致问题");
        }
        
        if (!historicalEvents.isEmpty()) {
            recommendations.add("建议关注申请人的历史风险处理情况");
        }
        
        return recommendations;
    }

    /**
     * 将风险级别映射为告警级别
     */
    private String mapRiskLevelToAlertLevel(String riskLevel)
    {
        switch (riskLevel) {
            case RiskEvent.RISK_LEVEL_HIGH:
                return "CRITICAL";
            case RiskEvent.RISK_LEVEL_MEDIUM:
                return "WARNING";
            case RiskEvent.RISK_LEVEL_LOW:
                return "INFO";
            default:
                return "INFO";
        }
    }

    /**
     * 根据用户角色获取接收者列表
     */
    private List<String> getRecipientsByRole(String userRole)
    {
        List<String> recipients = new ArrayList<>();
        
        switch (userRole) {
            case "SECURITY_COMPANY":
                // TODO: 获取安保公司用户列表
                recipients.add("security_company_admin");
                break;
            case "BANK":
                // TODO: 获取银行用户列表
                recipients.add("bank_risk_manager");
                recipients.add("bank_admin");
                break;
            case "ADMIN":
                // TODO: 获取平台管理员列表
                recipients.add("platform_admin");
                recipients.add("risk_manager");
                break;
            default:
                recipients.add("default_admin");
                break;
        }
        
        return recipients;
    }

    /**
     * 发送高风险告警
     */
    private void sendHighRiskAlert(RiskEvent riskEvent, String recipient, String alertMessage)
    {
        try {
            // TODO: 实现高风险告警的多渠道发送
            // 1. 发送邮件通知
            // 2. 发送短信通知
            // 3. 发送微信通知等
            log.info("发送高风险告警: recipient={}, eventId={}", recipient, riskEvent.getEventId());
        } catch (Exception e) {
            log.error("发送高风险告警异常", e);
        }
    }

    /**
     * 记录风险提示发送日志
     */
    private void logRiskAlertSent(RiskEvent riskEvent, String userRole, boolean success)
    {
        try {
            // 创建跟踪记录
            RiskEventTracking tracking = new RiskEventTracking();
            tracking.setEventId(riskEvent.getEventId());
            tracking.setTrackingStatus(success ? RiskEventTracking.TRACKING_STATUS_COMPLETED : RiskEventTracking.TRACKING_STATUS_PENDING);
            tracking.setActionTaken("向 " + userRole + " 角色发送风险提示");
            tracking.setActionResult(success ? "发送成功" : "发送失败");
            tracking.setActionTime(DateUtils.getNowDate());
            tracking.setActionBy("SYSTEM");
            
            if (!success) {
                tracking.setNextAction("重试发送风险提示");
            }
            
            riskEventTrackingMapper.insertRiskEventTracking(tracking);
            
        } catch (Exception e) {
            log.error("记录风险提示发送日志异常", e);
        }
    }

    /**
     * 发送状态变更通知
     */
    private void sendStatusChangeNotification(RiskEvent riskEvent, String oldStatus, String newStatus)
    {
        try {
            String message = String.format("风险事件 %s 状态已从 %s 变更为 %s", 
                                         riskEvent.getEventNumber(), oldStatus, newStatus);
            
            // TODO: 集成通知服务发送系统通知
            // 当通知模块可用时，取消注释以下代码：
            // notificationService.sendSystemAlert(
            //     "RISK_STATUS_CHANGE", 
            //     "INFO", 
            //     message, 
            //     "RISK_EVENT", 
            //     riskEvent.getEventId().toString()
            // );
            
            // 暂时记录日志作为通知发送的替代
            log.info("风险状态变更通知: eventId={}, oldStatus={}, newStatus={}, message={}", 
                    riskEvent.getEventId(), oldStatus, newStatus, message);
            
        } catch (Exception e) {
            log.error("发送状态变更通知异常", e);
        }
    }

    /**
     * 获取合同金额
     */
    private BigDecimal getContractAmount(Long contractId)
    {
        // TODO: 从合同表中获取实际金额
        // 这里返回模拟数据
        return new BigDecimal("100000.00");
    }

    /**
     * 获取服务确认单金额
     */
    private BigDecimal getServiceConfirmationAmount(Long serviceConfirmationId)
    {
        // TODO: 从服务确认单表中获取实际金额
        // 这里返回模拟数据
        return new BigDecimal("100000.00");
    }

    /**
     * 获取发票金额
     */
    private BigDecimal getInvoiceAmount(Long invoiceId)
    {
        // TODO: 从发票表中获取实际金额
        // 这里返回模拟数据
        return new BigDecimal("100000.00");
    }

    /**
     * 获取合同服务期限
     */
    private String getContractServicePeriod(Long contractId)
    {
        // TODO: 从合同表中获取实际服务期限
        // 这里返回模拟数据
        return "2025-01-01 to 2025-12-31";
    }

    /**
     * 创建合同金额不一致风险事件
     */
    private void createRiskEventForAmountInconsistency(Long contractId, Long serviceConfirmationId, 
                                                      BigDecimal contractAmount, BigDecimal confirmationAmount)
    {
        RiskEvent riskEvent = new RiskEvent();
        riskEvent.setEventNumber(generateEventNumber());
        riskEvent.setEventType(RiskEvent.EVENT_TYPE_AMOUNT_INCONSISTENCY);
        riskEvent.setRiskLevel(RiskEvent.RISK_LEVEL_HIGH);
        riskEvent.setEventSource("SYSTEM");
        riskEvent.setRelatedEntityId(contractId);
        riskEvent.setEntityType("CONTRACT");
        riskEvent.setEventDescription("合同金额与服务确认单金额不一致");
        riskEvent.setAnomalyDetails(String.format("合同ID: %d, 服务确认单ID: %d, 合同金额: %s, 确认单金额: %s", 
                                                  contractId, serviceConfirmationId, contractAmount, confirmationAmount));
        riskEvent.setEventStatus(RiskEvent.EVENT_STATUS_OPEN);
        riskEvent.setDetectedTime(DateUtils.getNowDate());
        
        riskEventMapper.insertRiskEvent(riskEvent);
        
        // 发送风险提示给安保公司用户
        sendRiskAlert(riskEvent, "SECURITY_COMPANY");
    }

    /**
     * 创建发票金额不一致风险事件
     */
    private void createRiskEventForInvoiceInconsistency(Long serviceConfirmationId, Long invoiceId,
                                                       BigDecimal confirmationAmount, BigDecimal invoiceAmount)
    {
        RiskEvent riskEvent = new RiskEvent();
        riskEvent.setEventNumber(generateEventNumber());
        riskEvent.setEventType(RiskEvent.EVENT_TYPE_AMOUNT_INCONSISTENCY);
        riskEvent.setRiskLevel(RiskEvent.RISK_LEVEL_HIGH);
        riskEvent.setEventSource("SYSTEM");
        riskEvent.setRelatedEntityId(serviceConfirmationId);
        riskEvent.setEntityType("SERVICE_CONFIRMATION");
        riskEvent.setEventDescription("服务确认单金额与发票金额不一致");
        riskEvent.setAnomalyDetails(String.format("服务确认单ID: %d, 发票ID: %d, 确认单金额: %s, 发票金额: %s", 
                                                  serviceConfirmationId, invoiceId, confirmationAmount, invoiceAmount));
        riskEvent.setEventStatus(RiskEvent.EVENT_STATUS_OPEN);
        riskEvent.setDetectedTime(DateUtils.getNowDate());
        
        riskEventMapper.insertRiskEvent(riskEvent);
        
        // 发送风险提示给银行和平台管理员
        sendRiskAlert(riskEvent, "BANK");
        sendRiskAlert(riskEvent, "ADMIN");
    }

    /**
     * 创建主体信息不匹配风险事件
     */
    private void createRiskEventForPartyMismatch(String invoiceParty, String contractParty)
    {
        RiskEvent riskEvent = new RiskEvent();
        riskEvent.setEventNumber(generateEventNumber());
        riskEvent.setEventType(RiskEvent.EVENT_TYPE_PARTY_MISMATCH);
        riskEvent.setRiskLevel(RiskEvent.RISK_LEVEL_HIGH);
        riskEvent.setEventSource("SYSTEM");
        riskEvent.setEntityType("PARTY_INFO");
        riskEvent.setEventDescription("开票方与收票方主体信息不匹配");
        riskEvent.setAnomalyDetails(String.format("开票方: %s, 收票方: %s", invoiceParty, contractParty));
        riskEvent.setEventStatus(RiskEvent.EVENT_STATUS_OPEN);
        riskEvent.setDetectedTime(DateUtils.getNowDate());
        
        riskEventMapper.insertRiskEvent(riskEvent);
        
        // 发送阻断性风险提示
        sendRiskAlert(riskEvent, "ADMIN");
    }

    /**
     * 创建服务期限不一致风险事件
     */
    private void createRiskEventForPeriodInconsistency(Long contractId, String contractPeriod, String actualPeriod)
    {
        RiskEvent riskEvent = new RiskEvent();
        riskEvent.setEventNumber(generateEventNumber());
        riskEvent.setEventType(RiskEvent.EVENT_TYPE_PERIOD_INCONSISTENCY);
        riskEvent.setRiskLevel(RiskEvent.RISK_LEVEL_MEDIUM);
        riskEvent.setEventSource("SYSTEM");
        riskEvent.setRelatedEntityId(contractId);
        riskEvent.setEntityType("CONTRACT");
        riskEvent.setEventDescription("服务期限与实际服务周期不一致");
        riskEvent.setAnomalyDetails(String.format("合同ID: %d, 合同期限: %s, 实际周期: %s", contractId, contractPeriod, actualPeriod));
        riskEvent.setEventStatus(RiskEvent.EVENT_STATUS_OPEN);
        riskEvent.setDetectedTime(DateUtils.getNowDate());
        
        riskEventMapper.insertRiskEvent(riskEvent);
        
        // 发送提醒性风险提示
        sendRiskAlert(riskEvent, "SECURITY_COMPANY");
    }

    /**
     * 生成事件编号
     */
    private String generateEventNumber()
    {
        return "RISK" + System.currentTimeMillis();
    }

    /**
     * 构建风险提示消息
     */
    private String buildAlertMessage(RiskEvent riskEvent, String userRole)
    {
        StringBuilder message = new StringBuilder();
        message.append("风险提示 - ").append(riskEvent.getEventNumber()).append("\n");
        message.append("风险级别: ").append(riskEvent.getRiskLevel()).append("\n");
        message.append("事件类型: ").append(riskEvent.getEventType()).append("\n");
        message.append("事件描述: ").append(riskEvent.getEventDescription()).append("\n");
        message.append("检测时间: ").append(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, riskEvent.getDetectedTime())).append("\n");
        
        // 根据用户角色添加特定的处理建议
        switch (userRole) {
            case "SECURITY_COMPANY":
                message.append("建议: 请及时核实相关数据并进行必要的修正\n");
                break;
            case "BANK":
                message.append("建议: 请暂停相关融资审批，等待数据修正后重新评估\n");
                break;
            case "ADMIN":
                message.append("建议: 请立即介入处理，确保数据一致性\n");
                break;
            default:
                message.append("建议: 请关注风险事件进展\n");
                break;
        }
        
        return message.toString();
    }
}