package com.ruoyi.credit.service.impl;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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.credit.domain.Contract;
import com.ruoyi.credit.domain.DigitalCredit;
import com.ruoyi.credit.domain.ServiceContract;
import com.ruoyi.credit.mapper.ContractMapper;
import com.ruoyi.credit.mapper.DigitalCreditMapper;
import com.ruoyi.credit.service.ICreditService;
import com.ruoyi.framework.security.validator.DepartmentPermissionValidator;

/**
 * 数字债权服务实现
 *
 * @author ruoyi
 * @date 2025-12-19
 */
@Service
public class CreditServiceImpl implements ICreditService {

    private static final Logger log = LoggerFactory.getLogger(CreditServiceImpl.class);

    @Autowired
    private DigitalCreditMapper digitalCreditMapper;

    @Autowired
    private ContractMapper contractMapper;

    @Autowired
    private DepartmentPermissionValidator departmentPermissionValidator;

    // 债权状态常量
    public static final String CREDIT_STATUS_ACTIVE = "ACTIVE";         // 有效
    public static final String CREDIT_STATUS_USED = "USED";             // 已使用
    public static final String CREDIT_STATUS_EXPIRED = "EXPIRED";       // 已过期
    public static final String CREDIT_STATUS_SETTLED = "SETTLED";       // 已结清
    public static final String CREDIT_STATUS_CANCELLED = "CANCELLED";   // 已取消

    // 合同状态常量
    public static final String CONTRACT_STATUS_CONFIRMED = "CONFIRMED";
    public static final String CONTRACT_STATUS_COMPLETED = "COMPLETED";

    /**
     * 生成数字债权凭证
     *
     * @param contractId 合同ID
     * @return 生成的债权凭证
     */
    @Override
    @Transactional
    public DigitalCredit generateCredit(Long contractId) {
        log.info("开始生成数字债权凭证，合同ID: {}", contractId);

        // 1. 查询合同信息
        Contract contract = contractMapper.selectContractByContractId(contractId);
        if (contract == null) {
            throw new RuntimeException("合同不存在: " + contractId);
        }

        // 2. 验证合同状态 - 只有已确认的合同才能生成债权
        if (!"CONFIRMED".equals(contract.getContractStatus())) {
            throw new RuntimeException("合同状态不允许生成债权，当前状态: " + contract.getContractStatus());
        }

        // 3. 检查是否已存在债权凭证
        DigitalCredit existingCredit = digitalCreditMapper.selectDigitalCreditByContractId(contractId);
        if (existingCredit != null) {
            log.warn("合同已存在债权凭证，合同ID: {}, 债权ID: {}", contractId, existingCredit.getCreditId());
            return existingCredit;
        }

        // 4. 从合同转换生成债权
        DigitalCredit credit = convertContractToCredit(contract);

        // 验证数据创建权限并自动设置部门ID
        departmentPermissionValidator.validateDataCreation(credit);

        // 5. 保存债权凭证
        int result = digitalCreditMapper.insertDigitalCredit(credit);
        if (result <= 0) {
            throw new RuntimeException("生成债权凭证失败");
        }

        log.info("成功生成数字债权凭证，债权ID: {}, 债权编号: {}", credit.getCreditId(), credit.getCreditNumber());

        return credit;
    }

