package com.ruoyi.credit.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

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.credit.domain.*;
import com.ruoyi.credit.mapper.*;
import com.ruoyi.credit.service.IServicePeriodLoanService;
import com.ruoyi.credit.service.IBankInstitutionService;
import com.ruoyi.notification.service.INotificationService;
import com.ruoyi.notification.domain.NotificationMessage;
import com.ruoyi.framework.security.validator.DepartmentPermissionValidator;

/**
 * 服务周期贷款管理服务实现
 * 
 * @author ruoyi
 * @date 2025-12-24
 */
@Service
public class ServicePeriodLoanServiceImpl implements IServicePeriodLoanService
{
    private static final Logger log = LoggerFactory.getLogger(ServicePeriodLoanServiceImpl.class);

    @Autowired
    private ServicePeriodLoanMapper servicePeriodLoanMapper;

    @Autowired
    private ServicePeriodMapper servicePeriodMapper;

    @Autowired
    private ServicePeriodEmployeeMapper servicePeriodEmployeeMapper;

    @Autowired
    private ServiceContractMapper serviceContractMapper;

    @Autowired
    private INotificationService notificationService;

    @Autowired
    private IBankInstitutionService bankInstitutionService;

    @Autowired
    private FinancingServiceImpl financingService;

    @Autowired
    private DepartmentPermissionValidator departmentPermissionValidator;

    // ==================== 基础CRUD操作 ====================

    @Override
    public ServicePeriodLoan selectServicePeriodLoanByLinkId(Long linkId)
    {
        return servicePeriodLoanMapper.selectServicePeriodLoanByLinkId(linkId);
    }

    @Override
    public List<ServicePeriodLoan> selectServicePeriodLoanList(ServicePeriodLoan servicePeriodLoan)
    {
        return servicePeriodLoanMapper.selectServicePeriodLoanList(servicePeriodLoan);
    }

    @Override
    public List<ServicePeriodLoan> selectServicePeriodLoansByPeriodId(Long servicePeriodId)
    {
        return servicePeriodLoanMapper.selectServicePeriodLoansByPeriodId(servicePeriodId);
    }

    @Override
    @Transactional
    public int insertServicePeriodLoan(ServicePeriodLoan servicePeriodLoan)
    {
        // 验证数据创建权限并自动设置部门ID
        departmentPermissionValidator.validateDataCreation(servicePeriodLoan);

        // 验证服务周期与合同的部门一致性（如果有关联合同）
        if (servicePeriodLoan.getServicePeriodId() != null) {
            ServicePeriod servicePeriod = servicePeriodMapper.selectServicePeriodByServicePeriodId(servicePeriodLoan.getServicePeriodId());
            if (servicePeriod != null && servicePeriod.getContractId() != null) {
                departmentPermissionValidator.validateServicePeriodContractConsistency(
                    servicePeriod.getContractId(), servicePeriodLoan.getServicePeriodId());
            }
        }

        // 生成贷款编号
        if (StringUtils.isEmpty(servicePeriodLoan.getLoanNumber())) {
            String loanNumber = generateLoanNumber(servicePeriodLoan.getServicePeriodId());
            servicePeriodLoan.setLoanNumber(loanNumber);
        }

        // 设置默认状态
        if (StringUtils.isEmpty(servicePeriodLoan.getLoanStatus())) {
            servicePeriodLoan.setLoanStatus(ServicePeriodLoan.STATUS_PENDING);
        }
        if (StringUtils.isEmpty(servicePeriodLoan.getApprovalStatus())) {
            servicePeriodLoan.setApprovalStatus(ServicePeriodLoan.APPROVAL_PENDING);
        }

        servicePeriodLoan.setCreateTime(DateUtils.getNowDate());
        
        int result = servicePeriodLoanMapper.insertServicePeriodLoan(servicePeriodLoan);
        
        // 自动创建融资申请记录
        if (result > 0) {
            try {
                Map<String, Object> financingResult = financingService.createFinancingApplicationFromLoan(servicePeriodLoan);
                if ((Boolean) financingResult.get("success")) {
                    log.info("自动创建融资申请成功: loanId={}, financingId={}", 
                            servicePeriodLoan.getLinkId(), financingResult.get("financingId"));
                } else {
                    log.warn("自动创建融资申请失败: loanId={}, message={}", 
                            servicePeriodLoan.getLinkId(), financingResult.get("message"));
                }
            } catch (Exception e) {
                log.error("自动创建融资申请异常: loanId={}", servicePeriodLoan.getLinkId(), e);
            }
        }
        
        // 记录数据变更审计
        recordServicePeriodDataChange(servicePeriodLoan.getServicePeriodId(), "LOAN_ADDED", 
                                    null, servicePeriodLoan, "新增贷款信息");
        
        return result;
    }

    @Override
    @Transactional
    public int updateServicePeriodLoan(ServicePeriodLoan servicePeriodLoan)
    {
        // 验证用户对该贷款记录的访问权限
        departmentPermissionValidator.validateDataAccess(servicePeriodLoan.getLinkId(), "dc_service_period_loan");

        // 获取原始数据用于审计
        ServicePeriodLoan oldLoan = servicePeriodLoanMapper.selectServicePeriodLoanByLinkId(servicePeriodLoan.getLinkId());
        
        servicePeriodLoan.setUpdateTime(DateUtils.getNowDate());
        int result = servicePeriodLoanMapper.updateServicePeriodLoan(servicePeriodLoan);
        
        // 同步更新融资申请记录
        if (result > 0) {
            try {
                Map<String, Object> syncResult = financingService.syncLoanDataToFinancing(servicePeriodLoan);
                if ((Boolean) syncResult.get("success")) {
                    log.info("同步融资申请成功: loanId={}, updated={}", 
                            servicePeriodLoan.getLinkId(), syncResult.get("updated"));
                } else {
                    log.warn("同步融资申请失败: loanId={}, message={}", 
                            servicePeriodLoan.getLinkId(), syncResult.get("message"));
                }
            } catch (Exception e) {
                log.error("同步融资申请异常: loanId={}", servicePeriodLoan.getLinkId(), e);
            }
        }
        
        // 记录数据变更审计
        if (oldLoan != null) {
            recordServicePeriodDataChange(servicePeriodLoan.getServicePeriodId(), "LOAN_UPDATED", 
                                        oldLoan, servicePeriodLoan, "更新贷款信息");
        }
        
        return result;
    }

    @Override
    @Transactional
    public int deleteServicePeriodLoanByLinkIds(Long[] linkIds)
    {
        // 记录删除的贷款信息用于审计
        for (Long linkId : linkIds) {
            ServicePeriodLoan loan = servicePeriodLoanMapper.selectServicePeriodLoanByLinkId(linkId);
            if (loan != null) {
                recordServicePeriodDataChange(loan.getServicePeriodId(), "LOAN_DELETED", 
                                            loan, null, "删除贷款信息");
            }
        }
        
        return servicePeriodLoanMapper.deleteServicePeriodLoanByLinkIds(linkIds);
    }

    @Override
    @Transactional
    public int deleteServicePeriodLoanByLinkId(Long linkId)
    {
        ServicePeriodLoan loan = servicePeriodLoanMapper.selectServicePeriodLoanByLinkId(linkId);
        int result = servicePeriodLoanMapper.deleteServicePeriodLoanByLinkId(linkId);
        
        // 记录数据变更审计
        if (loan != null) {
            recordServicePeriodDataChange(loan.getServicePeriodId(), "LOAN_DELETED", 
                                        loan, null, "删除贷款信息");
        }
        
        return result;
    }

    // ==================== 贷款申请管理 ====================

    @Override
    @Transactional
    public Map<String, Object> applyLoanBasedOnAttendance(Long servicePeriodId, Map<String, Object> loanRequest)
    {
        log.info("根据出勤记录申请贷款: servicePeriodId={}", servicePeriodId);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 1. 验证服务周期存在
            ServicePeriod servicePeriod = servicePeriodMapper.selectServicePeriodByServicePeriodId(servicePeriodId);
            if (servicePeriod == null) {
                result.put("success", false);
                result.put("message", "服务周期不存在");
                return result;
            }

            // 验证用户对该服务周期的访问权限
            departmentPermissionValidator.validateDataAccess(servicePeriodId, "dc_service_period");

            // 2. 计算基于出勤数据的贷款金额
            Map<String, Object> calculationResult = calculateLoanAmountBasedOnAttendance(servicePeriodId);
            if (!(Boolean) calculationResult.get("success")) {
                return calculationResult;
            }

            BigDecimal calculatedAmount = (BigDecimal) calculationResult.get("calculatedAmount");
            BigDecimal requestedAmount = new BigDecimal(loanRequest.get("loanAmount").toString());

            // 3. 验证申请金额
            Map<String, Object> validationResult = validateLoanAmountCalculation(servicePeriodId, requestedAmount);
            if (!(Boolean) validationResult.get("valid")) {
                result.put("success", false);
                result.put("message", "申请金额验证失败: " + validationResult.get("message"));
                result.put("calculatedAmount", calculatedAmount);
                result.put("requestedAmount", requestedAmount);
                return result;
            }

            // 4. 获取合同信息用于期限匹配
            ServiceContract contract = serviceContractMapper.selectServiceContractByContractId(servicePeriod.getContractId());
            if (contract == null) {
                result.put("success", false);
                result.put("message", "关联合同不存在");
                return result;
            }

            // 计算合同期限（月）
            Integer contractTermMonths = calculateContractTermMonths(contract.getStartDate(), contract.getEndDate());

            // 5. 选择匹配的银行融资条件
            Map<String, Object> financingOptions = selectBankFinancingByContractTerm(servicePeriodId, contractTermMonths);

            // 6. 创建贷款申请记录
            ServicePeriodLoan loan = new ServicePeriodLoan();
            loan.setServicePeriodId(servicePeriodId);
            loan.setLoanAmount(requestedAmount);
            loan.setLoanPurpose((String) loanRequest.getOrDefault("loanPurpose", "服务周期人工成本融资"));
            loan.setLoanStatus(ServicePeriodLoan.STATUS_PENDING);
            loan.setApprovalStatus(ServicePeriodLoan.APPROVAL_PENDING);

            // 设置银行信息（优先使用前端传递的银行信息）
            if (loanRequest.containsKey("bankInstitutionId")) {
                loan.setBankInstitutionId(Long.valueOf(loanRequest.get("bankInstitutionId").toString()));
                loan.setBankInstitutionName((String) loanRequest.get("bankInstitutionName"));
                loan.setInterestRate(Double.valueOf(loanRequest.get("interestRate").toString()));
                loan.setContractTermMatch((String) loanRequest.get("contractTermMatch"));
                
                // 使用前端计算的月还款额
                if (loanRequest.containsKey("monthlyPayment")) {
                    loan.setMonthlyPayment(new BigDecimal(loanRequest.get("monthlyPayment").toString()));
                } else {
                    // 后端计算月还款额
                    BigDecimal monthlyPayment = calculateMonthlyPayment(requestedAmount, 
                                                                      loan.getInterestRate(), 
                                                                      loan.getLoanTermMonths());
                    loan.setMonthlyPayment(monthlyPayment);
                }
            } else if (financingOptions.containsKey("recommendedBank")) {
                // 使用推荐银行信息（原有逻辑）
                Map<String, Object> recommendedBank = (Map<String, Object>) financingOptions.get("recommendedBank");
                loan.setBankInstitutionId(Long.valueOf(recommendedBank.get("bankId").toString()));
                loan.setBankInstitutionName((String) recommendedBank.get("bankName"));
                loan.setInterestRate((Double) recommendedBank.get("interestRate"));
                loan.setLoanTermMonths((Integer) recommendedBank.get("termMonths"));
                loan.setContractTermMatch((String) recommendedBank.get("termMatch"));
                
                // 计算月还款额
                BigDecimal monthlyPayment = calculateMonthlyPayment(requestedAmount, 
                                                                  loan.getInterestRate(), 
                                                                  loan.getLoanTermMonths());
                loan.setMonthlyPayment(monthlyPayment);
            }

            // 设置贷款期限
            if (loanRequest.containsKey("loanTermMonths")) {
                loan.setLoanTermMonths(Integer.valueOf(loanRequest.get("loanTermMonths").toString()));
            }

            // 设置贷款日期
            loan.setLoanStartDate(DateUtils.getNowDate());
            if (loan.getLoanTermMonths() != null) {
                Calendar cal = Calendar.getInstance();
                cal.add(Calendar.MONTH, loan.getLoanTermMonths());
                loan.setLoanEndDate(cal.getTime());
            }

            // 保存贷款申请
            insertServicePeriodLoan(loan);

            result.put("success", true);
            result.put("message", "贷款申请提交成功");
            result.put("loanId", loan.getLinkId());
            result.put("loanNumber", loan.getLoanNumber());
            result.put("calculatedAmount", calculatedAmount);
            result.put("requestedAmount", requestedAmount);
            result.put("financingOptions", financingOptions);

            // 发送通知
            sendDataChangeNotification(servicePeriodId, "LOAN_APPLICATION_SUBMITTED", result);

            log.info("贷款申请成功: servicePeriodId={}, loanId={}, amount={}", 
                    servicePeriodId, loan.getLinkId(), requestedAmount);

        } catch (Exception e) {
            log.error("贷款申请失败: servicePeriodId={}", servicePeriodId, e);
            result.put("success", false);
            result.put("message", "贷款申请失败: " + e.getMessage());
        }