    /**
     * 生成数字债权凭证（支持自定义债权数据）
     *
     * @param digitalCredit 债权数据
     * @return 生成的债权凭证
     */
    @Override
    @Transactional
    public DigitalCredit generateCredit(DigitalCredit digitalCredit) {
        log.info("开始生成自定义数字债权凭证，合同ID: {}", digitalCredit.getContractId());

        // 1. 验证必要字段
        if (digitalCredit.getContractId() == null) {
            throw new RuntimeException("合同ID不能为空");
        }

        // 2. 查询合同信息
        Contract contract = contractMapper.selectContractByContractId(digitalCredit.getContractId());
        if (contract == null) {
            throw new RuntimeException("合同不存在: " + digitalCredit.getContractId());
        }

        // 3. 验证合同状态
        if (!"CONFIRMED".equals(contract.getContractStatus())) {
            throw new RuntimeException("合同状态不允许生成债权，当前状态: " + contract.getContractStatus());
        }

        // 4. 检查是否已存在债权凭证
        DigitalCredit existingCredit = digitalCreditMapper.selectDigitalCreditByContractId(digitalCredit.getContractId());
        if (existingCredit != null) {
            log.warn("合同已存在债权凭证，合同ID: {}, 债权ID: {}", digitalCredit.getContractId(), existingCredit.getCreditId());
            return existingCredit;
        }

        // 5. 设置默认值和自动生成字段
        digitalCredit.setCreditNumber(generateCreditNumber());

        // 设置创建者信息 - 添加调试日志
        try {
            String currentUser = SecurityUtils.getUsername();
            log.info("当前登录用户: {}", currentUser);
            digitalCredit.setCreateBy(currentUser);
        } catch (Exception e) {
            log.error("获取当前用户失败", e);
            digitalCredit.setCreateBy("system"); // 设置默认值
        }

        digitalCredit.setCreateTime(new java.util.Date());
        digitalCredit.setUpdateTime(new java.util.Date());

        // 6. 如果没有设置债权人和债务人信息，从合同中获取
        if (digitalCredit.getCreditorName() == null || digitalCredit.getCreditorName().isEmpty()) {
            digitalCredit.setCreditorName(contract.getSecurityCompany());
            digitalCredit.setCreditorId(contract.getSecurityCompanyId() != null ? contract.getSecurityCompanyId()
                    : (contract.getSecurityCompany() != null ? (long) contract.getSecurityCompany().hashCode() : 0L));
        }

        if (digitalCredit.getDebtorName() == null || digitalCredit.getDebtorName().isEmpty()) {
            digitalCredit.setDebtorName(contract.getClientCompany());
            digitalCredit.setDebtorId(contract.getClientCompanyId() != null ? contract.getClientCompanyId()
                    : (contract.getClientCompany() != null ? (long) contract.getClientCompany().hashCode() : 0L));
        }

        // 7. 设置合同编号
        if (digitalCredit.getContractNumber() == null || digitalCredit.getContractNumber().isEmpty()) {
            digitalCredit.setContractNumber(contract.getContractNumber());
        }

        // 8. 如果没有设置状态，默认为已生成
        if (digitalCredit.getCreditStatus() == null || digitalCredit.getCreditStatus().isEmpty()) {
            digitalCredit.setCreditStatus("generated");
        }

        // 9. 生成数字签名 - 确保在所有必要字段设置完成后生成
        try {
            String signature = generateDigitalSignature(digitalCredit);
            digitalCredit.setDigitalSignature(signature);
            log.debug("为债权生成数字签名: {}", signature);
        } catch (Exception e) {
            log.error("生成数字签名失败", e);
            throw new RuntimeException("生成数字签名失败: " + e.getMessage());
        }

        // 10. 保存债权凭证
        int result = digitalCreditMapper.insertDigitalCredit(digitalCredit);
        if (result <= 0) {
            throw new RuntimeException("生成债权凭证失败");
        }

        log.info("成功生成自定义数字债权凭证，债权ID: {}, 债权编号: {}", digitalCredit.getCreditId(), digitalCredit.getCreditNumber());

        return digitalCredit;
    }

    /**
     * 验证债权凭证有效性（支持不同验证类型）
     *
     * @param creditId 债权ID
     * @param validationType 验证类型
     * @param description 验证描述
     * @param validationParams 验证参数
     * @return 验证结果
     */
    @Override
    public Map<String, Object> validateCredit(Long creditId, String validationType, String description, String validationParams) {
        log.info("验证债权凭证有效性，债权ID: {}, 验证类型: {}", creditId, validationType);

        Map<String, Object> result = new HashMap<>();
        StringBuilder errorMessage = new StringBuilder();
        boolean isValid = true;
        Map<String, Object> validationDetails = new HashMap<>();

        // 1. 查询债权信息
        DigitalCredit credit = digitalCreditMapper.selectDigitalCreditByCreditId(creditId);
        if (credit == null) {
            isValid = false;
            errorMessage.append("债权凭证不存在; ");
        } else {
            // 根据验证类型执行不同的验证逻辑
            switch (validationType) {
                case "integrity":
                    isValid = performIntegrityValidation(credit, errorMessage, validationDetails);
                    break;
                case "signature":
                    isValid = performSignatureValidation(credit, errorMessage, validationDetails);
                    break;
                case "blockchain":
                    isValid = performBlockchainValidation(credit, errorMessage, validationDetails);
                    break;
                case "comprehensive":
                default:
                    isValid = performComprehensiveValidation(credit, errorMessage, validationDetails);
                    break;
            }
        }

        // 构建验证结果
        result.put("valid", isValid);
        result.put("success", isValid);
        result.put("message", errorMessage.toString());
        result.put("credit", credit);
        result.put("validationType", validationType);
        result.put("validatedAt", new Date());
        result.put("validationCode", generateValidationCode());
        result.put("validatedBy", SecurityUtils.getUsername());
        result.put("description", description);
        result.put("details", validationDetails);

        // 记录验证历史
        recordValidationHistory(creditId, result);

        log.debug("债权验证结果: {}", result);
        return result;
    }

    /**
     * 验证债权凭证有效性（简化版本） 后端自动验证，不依赖前端输入
     *
     * @param creditId 债权ID
     * @return 验证结果
     */
    @Override
    public Map<String, Object> validateCredit(Long creditId) {
        log.info("开始后端自动验证债权凭证，债权ID: {}", creditId);

        // 首先尝试修复签名（如果需要的话）
        try {
            fixSignatureIfNeeded(creditId);
        } catch (Exception e) {
            log.warn("修复签名时出现异常，继续验证: {}", e.getMessage());
        }

        Map<String, Object> result = validateCredit(creditId, "comprehensive", "系统自动验证", "");

        // 如果验证成功，自动通知银行系统
        if ((Boolean) result.get("valid")) {
            DigitalCredit credit = (DigitalCredit) result.get("credit");
            if (credit != null) {
                // 更新债权状态为已验证
                updateCreditStatus(creditId, "verified");

                // 通知银行系统债权验证成功，可以进行贷款审批
                notifyBankForLoanEligibility(credit);

                result.put("message", "债权凭证验证成功，已自动通知银行系统进行贷款审批");
                log.info("债权验证成功并已通知银行系统，债权ID: {}", creditId);
            }
        }

        return result;
    }

    /**
     * 修复债权的数字签名（如果需要的话）
     *
     * @param creditId 债权ID
     */
    @Transactional
    private void fixSignatureIfNeeded(Long creditId) {
        try {
            DigitalCredit credit = digitalCreditMapper.selectDigitalCreditByCreditId(creditId);
            if (credit == null) {
                return;
            }

            // 生成新的签名
            String newSignature = generateDigitalSignature(credit);
            String currentSignature = credit.getDigitalSignature();

            // 如果签名不匹配，更新数据库中的签名
            if (currentSignature == null || !newSignature.equals(currentSignature)) {
                log.info("修复债权签名，债权ID: {}, 旧签名: {}, 新签名: {}",
                        creditId, currentSignature, newSignature);

                // 更新数据库中的签名
                digitalCreditMapper.updateDigitalSignature(creditId, newSignature, SecurityUtils.getUsername());

                log.info("成功修复债权签名，债权ID: {}", creditId);
            }
        } catch (Exception e) {
            log.error("修复债权签名失败，债权ID: {}", creditId, e);
            throw e;
        }
    }

    /**
     * 通知银行系统债权验证成功，可以进行贷款审批 只有同时满足债权验证和服务周期贷款信息的债权才能进行贷款
     */
    private void notifyBankForLoanEligibility(DigitalCredit credit) {
        try {
            // 检查是否有对应的服务周期贷款信息
            boolean hasServicePeriodLoan = checkServicePeriodLoanExists(credit.getContractId());

            if (hasServicePeriodLoan) {
                // 创建贷款资格记录，供银行管理界面查询
                createLoanEligibilityRecord(credit);
                log.info("债权ID: {} 已具备贷款资格，已通知银行系统", credit.getCreditId());
            } else {
                log.warn("债权ID: {} 缺少服务周期贷款信息，暂不具备贷款资格", credit.getCreditId());
            }
        } catch (Exception e) {
            log.error("通知银行系统失败", e);
        }
    }

    /**
     * 检查是否存在服务周期贷款信息 银行贷款需要同时满足：1.债权验证通过 2.有服务周期贷款申请
     */
    private boolean checkServicePeriodLoanExists(Long contractId) {
        try {
            // 这里需要调用服务周期管理服务检查贷款信息
            // 实际实现需要查询 dc_service_period_loan 表
            // ServicePeriodLoan loan = servicePeriodLoanMapper.selectByContractId(contractId);
            // return loan != null && "ACTIVE".equals(loan.getLoanStatus());

            // 暂时返回true，实际实现需要查询服务周期贷款表
            log.info("检查合同ID: {} 的服务周期贷款信息", contractId);
            return true;
        } catch (Exception e) {
            log.error("检查服务周期贷款信息失败", e);
            return false;
        }
    }

    /**
     * 创建贷款资格记录，供银行管理界面查询 银行界面只显示同时满足债权确认和服务周期贷款的记录
     */
    private void createLoanEligibilityRecord(DigitalCredit credit) {
        try {
            // 创建贷款资格记录，供银行系统查询
            // 实际实现需要：
            // 1. 插入到贷款资格表 dc_loan_eligibility
            // 2. 包含债权ID、合同ID、资格状态、创建时间等信息
            // 3. 银行管理界面通过此表查询可贷款的债权

            log.info("为债权 {} 创建贷款资格记录，银行可进行贷款审批", credit.getCreditId());

            // LoanEligibility eligibility = new LoanEligibility();
            // eligibility.setCreditId(credit.getCreditId());
            // eligibility.setContractId(credit.getContractId());
            // eligibility.setEligibilityStatus("ELIGIBLE");
            // eligibility.setCreateTime(new Date());
            // loanEligibilityMapper.insert(eligibility);
        } catch (Exception e) {
            log.error("创建贷款资格记录失败", e);
        }
    }