        return result;
    }

    @Override
    public Map<String, Object> calculateLoanAmountBasedOnAttendance(Long servicePeriodId)
    {
        log.info("计算基于出勤数据的贷款金额: servicePeriodId={}", servicePeriodId);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 获取服务周期信息
            ServicePeriod servicePeriod = servicePeriodMapper.selectServicePeriodByServicePeriodId(servicePeriodId);
            if (servicePeriod == null) {
                result.put("success", false);
                result.put("message", "服务周期不存在");
                return result;
            }

            // 获取出勤员工信息
            List<ServicePeriodEmployee> employees = servicePeriodEmployeeMapper.selectServicePeriodEmployeesByPeriodId(servicePeriodId);
            if (employees.isEmpty()) {
                result.put("success", false);
                result.put("message", "该服务周期没有出勤员工记录");
                return result;
            }

            // 计算总人工成本
            BigDecimal totalLaborCost = employees.stream()
                    .map(ServicePeriodEmployee::getTotalCost)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            // 根据贷款倍数计算贷款金额
            BigDecimal calculatedAmount;
            BigDecimal loanMultiplier = servicePeriod.getLoanMultiplier();
            
            if (loanMultiplier != null && loanMultiplier.compareTo(BigDecimal.ZERO) > 0) {
                calculatedAmount = totalLaborCost.multiply(loanMultiplier);
            } else {
                // 默认贷款金额等于人工成本
                calculatedAmount = totalLaborCost;
            }

            // 构建详细信息
            Map<String, Object> attendanceDetails = new HashMap<>();
            attendanceDetails.put("totalEmployees", employees.size());
            attendanceDetails.put("totalWorkDays", employees.stream().mapToInt(ServicePeriodEmployee::getWorkDays).sum());
            attendanceDetails.put("totalLaborCost", totalLaborCost);
            attendanceDetails.put("loanMultiplier", loanMultiplier);
            attendanceDetails.put("calculatedAmount", calculatedAmount);

            List<Map<String, Object>> employeeDetails = employees.stream().map(emp -> {
                Map<String, Object> detail = new HashMap<>();
                detail.put("employeeId", emp.getEmployeeId());
                detail.put("assignedPosition", emp.getAssignedPosition());
                detail.put("workDays", emp.getWorkDays());
                detail.put("assignedSalary", emp.getAssignedSalary());
                detail.put("totalCost", emp.getTotalCost());
                return detail;
            }).collect(Collectors.toList());

            result.put("success", true);
            result.put("calculatedAmount", calculatedAmount);
            result.put("attendanceDetails", attendanceDetails);
            result.put("employeeDetails", employeeDetails);

            log.info("贷款金额计算完成: servicePeriodId={}, totalLaborCost={}, multiplier={}, calculatedAmount={}", 
                    servicePeriodId, totalLaborCost, loanMultiplier, calculatedAmount);

        } catch (Exception e) {
            log.error("计算贷款金额失败: servicePeriodId={}", servicePeriodId, e);
            result.put("success", false);
            result.put("message", "计算失败: " + e.getMessage());
        }

        return result;
    }

    @Override
    public Map<String, Object> validateLoanAmountCalculation(Long servicePeriodId, BigDecimal requestedAmount)
    {
        log.info("验证贷款金额计算: servicePeriodId={}, requestedAmount={}", servicePeriodId, requestedAmount);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 计算基于出勤的标准金额
            Map<String, Object> calculationResult = calculateLoanAmountBasedOnAttendance(servicePeriodId);
            if (!(Boolean) calculationResult.get("success")) {
                result.put("valid", false);
                result.put("message", "无法计算标准贷款金额");
                return result;
            }

            BigDecimal calculatedAmount = (BigDecimal) calculationResult.get("calculatedAmount");
            
            // 设置允许的偏差范围（例如±20%）
            BigDecimal allowedVariancePercent = new BigDecimal("0.20");
            BigDecimal minAllowedAmount = calculatedAmount.multiply(BigDecimal.ONE.subtract(allowedVariancePercent));
            BigDecimal maxAllowedAmount = calculatedAmount.multiply(BigDecimal.ONE.add(allowedVariancePercent));

            boolean isValid = requestedAmount.compareTo(minAllowedAmount) >= 0 && 
                             requestedAmount.compareTo(maxAllowedAmount) <= 0;

            result.put("valid", isValid);
            result.put("calculatedAmount", calculatedAmount);
            result.put("requestedAmount", requestedAmount);
            result.put("minAllowedAmount", minAllowedAmount);
            result.put("maxAllowedAmount", maxAllowedAmount);
            result.put("allowedVariancePercent", allowedVariancePercent.multiply(new BigDecimal("100")));

            if (isValid) {
                result.put("message", "申请金额在允许范围内");
            } else {
                String message = String.format("申请金额超出允许范围。标准金额: %.2f, 允许范围: %.2f - %.2f", 
                                              calculatedAmount, minAllowedAmount, maxAllowedAmount);
                result.put("message", message);
            }

            log.info("贷款金额验证完成: servicePeriodId={}, valid={}, calculated={}, requested={}", 
                    servicePeriodId, isValid, calculatedAmount, requestedAmount);

        } catch (Exception e) {
            log.error("验证贷款金额失败: servicePeriodId={}", servicePeriodId, e);
            result.put("valid", false);
            result.put("message", "验证失败: " + e.getMessage());
        }

        return result;
    }

    // ==================== 银行融资条件匹配 ====================

    @Override
    public Map<String, Object> selectBankFinancingByContractTerm(Long servicePeriodId, Integer contractTermMonths)
    {
        log.info("根据合同期限选择银行融资条件: servicePeriodId={}, contractTermMonths={}", 
                servicePeriodId, contractTermMonths);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 从数据库获取银行融资产品数据
            List<Map<String, Object>> bankProducts = getBankProducts();
            
            // 根据合同期限匹配最佳融资方案
            List<Map<String, Object>> matchedProducts = new ArrayList<>();
            
            for (Map<String, Object> product : bankProducts) {
                Integer bankTermMonths = (Integer) product.get("termMonths");
                String matchLevel = matchContractTermWithBankTerm(contractTermMonths, bankTermMonths);
                
                Map<String, Object> matchedProduct = new HashMap<>(product);
                matchedProduct.put("termMatch", matchLevel);
                matchedProduct.put("contractTermMonths", contractTermMonths);
                
                // 只返回匹配度为GOOD或以上的产品
                if (!ServicePeriodLoan.MATCH_POOR.equals(matchLevel)) {
                    matchedProducts.add(matchedProduct);
                }
            }
            
            // 按匹配度和利率排序
            matchedProducts.sort((p1, p2) -> {
                String match1 = (String) p1.get("termMatch");
                String match2 = (String) p2.get("termMatch");
                Double rate1 = (Double) p1.get("interestRate");
                Double rate2 = (Double) p2.get("interestRate");
                
                // 先按匹配度排序
                int matchCompare = getMatchScore(match2) - getMatchScore(match1);
                if (matchCompare != 0) {
                    return matchCompare;
                }
                // 匹配度相同时按利率排序
                return rate1.compareTo(rate2);
            });
            
            result.put("success", true);
            result.put("contractTermMonths", contractTermMonths);
            result.put("matchedProducts", matchedProducts);
            
            if (!matchedProducts.isEmpty()) {
                result.put("recommendedBank", matchedProducts.get(0));
            }
            
            log.info("银行融资条件匹配完成: servicePeriodId={}, matchedCount={}", 
                    servicePeriodId, matchedProducts.size());

        } catch (Exception e) {
            log.error("选择银行融资条件失败: servicePeriodId={}", servicePeriodId, e);
            result.put("success", false);
            result.put("message", "匹配失败: " + e.getMessage());
        }

        return result;
    }

    @Override
    public String matchContractTermWithBankTerm(Integer contractTermMonths, Integer bankTermMonths)
    {
        if (contractTermMonths == null || bankTermMonths == null) {
            return ServicePeriodLoan.MATCH_POOR;
        }

        int difference = Math.abs(contractTermMonths - bankTermMonths);
        
        if (difference == 0) {
            return ServicePeriodLoan.MATCH_PERFECT;
        } else if (difference <= 1) {
            return ServicePeriodLoan.MATCH_GOOD;
        } else if (difference <= 3) {
            return ServicePeriodLoan.MATCH_ACCEPTABLE;
        } else {
            return ServicePeriodLoan.MATCH_POOR;
        }
    }

    @Override
    public List<Map<String, Object>> getRecommendedFinancingOptions(Long servicePeriodId, BigDecimal loanAmount, Integer termMonths)
    {
        log.info("获取推荐融资方案: servicePeriodId={}, loanAmount={}, termMonths={}", 
                servicePeriodId, loanAmount, termMonths);
        
        List<Map<String, Object>> options = new ArrayList<>();
        
        try {
            // 获取匹配的银行产品
            Map<String, Object> matchingResult = selectBankFinancingByContractTerm(servicePeriodId, termMonths);
            
            if ((Boolean) matchingResult.get("success")) {
                List<Map<String, Object>> matchedProducts = (List<Map<String, Object>>) matchingResult.get("matchedProducts");
                
                for (Map<String, Object> product : matchedProducts) {
                    Map<String, Object> option = new HashMap<>(product);
                    
                    // 计算月还款额
                    Double interestRate = (Double) product.get("interestRate");
                    Integer productTermMonths = (Integer) product.get("termMonths");
                    BigDecimal monthlyPayment = calculateMonthlyPayment(loanAmount, interestRate, productTermMonths);
                    
                    option.put("loanAmount", loanAmount);
                    option.put("monthlyPayment", monthlyPayment);
                    option.put("totalInterest", monthlyPayment.multiply(new BigDecimal(productTermMonths)).subtract(loanAmount));
                    
                    options.add(option);
                }
            }

        } catch (Exception e) {
            log.error("获取推荐融资方案失败: servicePeriodId={}", servicePeriodId, e);
        }

        return options;
    }

    // ==================== 贷款审批管理 ====================

    @Override
    @Transactional
    public Map<String, Object> submitLoanApproval(Long linkId, Map<String, Object> approvalRequest)
    {
        log.info("提交贷款审批: linkId={}", linkId);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            ServicePeriodLoan loan = servicePeriodLoanMapper.selectServicePeriodLoanByLinkId(linkId);
            if (loan == null) {
                result.put("success", false);
                result.put("message", "贷款记录不存在");
                return result;
            }

            // 更新审批状态
            loan.setApprovalStatus(ServicePeriodLoan.APPROVAL_SUBMITTED);
            loan.setLoanStatus(ServicePeriodLoan.STATUS_SUBMITTED);
            loan.setUpdateTime(DateUtils.getNowDate());
            
            servicePeriodLoanMapper.updateServicePeriodLoan(loan);
            
            result.put("success", true);
            result.put("message", "贷款审批提交成功");
            result.put("loanNumber", loan.getLoanNumber());
            
            // 发送审批通知
            sendDataChangeNotification(loan.getServicePeriodId(), "LOAN_APPROVAL_SUBMITTED", result);

        } catch (Exception e) {
            log.error("提交贷款审批失败: linkId={}", linkId, e);
            result.put("success", false);
            result.put("message", "提交失败: " + e.getMessage());
        }

        return result;
    }

    @Override
    @Transactional
    public Map<String, Object> processLoanApprovalResult(Long linkId, boolean approved, String approvalComments)
    {
        log.info("处理贷款审批结果: linkId={}, approved={}", linkId, approved);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            ServicePeriodLoan loan = servicePeriodLoanMapper.selectServicePeriodLoanByLinkId(linkId);
            if (loan == null) {
                result.put("success", false);
                result.put("message", "贷款记录不存在");
                return result;
            }

            // 更新审批结果
            loan.setApprovalStatus(approved ? ServicePeriodLoan.APPROVAL_APPROVED : ServicePeriodLoan.APPROVAL_REJECTED);
            loan.setLoanStatus(approved ? ServicePeriodLoan.STATUS_APPROVED : ServicePeriodLoan.STATUS_REJECTED);
            loan.setApprovalTime(DateUtils.getNowDate());
            loan.setApprovedBy(SecurityUtils.getUsername());
            loan.setUpdateTime(DateUtils.getNowDate());
            
            servicePeriodLoanMapper.updateServicePeriodLoan(loan);
            
            result.put("success", true);
            result.put("message", approved ? "贷款审批通过" : "贷款审批拒绝");
            result.put("approved", approved);
            result.put("loanNumber", loan.getLoanNumber());
            
            // 记录审计和发送通知
            String changeType = approved ? "LOAN_APPROVED" : "LOAN_REJECTED";
            recordServicePeriodDataChange(loan.getServicePeriodId(), changeType, null, loan, approvalComments);
            sendDataChangeNotification(loan.getServicePeriodId(), changeType, result);

        } catch (Exception e) {
            log.error("处理贷款审批结果失败: linkId={}", linkId, e);
            result.put("success", false);
            result.put("message", "处理失败: " + e.getMessage());
        }

        return result;
    }

    @Override
    public List<ServicePeriodLoan> selectPendingApprovalLoans()
    {
        return servicePeriodLoanMapper.selectServicePeriodLoansByApprovalStatus(ServicePeriodLoan.APPROVAL_SUBMITTED);
    }

    // ==================== 报表导出功能 ====================

    @Override
    public Map<String, Object> generateServicePeriodLoanReport(Long servicePeriodId, String reportType)
    {
        log.info("生成服务周期贷款报表: servicePeriodId={}, reportType={}", servicePeriodId, reportType);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 获取基础数据
            ServicePeriod servicePeriod = servicePeriodMapper.selectServicePeriodByServicePeriodId(servicePeriodId);
            List<ServicePeriodLoan> loans = servicePeriodLoanMapper.selectServicePeriodLoansByPeriodId(servicePeriodId);
            List<ServicePeriodEmployee> employees = servicePeriodEmployeeMapper.selectServicePeriodEmployeesByPeriodId(servicePeriodId);
            
            // 构建报表数据
            Map<String, Object> reportData = new HashMap<>();
            reportData.put("servicePeriod", servicePeriod);
            reportData.put("loans", loans);
            reportData.put("employees", employees);
            
            // 计算统计信息
            BigDecimal totalLoanAmount = loans.stream()
                    .map(ServicePeriodLoan::getLoanAmount)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            
            BigDecimal totalLaborCost = employees.stream()
                    .map(ServicePeriodEmployee::getTotalCost)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            
            Map<String, Object> statistics = new HashMap<>();
            statistics.put("totalLoanAmount", totalLoanAmount);
            statistics.put("totalLaborCost", totalLaborCost);
            statistics.put("loanCount", loans.size());
            statistics.put("employeeCount", employees.size());
            statistics.put("loanToLaborRatio", totalLaborCost.compareTo(BigDecimal.ZERO) > 0 ? 
                          totalLoanAmount.divide(totalLaborCost, 4, RoundingMode.HALF_UP) : BigDecimal.ZERO);
            
            reportData.put("statistics", statistics);
            
            result.put("success", true);
            result.put("reportType", reportType);
            result.put("reportData", reportData);
            result.put("generateTime", DateUtils.getNowDate());

        } catch (Exception e) {
            log.error("生成服务周期贷款报表失败: servicePeriodId={}", servicePeriodId, e);
            result.put("success", false);
            result.put("message", "生成报表失败: " + e.getMessage());
        }

        return result;
    }

    @Override
    public Map<String, Object> exportLoanAttendanceReport(Long servicePeriodId, String format)
    {
        log.info("导出贷款与出勤关联报表: servicePeriodId={}, format={}", servicePeriodId, format);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 获取关联信息
            Map<String, Object> associationData = getLoanAttendanceAssociation(servicePeriodId);
            
            // 根据格式生成导出文件
            String fileName = String.format("loan_attendance_report_%s_%s.%s", 
                                           servicePeriodId, 
                                           DateUtils.dateTimeNow("yyyyMMdd_HHmmss"), 
                                           format.toLowerCase());
            
            // 这里应该实现具体的文件生成逻辑
            // 目前返回模拟结果
            result.put("success", true);
            result.put("fileName", fileName);
            result.put("format", format);
            result.put("fileSize", "1.2MB");
            result.put("downloadUrl", "/api/download/" + fileName);
            result.put("associationData", associationData);

        } catch (Exception e) {
            log.error("导出贷款与出勤关联报表失败: servicePeriodId={}", servicePeriodId, e);
            result.put("success", false);
            result.put("message", "导出失败: " + e.getMessage());
        }

        return result;
    }

    @Override
    public Map<String, Object> getLoanAttendanceAssociation(Long servicePeriodId)
    {
        log.info("获取贷款与出勤关联信息: servicePeriodId={}", servicePeriodId);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 获取服务周期信息
            ServicePeriod servicePeriod = servicePeriodMapper.selectServicePeriodByServicePeriodId(servicePeriodId);
            List<ServicePeriodLoan> loans = servicePeriodLoanMapper.selectServicePeriodLoansByPeriodId(servicePeriodId);
            List<ServicePeriodEmployee> employees = servicePeriodEmployeeMapper.selectServicePeriodEmployeesByPeriodId(servicePeriodId);
            
            // 构建关联分析
            Map<String, Object> association = new HashMap<>();
            association.put("servicePeriodId", servicePeriodId);
            association.put("periodNumber", servicePeriod != null ? servicePeriod.getPeriodNumber() : null);
            
            // 出勤统计
            Map<String, Object> attendanceStats = new HashMap<>();
            attendanceStats.put("totalEmployees", employees.size());
            attendanceStats.put("totalWorkDays", employees.stream().mapToInt(ServicePeriodEmployee::getWorkDays).sum());
            attendanceStats.put("totalLaborCost", employees.stream()
                    .map(ServicePeriodEmployee::getTotalCost)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));
            
            // 贷款统计
            Map<String, Object> loanStats = new HashMap<>();
            loanStats.put("totalLoans", loans.size());
            loanStats.put("totalLoanAmount", loans.stream()
                    .map(ServicePeriodLoan::getLoanAmount)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));
            loanStats.put("approvedLoans", loans.stream()
                    .mapToInt(loan -> ServicePeriodLoan.STATUS_APPROVED.equals(loan.getLoanStatus()) ? 1 : 0)
                    .sum());
            
            // 关联分析
            Map<String, Object> correlationAnalysis = new HashMap<>();
            BigDecimal totalLaborCost = (BigDecimal) attendanceStats.get("totalLaborCost");
            BigDecimal totalLoanAmount = (BigDecimal) loanStats.get("totalLoanAmount");
            
            if (totalLaborCost.compareTo(BigDecimal.ZERO) > 0) {
                correlationAnalysis.put("loanToLaborRatio", totalLoanAmount.divide(totalLaborCost, 4, RoundingMode.HALF_UP));
            } else {
                correlationAnalysis.put("loanToLaborRatio", BigDecimal.ZERO);
            }
            
            correlationAnalysis.put("averageLoanPerEmployee", employees.size() > 0 ? 
                    totalLoanAmount.divide(new BigDecimal(employees.size()), 2, RoundingMode.HALF_UP) : BigDecimal.ZERO);
            
            association.put("attendanceStats", attendanceStats);
            association.put("loanStats", loanStats);
            association.put("correlationAnalysis", correlationAnalysis);
            association.put("detailedEmployees", employees);
            association.put("detailedLoans", loans);
            
            result.put("success", true);
            result.put("association", association);

        } catch (Exception e) {
            log.error("获取贷款与出勤关联信息失败: servicePeriodId={}", servicePeriodId, e);
            result.put("success", false);
            result.put("message", "获取关联信息失败: " + e.getMessage());
        }

        return result;
    }

    // ==================== 数据变更审计 ====================

    @Override
    @Transactional
    public Map<String, Object> recordServicePeriodDataChange(Long servicePeriodId, String changeType, 
                                                           Object oldValue, Object newValue, String changeReason)
    {
        log.info("记录服务周期数据变更: servicePeriodId={}, changeType={}", servicePeriodId, changeType);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 创建审计记录（这里应该有专门的审计表）
            Map<String, Object> auditRecord = new HashMap<>();
            auditRecord.put("servicePeriodId", servicePeriodId);
            auditRecord.put("changeType", changeType);
            auditRecord.put("oldValue", oldValue != null ? oldValue.toString() : null);
            auditRecord.put("newValue", newValue != null ? newValue.toString() : null);
            auditRecord.put("changeReason", changeReason);
            auditRecord.put("changedBy", SecurityUtils.getUsername());
            auditRecord.put("changeTime", DateUtils.getNowDate());
            
            // 这里应该保存到审计表
            // auditLogMapper.insertAuditLog(auditRecord);
            
            result.put("success", true);
            result.put("auditId", System.currentTimeMillis()); // 模拟审计ID
            result.put("message", "审计记录创建成功");

        } catch (Exception e) {
            log.error("记录数据变更审计失败: servicePeriodId={}", servicePeriodId, e);
            result.put("success", false);
            result.put("message", "记录审计失败: " + e.getMessage());
        }

        return result;
    }

    @Override
    public List<Map<String, Object>> getServicePeriodChangeHistory(Long servicePeriodId)
    {
        log.info("查询服务周期数据变更历史: servicePeriodId={}", servicePeriodId);
        
        List<Map<String, Object>> history = new ArrayList<>();
        
        try {
            // 这里应该从审计表查询历史记录
            // 目前返回模拟数据
            Map<String, Object> record = new HashMap<>();
            record.put("changeType", "LOAN_ADDED");
            record.put("changeTime", DateUtils.getNowDate());
            record.put("changedBy", "admin");
            record.put("changeReason", "新增贷款信息");
            history.add(record);

        } catch (Exception e) {
            log.error("查询数据变更历史失败: servicePeriodId={}", servicePeriodId, e);
        }

        return history;
    }

    @Override
    public Map<String, Object> sendDataChangeNotification(Long servicePeriodId, String changeType, Map<String, Object> changeDetails)
    {
        log.info("发送数据变更通知: servicePeriodId={}, changeType={}", servicePeriodId, changeType);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 构建通知内容
            String title = getNotificationTitle(changeType);
            String content = buildNotificationContent(servicePeriodId, changeType, changeDetails);
            
            // 发送通知
            if (notificationService != null) {
                // 创建通知消息对象
                NotificationMessage message = new NotificationMessage();
                message.setNotificationId("LOAN_" + servicePeriodId + "_" + System.currentTimeMillis());
                message.setRecipientType("ADMIN");
                message.setRecipientId("admin");
                message.setRecipientAddress("admin@example.com"); // 这里应该从配置或数据库获取
                message.setNotificationType("SERVICE_PERIOD_CHANGE");
                message.setNotificationChannel("SYSTEM");
                message.setSubject(title);
                message.setContent(content);
                message.setPriority("NORMAL");
                message.setBusinessType("SERVICE_PERIOD");
                message.setBusinessId(servicePeriodId.toString());
                message.setCreateTime(DateUtils.getNowDate());
                
                // 发送通知
                boolean sendResult = notificationService.sendNotification(message);
                
                if (sendResult) {
                    result.put("success", true);
                    result.put("message", "通知发送成功");
                } else {
                    result.put("success", false);
                    result.put("message", "通知发送失败");
                }
            } else {
                result.put("success", false);
                result.put("message", "通知服务不可用");
            }

        } catch (Exception e) {
            log.error("发送数据变更通知失败: servicePeriodId={}", servicePeriodId, e);
            result.put("success", false);
            result.put("message", "发送通知失败: " + e.getMessage());
        }

        return result;
    }

    // ==================== 统计分析功能 ====================

    @Override
    public BigDecimal sumLoanAmountByPeriodId(Long servicePeriodId)
    {
        return servicePeriodLoanMapper.sumLoanAmountByPeriodId(servicePeriodId);
    }

    @Override
    public List<ServicePeriodLoan> selectExpiringLoans(Integer days)
    {
        return servicePeriodLoanMapper.selectExpiringLoans(days);
    }

    @Override
    public Map<String, Object> generateLoanStatisticsReport(Long servicePeriodId)
    {
        log.info("生成贷款统计分析报告: servicePeriodId={}", servicePeriodId);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            List<ServicePeriodLoan> loans = servicePeriodLoanMapper.selectServicePeriodLoansByPeriodId(servicePeriodId);
            
            // 基础统计
            Map<String, Object> basicStats = new HashMap<>();
            basicStats.put("totalLoans", loans.size());
            basicStats.put("totalAmount", loans.stream()
                    .map(ServicePeriodLoan::getLoanAmount)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));
            
            // 状态分布
            Map<String, Long> statusDistribution = loans.stream()
                    .collect(Collectors.groupingBy(ServicePeriodLoan::getLoanStatus, Collectors.counting()));
            
            // 银行分布
            Map<String, Long> bankDistribution = loans.stream()
                    .filter(loan -> loan.getBankInstitutionName() != null)
                    .collect(Collectors.groupingBy(ServicePeriodLoan::getBankInstitutionName, Collectors.counting()));
            
            result.put("success", true);
            result.put("basicStats", basicStats);
            result.put("statusDistribution", statusDistribution);
            result.put("bankDistribution", bankDistribution);

        } catch (Exception e) {
            log.error("生成贷款统计分析报告失败: servicePeriodId={}", servicePeriodId, e);
            result.put("success", false);
            result.put("message", "生成统计报告失败: " + e.getMessage());
        }

        return result;
    }

    // ==================== 贷款编号生成 ====================

    @Override
    public String generateLoanNumber(Long servicePeriodId)
    {
        try {
            ServicePeriod servicePeriod = servicePeriodMapper.selectServicePeriodByServicePeriodId(servicePeriodId);
            if (servicePeriod == null) {
                throw new RuntimeException("服务周期不存在");
            }

            // 获取该服务周期已有的贷款数量
            List<ServicePeriodLoan> existingLoans = servicePeriodLoanMapper.selectServicePeriodLoansByPeriodId(servicePeriodId);
            int loanCount = existingLoans.size() + 1;

            // 生成格式: 服务周期编号-LOAN-序号
            return servicePeriod.getPeriodNumber() + "-LOAN-" + String.format("%03d", loanCount);

        } catch (Exception e) {
            log.error("生成贷款编号失败: servicePeriodId={}", servicePeriodId, e);
            return "LOAN-" + System.currentTimeMillis();
        }
    }

    // ==================== 银行选择逻辑优化 ====================

    @Override
    @Transactional
    public Map<String, Object> createLoanWithBankSelection(ServicePeriodLoan servicePeriodLoan)
    {
        log.info("创建包含银行选择的贷款申请: servicePeriodId={}, bankId={}", 
                servicePeriodLoan.getServicePeriodId(), servicePeriodLoan.getBankInstitutionId());
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 1. 验证必要参数
            if (servicePeriodLoan.getServicePeriodId() == null) {
                result.put("success", false);
                result.put("message", "服务周期ID不能为空");
                return result;
            }
            
            if (servicePeriodLoan.getLoanAmount() == null || servicePeriodLoan.getLoanAmount().compareTo(BigDecimal.ZERO) <= 0) {
                result.put("success", false);
                result.put("message", "贷款金额必须大于0");
                return result;
            }

            // 2. 验证服务周期存在
            ServicePeriod servicePeriod = servicePeriodMapper.selectServicePeriodByServicePeriodId(servicePeriodLoan.getServicePeriodId());
            if (servicePeriod == null) {
                result.put("success", false);
                result.put("message", "服务周期不存在");
                return result;
            }

            // 3. 设置默认值
            if (StringUtils.isEmpty(servicePeriodLoan.getLoanPurpose())) {
                servicePeriodLoan.setLoanPurpose("服务周期人工成本融资");
            }
            
            if (servicePeriodLoan.getLoanTermMonths() == null) {
                servicePeriodLoan.setLoanTermMonths(12); // 默认12个月
            }

            // 4. 生成贷款编号
            if (StringUtils.isEmpty(servicePeriodLoan.getLoanNumber())) {
                String loanNumber = generateLoanNumber(servicePeriodLoan.getServicePeriodId());
                servicePeriodLoan.setLoanNumber(loanNumber);
            }

            // 5. 设置银行选择相关信息
            if (servicePeriodLoan.getBankInstitutionId() != null) {
                servicePeriodLoan.setBankSelectedTime(DateUtils.getNowDate());
                servicePeriodLoan.setQuickSubmitEnabled(true);
                
                // 计算月还款额（如果未提供）
                if (servicePeriodLoan.getMonthlyPayment() == null && servicePeriodLoan.getInterestRate() != null) {
                    BigDecimal monthlyPayment = calculateMonthlyPayment(
                        servicePeriodLoan.getLoanAmount(), 
                        servicePeriodLoan.getInterestRate(), 
                        servicePeriodLoan.getLoanTermMonths()
                    );
                    servicePeriodLoan.setMonthlyPayment(monthlyPayment);
                }
            } else {
                servicePeriodLoan.setQuickSubmitEnabled(false);
            }

            // 6. 设置状态
            servicePeriodLoan.setLoanStatus(ServicePeriodLoan.STATUS_PENDING);
            servicePeriodLoan.setApprovalStatus(ServicePeriodLoan.APPROVAL_PENDING);

            // 7. 设置贷款日期
            servicePeriodLoan.setLoanStartDate(DateUtils.getNowDate());
            if (servicePeriodLoan.getLoanTermMonths() != null) {
                Calendar cal = Calendar.getInstance();
                cal.add(Calendar.MONTH, servicePeriodLoan.getLoanTermMonths());
                servicePeriodLoan.setLoanEndDate(cal.getTime());
            }

            // 8. 保存贷款申请
            servicePeriodLoan.setCreateTime(DateUtils.getNowDate());
            int insertResult = servicePeriodLoanMapper.insertServicePeriodLoan(servicePeriodLoan);
            
            if (insertResult > 0) {
                result.put("success", true);
                result.put("message", "贷款申请创建成功");
                result.put("loanId", servicePeriodLoan.getLinkId());
                result.put("loanNumber", servicePeriodLoan.getLoanNumber());
                result.put("quickSubmitEnabled", servicePeriodLoan.getQuickSubmitEnabled());
                
                // 记录数据变更审计
                recordServicePeriodDataChange(servicePeriodLoan.getServicePeriodId(), "LOAN_CREATED_WITH_BANK_SELECTION", 
                                            null, servicePeriodLoan, "创建包含银行选择的贷款申请");
                
                // 发送通知
                sendDataChangeNotification(servicePeriodLoan.getServicePeriodId(), "LOAN_CREATED_WITH_BANK_SELECTION", result);
                
                log.info("贷款申请创建成功: loanId={}, loanNumber={}, bankId={}", 
                        servicePeriodLoan.getLinkId(), servicePeriodLoan.getLoanNumber(), servicePeriodLoan.getBankInstitutionId());
            } else {
                result.put("success", false);
                result.put("message", "贷款申请创建失败");
            }

        } catch (Exception e) {
            log.error("创建包含银行选择的贷款申请失败: servicePeriodId={}", servicePeriodLoan.getServicePeriodId(), e);
            result.put("success", false);
            result.put("message", "创建失败: " + e.getMessage());
        }

        return result;
    }

    @Override
    @Transactional
    public Map<String, Object> quickSubmitToBank(Long linkId)
    {
        log.info("一键提交贷款到银行: linkId={}", linkId);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 1. 获取贷款信息
            ServicePeriodLoan loan = servicePeriodLoanMapper.selectServicePeriodLoanByLinkId(linkId);
            if (loan == null) {
                result.put("success", false);
                result.put("message", "贷款记录不存在");
                return result;
            }

            // 2. 验证是否可以一键提交
            if (!Boolean.TRUE.equals(loan.getQuickSubmitEnabled())) {
                result.put("success", false);
                result.put("message", "该贷款申请不支持一键提交");
                return result;
            }

            // 3. 验证必要信息完整性
            if (loan.getBankInstitutionId() == null) {
                result.put("success", false);
                result.put("message", "银行信息缺失，无法提交");
                return result;
            }

            if (loan.getLoanAmount() == null || loan.getLoanAmount().compareTo(BigDecimal.ZERO) <= 0) {
                result.put("success", false);
                result.put("message", "贷款金额无效，无法提交");
                return result;
            }

            if (StringUtils.isEmpty(loan.getSubmitComments())) {
                result.put("success", false);
                result.put("message", "提交说明缺失，无法提交");
                return result;
            }

            // 4. 验证当前状态
            if (!ServicePeriodLoan.STATUS_PENDING.equals(loan.getLoanStatus())) {
                result.put("success", false);
                result.put("message", "贷款状态不是待提交，无法提交");
                return result;
            }

            // 5. 记录提交前的状态用于审计
            ServicePeriodLoan oldLoan = new ServicePeriodLoan();
            oldLoan.setLoanStatus(loan.getLoanStatus());
            oldLoan.setApprovalStatus(loan.getApprovalStatus());

            // 6. 更新贷款状态
            loan.setLoanStatus(ServicePeriodLoan.STATUS_SUBMITTED);
            loan.setApprovalStatus(ServicePeriodLoan.APPROVAL_SUBMITTED);
            loan.setUpdateTime(DateUtils.getNowDate());
            
            // 记录提交时间
            if (loan.getApprovalTime() == null) {
                loan.setApprovalTime(DateUtils.getNowDate());
            }

            // 7. 保存更新
            int updateResult = servicePeriodLoanMapper.updateServicePeriodLoan(loan);
            
            if (updateResult > 0) {
                // 提交成功
                result.put("success", true);
                result.put("message", "贷款已成功提交至银行");
                result.put("loanNumber", loan.getLoanNumber());
                result.put("bankName", loan.getBankInstitutionName());
                result.put("submitTime", loan.getUpdateTime());
                result.put("loanAmount", loan.getLoanAmount());
                result.put("monthlyPayment", loan.getMonthlyPayment());
                result.put("loanStatus", loan.getLoanStatus());
                result.put("approvalStatus", loan.getApprovalStatus());
                
                // 记录数据变更审计
                recordServicePeriodDataChange(loan.getServicePeriodId(), "LOAN_QUICK_SUBMITTED", 
                                            oldLoan, loan, "一键提交贷款到银行: " + loan.getBankInstitutionName());
                
                // 发送通知
                Map<String, Object> notificationData = new HashMap<>();
                notificationData.put("loanNumber", loan.getLoanNumber());
                notificationData.put("bankName", loan.getBankInstitutionName());
                notificationData.put("loanAmount", loan.getLoanAmount());
                notificationData.put("submitTime", loan.getUpdateTime());
                sendDataChangeNotification(loan.getServicePeriodId(), "LOAN_QUICK_SUBMITTED", notificationData);
                
                log.info("贷款一键提交成功: loanId={}, loanNumber={}, bankName={}", 
                        linkId, loan.getLoanNumber(), loan.getBankInstitutionName());
            } else {
                // 提交失败
                result.put("success", false);
                result.put("message", "提交失败，数据库更新失败");
                log.error("贷款一键提交失败，数据库更新失败: linkId={}", linkId);
            }

        } catch (Exception e) {
            log.error("一键提交贷款失败: linkId={}", linkId, e);
            result.put("success", false);
            result.put("message", "提交失败: " + e.getMessage());
            
            // 记录错误审计
            try {
                recordServicePeriodDataChange(null, "LOAN_QUICK_SUBMIT_FAILED", 
                                            null, null, "一键提交失败: " + e.getMessage());
            } catch (Exception auditException) {
                log.error("记录审计失败", auditException);
            }
        }

        return result;
    }

    @Override
    @Transactional
    public int updateServicePeriodLoanWithHistory(ServicePeriodLoan servicePeriodLoan)
    {
        log.info("更新服务周期贷款关联（支持银行选择历史）: linkId={}", servicePeriodLoan.getLinkId());
        
        try {
            // 1. 获取原始数据用于历史记录
            ServicePeriodLoan oldLoan = servicePeriodLoanMapper.selectServicePeriodLoanByLinkId(servicePeriodLoan.getLinkId());
            if (oldLoan == null) {
                log.warn("贷款记录不存在: linkId={}", servicePeriodLoan.getLinkId());
                return 0;
            }

            // 2. 检查银行选择是否发生变化
            boolean bankChanged = false;
            StringBuilder historyBuilder = new StringBuilder();
            
            if (oldLoan.getBankInstitutionId() != null && servicePeriodLoan.getBankInstitutionId() != null) {
                if (!oldLoan.getBankInstitutionId().equals(servicePeriodLoan.getBankInstitutionId())) {
                    bankChanged = true;
                    historyBuilder.append(String.format("[%s] 银行变更: %s(%d) -> %s(%d)", 
                                        DateUtils.getTime(),
                                        oldLoan.getBankInstitutionName(), oldLoan.getBankInstitutionId(),
                                        servicePeriodLoan.getBankInstitutionName(), servicePeriodLoan.getBankInstitutionId()));
                }
            } else if (oldLoan.getBankInstitutionId() == null && servicePeriodLoan.getBankInstitutionId() != null) {
                bankChanged = true;
                historyBuilder.append(String.format("[%s] 首次选择银行: %s(%d)", 
                                    DateUtils.getTime(),
                                    servicePeriodLoan.getBankInstitutionName(), servicePeriodLoan.getBankInstitutionId()));
            }

            // 3. 检查提交说明是否发生变化
            if (!StringUtils.equals(oldLoan.getSubmitComments(), servicePeriodLoan.getSubmitComments())) {
                if (historyBuilder.length() > 0) {
                    historyBuilder.append("; ");
                }
                historyBuilder.append(String.format("[%s] 提交说明变更: '%s' -> '%s'", 
                                    DateUtils.getTime(),
                                    StringUtils.defaultString(oldLoan.getSubmitComments(), "无"),
                                    StringUtils.defaultString(servicePeriodLoan.getSubmitComments(), "无")));
            }

            // 4. 更新银行选择历史
            if (historyBuilder.length() > 0) {
                String existingHistory = StringUtils.defaultString(oldLoan.getBankSelectionHistory(), "");
                String newHistoryEntry = historyBuilder.toString();
                
                if (StringUtils.isNotEmpty(existingHistory)) {
                    servicePeriodLoan.setBankSelectionHistory(existingHistory + "\n" + newHistoryEntry);
                } else {
                    servicePeriodLoan.setBankSelectionHistory(newHistoryEntry);
                }
                
                // 如果银行发生变化，更新银行选择时间
                if (bankChanged) {
                    servicePeriodLoan.setBankSelectedTime(DateUtils.getNowDate());
                }
            }

            // 5. 重新计算月还款额（如果银行或金额发生变化）
            if (bankChanged || !Objects.equals(oldLoan.getLoanAmount(), servicePeriodLoan.getLoanAmount())) {
                if (servicePeriodLoan.getInterestRate() != null && servicePeriodLoan.getLoanTermMonths() != null) {
                    BigDecimal monthlyPayment = calculateMonthlyPayment(
                        servicePeriodLoan.getLoanAmount(), 
                        servicePeriodLoan.getInterestRate(), 
                        servicePeriodLoan.getLoanTermMonths()
                    );
                    servicePeriodLoan.setMonthlyPayment(monthlyPayment);
                }
            }

            // 6. 更新一键提交状态
            boolean canQuickSubmit = servicePeriodLoan.getBankInstitutionId() != null 
                                   && servicePeriodLoan.getLoanAmount() != null 
                                   && servicePeriodLoan.getLoanAmount().compareTo(BigDecimal.ZERO) > 0
                                   && ServicePeriodLoan.STATUS_PENDING.equals(servicePeriodLoan.getLoanStatus());
            servicePeriodLoan.setQuickSubmitEnabled(canQuickSubmit);

            // 7. 设置更新时间
            servicePeriodLoan.setUpdateTime(DateUtils.getNowDate());

            // 8. 执行更新
            int result = servicePeriodLoanMapper.updateServicePeriodLoan(servicePeriodLoan);
            
            // 9. 记录数据变更审计
            if (result > 0) {
                String changeReason = bankChanged ? "银行选择变更" : "贷款信息更新";
                recordServicePeriodDataChange(servicePeriodLoan.getServicePeriodId(), "LOAN_UPDATED_WITH_HISTORY", 
                                            oldLoan, servicePeriodLoan, changeReason);
                
                // 发送通知（如果有重要变更）
                if (bankChanged) {
                    Map<String, Object> notificationData = new HashMap<>();
                    notificationData.put("loanNumber", servicePeriodLoan.getLoanNumber());
                    notificationData.put("oldBank", oldLoan.getBankInstitutionName());
                    notificationData.put("newBank", servicePeriodLoan.getBankInstitutionName());
                    sendDataChangeNotification(servicePeriodLoan.getServicePeriodId(), "BANK_SELECTION_CHANGED", notificationData);
                }
                
                log.info("贷款信息更新成功: linkId={}, bankChanged={}, historyUpdated={}", 
                        servicePeriodLoan.getLinkId(), bankChanged, historyBuilder.length() > 0);
            }
            
            return result;

        } catch (Exception e) {
            log.error("更新服务周期贷款关联失败: linkId={}", servicePeriodLoan.getLinkId(), e);
            throw new RuntimeException("更新贷款信息失败: " + e.getMessage(), e);
        }
    }

    // ==================== 私有辅助方法 ====================

    /**
     * 获取银行产品数据 - 从数据库获取
     */
    private List<Map<String, Object>> getBankProducts()
    {
        try {
            // 获取所有活跃的银行机构
            List<BankInstitution> activeBanks = bankInstitutionService.selectActiveBankInstitutions();
            
            List<Map<String, Object>> products = new ArrayList<>();
            
            for (BankInstitution bank : activeBanks) {
                Map<String, Object> product = new HashMap<>();
                product.put("bankId", bank.getBankId());
                product.put("bankName", bank.getBankName());
                product.put("productName", bank.getProductName() != null ? bank.getProductName() : "标准产品");
                
                // 优先使用产品利率，如果没有则使用基准利率
                Double interestRate = bank.getProductInterestRate();
                if (interestRate == null) {
                    interestRate = bank.getBaseInterestRate();
                }
                if (interestRate == null) {
                    interestRate = 0.045; // 默认利率
                }
                product.put("interestRate", interestRate);
                
                // 使用产品期限，如果没有则使用最大贷款期限
                Integer termMonths = bank.getProductTermMonths();
                if (termMonths == null) {
                    termMonths = bank.getMaxLoanTermMonths();
                }
                if (termMonths == null) {
                    termMonths = 12; // 默认期限
                }
                product.put("termMonths", termMonths);
                
                // 使用最大贷款金额
                java.math.BigDecimal maxAmount = bank.getMaxLoanAmountDecimal();
                if (maxAmount == null) {
                    maxAmount = new java.math.BigDecimal("1000000"); // 默认最大金额
                }
                product.put("maxAmount", maxAmount);
                
                products.add(product);
            }
            
            // 如果数据库中没有数据，返回默认的银行产品
            if (products.isEmpty()) {
                return getDefaultBankProducts();
            }
            
            return products;
        } catch (Exception e) {
            log.error("从数据库获取银行产品失败，使用默认数据", e);
            return getDefaultBankProducts();
        }
    }

    /**
     * 获取默认银行产品数据 - 作为备用方案
     */
    private List<Map<String, Object>> getDefaultBankProducts()
    {
        List<Map<String, Object>> products = new ArrayList<>();
        
        // 工商银行 - 短期产品
        Map<String, Object> icbc1 = new HashMap<>();
        icbc1.put("bankId", 1L);
        icbc1.put("bankName", "工商银行");
        icbc1.put("productName", "短期经营贷");
        icbc1.put("interestRate", 0.045);
        icbc1.put("termMonths", 6);
        icbc1.put("maxAmount", new BigDecimal("1000000"));
        products.add(icbc1);
        
        // 工商银行 - 中期产品
        Map<String, Object> icbc2 = new HashMap<>();
        icbc2.put("bankId", 1L);
        icbc2.put("bankName", "工商银行");
        icbc2.put("productName", "中期经营贷");
        icbc2.put("interestRate", 0.055);
        icbc2.put("termMonths", 12);
        icbc2.put("maxAmount", new BigDecimal("2000000"));
        products.add(icbc2);
        
        // 建设银行 - 灵活期限产品
        Map<String, Object> ccb1 = new HashMap<>();
        ccb1.put("bankId", 2L);
        ccb1.put("bankName", "建设银行");
        ccb1.put("productName", "灵活经营贷");
        ccb1.put("interestRate", 0.050);
        ccb1.put("termMonths", 9);
        ccb1.put("maxAmount", new BigDecimal("1500000"));
        products.add(ccb1);
        
        // 建设银行 - 长期产品
        Map<String, Object> ccb2 = new HashMap<>();
        ccb2.put("bankId", 2L);
        ccb2.put("bankName", "建设银行");
        ccb2.put("productName", "长期经营贷");
        ccb2.put("interestRate", 0.065);
        ccb2.put("termMonths", 24);
        ccb2.put("maxAmount", new BigDecimal("3000000"));
        products.add(ccb2);
        
        // 农业银行 - 中短期产品
        Map<String, Object> abc1 = new HashMap<>();
        abc1.put("bankId", 3L);
        abc1.put("bankName", "农业银行");
        abc1.put("productName", "惠农经营贷");
        abc1.put("interestRate", 0.048);
        abc1.put("termMonths", 8);
        abc1.put("maxAmount", new BigDecimal("1200000"));
        products.add(abc1);
        
        // 中国银行 - 标准产品
        Map<String, Object> boc1 = new HashMap<>();
        boc1.put("bankId", 4L);
        boc1.put("bankName", "中国银行");
        boc1.put("productName", "标准经营贷");
        boc1.put("interestRate", 0.052);
        boc1.put("termMonths", 12);
        boc1.put("maxAmount", new BigDecimal("1800000"));
        products.add(boc1);
        
        // 招商银行 - 快速贷
        Map<String, Object> cmb1 = new HashMap<>();
        cmb1.put("bankId", 5L);
        cmb1.put("bankName", "招商银行");
        cmb1.put("productName", "快速经营贷");
        cmb1.put("interestRate", 0.058);
        cmb1.put("termMonths", 6);
        cmb1.put("maxAmount", new BigDecimal("800000"));
        products.add(cmb1);
        
        return products;
    }

    /**
     * 计算合同期限（月）
     */
    private Integer calculateContractTermMonths(Date startDate, Date endDate)
    {
        if (startDate == null || endDate == null) {
            return null;
        }
        
        Calendar start = Calendar.getInstance();
        start.setTime(startDate);
        Calendar end = Calendar.getInstance();
        end.setTime(endDate);
        
        int months = 0;
        while (start.before(end)) {
            start.add(Calendar.MONTH, 1);
            months++;
        }
        
        return months;
    }

    /**
     * 计算月还款额
     */
    private BigDecimal calculateMonthlyPayment(BigDecimal loanAmount, Double annualRate, Integer termMonths)
    {
        if (loanAmount == null || annualRate == null || termMonths == null || termMonths <= 0) {
            return BigDecimal.ZERO;
        }
        
        double monthlyRate = annualRate / 12;
        if (monthlyRate == 0) {
            return loanAmount.divide(new BigDecimal(termMonths), 2, RoundingMode.HALF_UP);
        }
        
        double factor = Math.pow(1 + monthlyRate, termMonths);
        double monthlyPayment = loanAmount.doubleValue() * monthlyRate * factor / (factor - 1);
        
        return new BigDecimal(monthlyPayment).setScale(2, RoundingMode.HALF_UP);
    }

    /**
     * 获取匹配度分数
     */
    private int getMatchScore(String matchLevel)
    {
        switch (matchLevel) {
            case ServicePeriodLoan.MATCH_PERFECT: return 4;
            case ServicePeriodLoan.MATCH_GOOD: return 3;
            case ServicePeriodLoan.MATCH_ACCEPTABLE: return 2;
            case ServicePeriodLoan.MATCH_POOR: return 1;
            default: return 0;
        }
    }

    /**
     * 获取通知标题
     */
    private String getNotificationTitle(String changeType)
    {
        switch (changeType) {
            case "LOAN_APPLICATION_SUBMITTED": return "贷款申请已提交";
            case "LOAN_APPROVED": return "贷款审批通过";
            case "LOAN_REJECTED": return "贷款审批拒绝";
            case "LOAN_ADDED": return "新增贷款信息";
            case "LOAN_UPDATED": return "贷款信息更新";
            case "LOAN_DELETED": return "贷款信息删除";
            default: return "服务周期数据变更";
        }
    }

    /**
     * 构建通知内容
     */
    private String buildNotificationContent(Long servicePeriodId, String changeType, Map<String, Object> changeDetails)
    {
        StringBuilder content = new StringBuilder();
        content.append("服务周期ID: ").append(servicePeriodId).append("\n");
        content.append("变更类型: ").append(changeType).append("\n");
        content.append("变更时间: ").append(DateUtils.getTime()).append("\n");
        
        if (changeDetails != null && !changeDetails.isEmpty()) {
            content.append("变更详情: ").append(changeDetails.toString());
        }
        
        return content.toString();
    }
}