    /**
     * 获取债权验证历史
     *
     * @param creditId 债权ID
     * @return 验证历史列表
     */
    @Override
    public List<Map<String, Object>> getValidationHistory(Long creditId) {
        log.info("获取债权验证历史，债权ID: {}", creditId);

        // 这里应该从数据库查询验证历史记录
        // 为了演示，先返回模拟数据
        List<Map<String, Object>> history = new ArrayList<>();

        // 实际实现中，这里应该查询验证历史表
        // List<ValidationHistory> historyRecords = validationHistoryMapper.selectByCreditsId(creditId);
        return history;
    }

    /**
     * 执行完整性验证
     */
    private boolean performIntegrityValidation(DigitalCredit credit, StringBuilder errorMessage, Map<String, Object> details) {
        boolean isValid = true;

        // 1. 验证债权状态
        if (CREDIT_STATUS_EXPIRED.equals(credit.getCreditStatus())
                || CREDIT_STATUS_CANCELLED.equals(credit.getCreditStatus())) {
            isValid = false;
            errorMessage.append("债权凭证已失效，状态: ").append(credit.getCreditStatus()).append("; ");
        }

        // 2. 验证到期日期
        if (credit.getMaturityDate() != null && credit.getMaturityDate().before(new Date())) {
            isValid = false;
            errorMessage.append("债权凭证已过期; ");
        }

        // 3. 验证关联合同
        Contract contract = contractMapper.selectContractByContractId(credit.getContractId());
        if (contract == null) {
            isValid = false;
            errorMessage.append("关联合同不存在; ");
        }

        details.put("statusValid", !CREDIT_STATUS_EXPIRED.equals(credit.getCreditStatus())
                && !CREDIT_STATUS_CANCELLED.equals(credit.getCreditStatus()));
        details.put("dateValid", credit.getMaturityDate() == null || !credit.getMaturityDate().before(new Date()));
        details.put("contractValid", contract != null);

        return isValid;
    }

    /**
     * 执行数字签名验证
     */
    private boolean performSignatureValidation(DigitalCredit credit, StringBuilder errorMessage, Map<String, Object> details) {
        boolean isValid = true;

        try {
            // 验证数字签名
            String expectedSignature = generateDigitalSignature(credit);
            String actualSignature = credit.getDigitalSignature();
            boolean signatureValid = expectedSignature.equals(actualSignature);

            log.debug("签名验证 - 期望签名: {}", expectedSignature);
            log.debug("签名验证 - 实际签名: {}", actualSignature);
            log.debug("签名验证结果: {}", signatureValid);

            if (!signatureValid) {
                isValid = false;
                errorMessage.append("数字签名验证失败; ");
                log.warn("数字签名验证失败，债权ID: {}, 期望: {}, 实际: {}",
                        credit.getCreditId(), expectedSignature, actualSignature);
            }

            details.put("expectedSignature", expectedSignature);
            details.put("actualSignature", actualSignature);
            details.put("signatureValid", signatureValid);

        } catch (Exception e) {
            isValid = false;
            errorMessage.append("数字签名验证异常: ").append(e.getMessage()).append("; ");
            log.error("数字签名验证异常，债权ID: {}", credit.getCreditId(), e);

            details.put("signatureValid", false);
            details.put("signatureError", e.getMessage());
        }

        return isValid;
    }

    /**
     * 执行区块链验证
     */
    private boolean performBlockchainValidation(DigitalCredit credit, StringBuilder errorMessage, Map<String, Object> details) {
        boolean isValid = true;

        // 这里应该调用区块链服务进行验证
        // 暂时模拟验证逻辑
        boolean blockchainValid = true; // 实际应该调用区块链验证服务

        if (!blockchainValid) {
            isValid = false;
            errorMessage.append("区块链验证失败; ");
        }

        details.put("blockchainValid", blockchainValid);
        details.put("blockchainHash", "mock_blockchain_hash"); // 实际应该从区块链获取

        return isValid;
    }

    /**
     * 执行综合验证
     */
    private boolean performComprehensiveValidation(DigitalCredit credit, StringBuilder errorMessage, Map<String, Object> details) {
        boolean isValid = true;

        // 执行所有类型的验证
        isValid &= performIntegrityValidation(credit, errorMessage, details);
        isValid &= performSignatureValidation(credit, errorMessage, details);
        isValid &= performBlockchainValidation(credit, errorMessage, details);

        // 验证债权完整性
        if (!validateCreditIntegrity(credit.getCreditId())) {
            isValid = false;
            errorMessage.append("债权数据完整性验证失败; ");
        }

        details.put("integrityCheckPassed", validateCreditIntegrity(credit.getCreditId()));

        return isValid;
    }

    /**
     * 生成验证码
     */
    private String generateValidationCode() {
        return "VAL-" + System.currentTimeMillis();
    }

    /**
     * 记录验证历史
     */
    private void recordValidationHistory(Long creditId, Map<String, Object> validationResult) {
        try {
            // 这里应该将验证结果保存到验证历史表
            // ValidationHistory history = new ValidationHistory();
            // history.setCreditId(creditId);
            // history.setValidationType((String) validationResult.get("validationType"));
            // history.setValidationResult((Boolean) validationResult.get("valid"));
            // history.setValidationMessage((String) validationResult.get("message"));
            // history.setValidatedBy((String) validationResult.get("validatedBy"));
            // history.setValidatedAt((Date) validationResult.get("validatedAt"));
            // validationHistoryMapper.insert(history);

            log.info("验证历史已记录，债权ID: {}", creditId);
        } catch (Exception e) {
            log.error("记录验证历史失败", e);
        }
    }

    /**
     * 更新债权状态
     *
     * @param creditId 债权ID
     * @param status 新状态
     * @return 操作结果
     */
    @Override
    @Transactional
    public boolean updateCreditStatus(Long creditId, String status) {
        log.info("更新债权状态，债权ID: {}, 新状态: {}", creditId, status);

        // 验证状态值
        if (!isValidCreditStatus(status)) {
            throw new RuntimeException("无效的债权状态: " + status);
        }

        // 创建更新对象，设置必要的字段
        DigitalCredit updateCredit = new DigitalCredit();
        updateCredit.setCreditId(creditId);
        updateCredit.setCreditStatus(status);
        updateCredit.setUpdateBy(SecurityUtils.getUsername());
        updateCredit.setUpdateTime(new Date());

        int result = digitalCreditMapper.updateDigitalCredit(updateCredit);
        if (result <= 0) {
            log.error("更新债权状态失败，债权ID: {}", creditId);
            return false;
        }

        log.info("成功更新债权状态，债权ID: {}, 新状态: {}", creditId, status);
        return true;
    }

    /**
     * 计算债权金额
     *
     * @param contractId 合同ID
     * @return 债权金额
     */
    @Override
    public BigDecimal calculateCreditAmount(Long contractId) {
        Contract contract = contractMapper.selectContractByContractId(contractId);
        if (contract == null) {
            throw new RuntimeException("合同不存在: " + contractId);
        }

        // 债权金额等于合同金额
        return contract.getContractAmount();
    }

    /**
     * 生成数字签名
     *
     * @param creditData 债权数据
     * @return 数字签名
     */
    @Override
    public String generateDigitalSignature(DigitalCredit creditData) {
        try {
            // 构建签名数据 - 只使用不会变化的核心字段
            StringBuilder data = new StringBuilder();

            // 使用安全的字段拼接，避免null值
            data.append(creditData.getCreditNumber() != null ? creditData.getCreditNumber() : "")
                    .append("|")
                    .append(creditData.getContractId() != null ? creditData.getContractId().toString() : "")
                    .append("|")
                    .append(creditData.getCreditAmount() != null ? creditData.getCreditAmount().toString() : "")
                    .append("|")
                    .append(creditData.getCreditorName() != null ? creditData.getCreditorName() : "")
                    .append("|")
                    .append(creditData.getDebtorName() != null ? creditData.getDebtorName() : "");

            log.debug("签名数据: {}", data.toString());

            // 使用SHA-256生成哈希
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(data.toString().getBytes("UTF-8"));

            // 转换为十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }

            String signature = hexString.toString();
            log.debug("生成的签名: {}", signature);
            return signature;
        } catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
            log.error("生成数字签名失败", e);
            throw new RuntimeException("生成数字签名失败: " + e.getMessage());
        }
    }

    /**
     * 从合同转换生成债权 - Contract版本
     *
     * @param contract 合同
     * @return 生成的债权凭证
     */
    public DigitalCredit convertContractToCredit(Contract contract) {
        log.info("从合同转换生成债权，合同ID: {}", contract.getContractId());

        DigitalCredit credit = new DigitalCredit();

        // 生成债权编号
        credit.setCreditNumber(generateCreditNumber());

        // 设置关联合同信息
        credit.setContractId(contract.getContractId());
        credit.setContractNumber(contract.getContractNumber());

        // 获取债权人信息（安保公司）
        credit.setCreditorName(contract.getSecurityCompany());
        credit.setCreditorId(contract.getSecurityCompanyId() != null ? contract.getSecurityCompanyId()
                : (contract.getSecurityCompany() != null ? (long) contract.getSecurityCompany().hashCode() : 0L));

        // 获取债务人信息（甲方单位）
        credit.setDebtorName(contract.getClientCompany());
        credit.setDebtorId(contract.getClientCompanyId() != null ? contract.getClientCompanyId()
                : (contract.getClientCompany() != null ? (long) contract.getClientCompany().hashCode() : 0L));

        // 计算债权金额
        credit.setCreditAmount(contract.getContractAmount());

        // 设置发行日期为当前日期
        credit.setIssueDate(DateUtils.getNowDate());

        // 设置到期日期为合同服务结束日期后一年（可根据业务需求调整）
        java.util.Calendar cal = java.util.Calendar.getInstance();
        cal.setTime(contract.getEndDate());
        cal.add(java.util.Calendar.YEAR, 1);
        credit.setMaturityDate(cal.getTime());

        // 设置初始状态
        credit.setCreditStatus("VALID");

        // 设置描述
        credit.setDescription("基于合同 " + contract.getContractNumber() + " 生成的数字债权凭证");

        // 设置创建信息
        try {
            String currentUser = SecurityUtils.getUsername();
            log.info("convertContractToCredit - 当前登录用户: {}", currentUser);
            credit.setCreateBy(currentUser);
        } catch (Exception e) {
            log.error("convertContractToCredit - 获取当前用户失败", e);
            credit.setCreateBy("system"); // 设置默认值
        }
        credit.setCreateTime(DateUtils.getNowDate());

        // 生成数字签名
        String digitalSignature = generateDigitalSignature(credit);
        credit.setDigitalSignature(digitalSignature);

        log.info("成功从合同转换生成债权，债权编号: {}", credit.getCreditNumber());
        return credit;
    }

    /**
     * 从合同自动转换生成债权 - ServiceContract版本（保持兼容性）
     *
     * @param contract 服务合同
     * @return 生成的债权凭证
     */
    @Override
    public DigitalCredit convertContractToCredit(ServiceContract contract) {
        log.info("从合同转换生成债权，合同ID: {}", contract.getContractId());

        DigitalCredit credit = new DigitalCredit();

        // 生成债权编号
        credit.setCreditNumber(generateCreditNumber());

        // 设置关联合同信息
        credit.setContractId(contract.getContractId());
        credit.setContractNumber(contract.getContractNumber());

        // 获取债权人信息（安保公司）
        // 由于现在使用公司名称而不是ID，直接使用名称
        credit.setCreditorName(contract.getSecurityCompany());
        // 为了保持兼容性，可以生成一个临时ID或使用哈希值
        credit.setCreditorId(contract.getSecurityCompany() != null ? (long) contract.getSecurityCompany().hashCode() : 0L);

        // 获取债务人信息（甲方单位）
        // 由于现在使用公司名称而不是ID，直接使用名称
        credit.setDebtorName(contract.getClientCompany());
        // 为了保持兼容性，可以生成一个临时ID或使用哈希值
        credit.setDebtorId(contract.getClientCompany() != null ? (long) contract.getClientCompany().hashCode() : 0L);

        // 计算债权金额
        credit.setCreditAmount(contract.getContractAmount());

        // 设置发行日期为当前日期
        credit.setIssueDate(DateUtils.getNowDate());

        // 设置到期日期为合同付款到期日
        credit.setMaturityDate(contract.getPaymentDueDate());

        // 设置初始状态
        credit.setCreditStatus(CREDIT_STATUS_ACTIVE);

        // 设置创建信息
        try {
            String currentUser = SecurityUtils.getUsername();
            log.info("convertContractToCredit - 当前登录用户: {}", currentUser);
            credit.setCreateBy(currentUser);
        } catch (Exception e) {
            log.error("convertContractToCredit - 获取当前用户失败", e);
            credit.setCreateBy("system"); // 设置默认值
        }
        credit.setCreateTime(DateUtils.getNowDate());

        // 生成数字签名 - 确保在所有字段设置完成后生成
        try {
            String signature = generateDigitalSignature(credit);
            credit.setDigitalSignature(signature);
            log.debug("为转换的债权生成数字签名: {}", signature);
        } catch (Exception e) {
            log.error("生成数字签名失败", e);
            throw new RuntimeException("生成数字签名失败: " + e.getMessage());
        }

        log.debug("债权转换完成: {}", credit.toString());
        return credit;
    }

    /**
     * 验证债权完整性
     *
     * @param creditId 债权ID
     * @return 验证结果
     */
    @Override
    public boolean validateCreditIntegrity(Long creditId) {
        try {
            return digitalCreditMapper.validateCreditIntegrity(creditId);
        } catch (Exception e) {
            log.error("验证债权完整性失败，债权ID: {}", creditId, e);
            return false;
        }
    }

    /**
     * 生成债权编号
     *
     * @return 债权编号
     */
    private String generateCreditNumber() {
        // 格式: CR + YYYYMMDD + 6位序号
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String dateStr = sdf.format(new Date());

        // 生成6位随机序号
        int sequence = (int) (Math.random() * 900000) + 100000;

        String creditNumber = "CR" + dateStr + sequence;

        // 确保编号唯一性
        while (!checkCreditNumberUnique(creditNumber)) {
            sequence = (int) (Math.random() * 900000) + 100000;
            creditNumber = "CR" + dateStr + sequence;
        }

        log.debug("生成债权编号: {}", creditNumber);
        return creditNumber;
    }

    /**
     * 验证债权状态是否有效
     *
     * @param status 状态
     * @return 是否有效
     */
    private boolean isValidCreditStatus(String status) {
        return CREDIT_STATUS_ACTIVE.equals(status)
                || CREDIT_STATUS_USED.equals(status)
                || CREDIT_STATUS_EXPIRED.equals(status)
                || CREDIT_STATUS_SETTLED.equals(status)
                || CREDIT_STATUS_CANCELLED.equals(status)
                || "verified".equals(status)
                || "generated".equals(status);
    }

    // 以下是查询相关方法的实现
    @Override
    public DigitalCredit selectDigitalCreditByCreditId(Long creditId) {
        return digitalCreditMapper.selectDigitalCreditByCreditId(creditId);
    }

    @Override
    public List<DigitalCredit> selectDigitalCreditList(DigitalCredit digitalCredit) {
        List<DigitalCredit> result = digitalCreditMapper.selectDigitalCreditList(digitalCredit);
        // 确保永远不返回null，如果mapper返回null则返回空列表
        return result != null ? result : new ArrayList<>();
    }

    @Override
    public DigitalCredit selectDigitalCreditByCreditNumber(String creditNumber) {
        return digitalCreditMapper.selectDigitalCreditByCreditNumber(creditNumber);
    }

    @Override
    public DigitalCredit selectDigitalCreditByContractId(Long contractId) {
        return digitalCreditMapper.selectDigitalCreditByContractId(contractId);
    }

    @Override
    public List<DigitalCredit> selectDigitalCreditByStatus(String creditStatus) {
        List<DigitalCredit> result = digitalCreditMapper.selectDigitalCreditByStatus(creditStatus);
        // 确保永远不返回null，如果mapper返回null则返回空列表
        return result != null ? result : new ArrayList<>();
    }

    @Override
    public List<DigitalCredit> selectExpiringCredits(int days) {
        List<DigitalCredit> result = digitalCreditMapper.selectExpiringCredits(days);
        // 确保永远不返回null，如果mapper返回null则返回空列表
        return result != null ? result : new ArrayList<>();
    }

    @Override
    @Transactional
    public int deleteDigitalCreditByCreditId(Long creditId) {
        log.info("删除债权，债权ID: {}", creditId);
        return digitalCreditMapper.deleteDigitalCreditByCreditId(creditId);
    }

    @Override
    @Transactional
    public int deleteDigitalCreditByCreditIds(Long[] creditIds) {
        log.info("批量删除债权，债权ID数组: {}", java.util.Arrays.toString(creditIds));
        return digitalCreditMapper.deleteDigitalCreditByCreditIds(creditIds);
    }

    @Override
    public boolean checkCreditNumberUnique(String creditNumber) {
        boolean isUnique = digitalCreditMapper.checkCreditNumberUnique(creditNumber);
        return isUnique;
    }

    /**
     * 批量修复所有债权的数字签名 用于修复历史数据的签名问题
     *
     * @return 修复的记录数
     */
    @Transactional
    public int fixAllCreditSignatures() {
        log.info("开始批量修复所有债权的数字签名");

        try {
            // 查询所有债权
            List<DigitalCredit> allCredits = digitalCreditMapper.selectDigitalCreditList(new DigitalCredit());
            int fixedCount = 0;

            for (DigitalCredit credit : allCredits) {
                try {
                    // 生成新的签名
                    String newSignature = generateDigitalSignature(credit);
                    String currentSignature = credit.getDigitalSignature();

                    // 如果签名不匹配，更新数据库中的签名
                    if (currentSignature == null || !newSignature.equals(currentSignature)) {
                        digitalCreditMapper.updateDigitalSignature(credit.getCreditId(), newSignature, SecurityUtils.getUsername());
                        fixedCount++;
                        log.info("修复债权签名，债权ID: {}, 债权编号: {}", credit.getCreditId(), credit.getCreditNumber());
                    }
                } catch (Exception e) {
                    log.error("修复债权签名失败，债权ID: {}, 债权编号: {}", credit.getCreditId(), credit.getCreditNumber(), e);
                }
            }

            log.info("批量修复债权签名完成，共修复 {} 条记录", fixedCount);
            return fixedCount;
        } catch (Exception e) {
            log.error("批量修复债权签名失败", e);
            throw new RuntimeException("批量修复债权签名失败: " + e.getMessage());
        }
    }

    /**
     * 根据债权ID重新生成债权凭证 用于在债权被删除后重新生成
     *
     * @param creditId 债权ID
     * @return 重新生成的债权凭证
     */
    @Override
    @Transactional
    public DigitalCredit regenerateCreditById(Long creditId) {
        log.info("尝试根据债权ID重新生成债权凭证，债权ID: {}", creditId);

        try {
            // 方法1: 尝试通过历史记录或备份表查找原始合同ID
            Long contractId = findContractIdByDeletedCredit(creditId);

            if (contractId != null) {
                log.info("找到原始合同ID: {}，开始重新生成债权", contractId);

                // 查询合同信息
                Contract contract = contractMapper.selectContractByContractId(contractId);
                if (contract != null) {
                    // 重新生成债权凭证
                    DigitalCredit newCredit = convertContractToCredit(contract);

                    // 保持原来的债权ID（如果可能的话）
                    newCredit.setCreditId(creditId);

                    // 保存新的债权凭证
                    int result = digitalCreditMapper.insertDigitalCredit(newCredit);
                    if (result > 0) {
                        log.info("成功重新生成债权凭证，债权ID: {}, 债权编号: {}", creditId, newCredit.getCreditNumber());
                        return newCredit;
                    } else {
                        throw new RuntimeException("保存重新生成的债权凭证失败");
                    }
                } else {
                    throw new RuntimeException("找不到对应的合同信息，合同ID: " + contractId);
                }
            } else {
                // 方法2: 如果找不到历史记录，尝试通过债权ID推断可能的合同ID
                // 这是一个备用方案，假设债权ID和合同ID有某种关联
                log.warn("无法找到债权ID {} 对应的合同信息，尝试备用方案", creditId);

                // 可以尝试查找最近的合同或者让用户手动指定
                // 这里提供一个简单的实现：查找状态为已确认的合同
                List<Contract> confirmedContracts = contractMapper.selectConfirmedContracts();
                if (!confirmedContracts.isEmpty()) {
                    // 选择第一个已确认的合同作为示例
                    Contract contract = confirmedContracts.get(0);
                    log.info("使用合同ID {} 重新生成债权", contract.getContractId());

                    DigitalCredit newCredit = convertContractToCredit(contract);
                    newCredit.setCreditId(creditId);

                    int result = digitalCreditMapper.insertDigitalCredit(newCredit);
                    if (result > 0) {
                        log.info("使用备用方案成功重新生成债权凭证，债权ID: {}", creditId);
                        return newCredit;
                    }
                }

                throw new RuntimeException("无法找到合适的合同来重新生成债权凭证");
            }
        } catch (Exception e) {
            log.error("重新生成债权凭证失败，债权ID: {}", creditId, e);
            throw new RuntimeException("重新生成债权凭证失败: " + e.getMessage());
        }
    }

    /**
     * 查找被删除债权对应的合同ID 可以通过日志表、历史表或其他方式查找
     *
     * @param creditId 债权ID
     * @return 合同ID
     */
    private Long findContractIdByDeletedCredit(Long creditId) {
        try {
            // 方法1: 查询操作日志表（如果有的话）
            // 这里需要根据实际的日志表结构来实现
            // Long contractId = operationLogMapper.findContractIdByCreditId(creditId);

            // 方法2: 查询历史备份表（如果有的话）
            // Long contractId = creditHistoryMapper.findContractIdByCreditId(creditId);
            // 方法3: 通过其他业务逻辑推断
            // 这里可以根据业务规则来推断合同ID
            // 暂时返回null，表示无法找到
            // 实际实现中应该根据具体的数据结构来查找
            log.debug("尝试查找债权ID {} 对应的合同ID", creditId);

            // 如果有审计日志或历史表，可以在这里查询
            // 目前返回null，让系统使用备用方案
            return null;

        } catch (Exception e) {
            log.error("查找被删除债权对应的合同ID失败", e);
            return null;
        }
    }
}
