package com.ruoyi.credit.service.impl;

import java.math.BigDecimal;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
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 org.springframework.web.multipart.MultipartFile;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.credit.domain.Contract;
import com.ruoyi.credit.domain.ServiceContract;
import com.ruoyi.credit.domain.ServicePeriod;
import com.ruoyi.credit.domain.ServicePeriodLoan;
import com.ruoyi.credit.mapper.ContractMapper;
import com.ruoyi.credit.mapper.ServiceContractMapper;
import com.ruoyi.credit.mapper.ServicePeriodLoanMapper;
import com.ruoyi.credit.mapper.ServicePeriodMapper;
import com.ruoyi.credit.service.IContractService;
import com.ruoyi.framework.security.context.DepartmentContextHolder;
import com.ruoyi.framework.security.validator.DepartmentPermissionValidator;

/**
 * 合同管理服务实现
 * 
 * @author ruoyi
 * @date 2025-12-19
 */
@Service
public class ContractServiceImpl implements IContractService 
{
    private static final Logger log = LoggerFactory.getLogger(ContractServiceImpl.class);

    @Autowired
    private ContractMapper contractMapper;

    @Autowired
    private ServiceContractMapper serviceContractMapper;

    @Autowired
    private ServicePeriodMapper servicePeriodMapper;

    @Autowired
    private ServicePeriodLoanMapper servicePeriodLoanMapper;

    @Autowired
    private DepartmentPermissionValidator departmentPermissionValidator;

    private final ObjectMapper objectMapper = new ObjectMapper();

    // 合同状态常量
    public static final String CONTRACT_STATUS_DRAFT = "DRAFT";           // 草稿
    public static final String CONTRACT_STATUS_PENDING = "PENDING";       // 待确认
    public static final String CONTRACT_STATUS_CONFIRMED = "CONFIRMED";   // 已确认
    public static final String CONTRACT_STATUS_COMPLETED = "COMPLETED";   // 已完成
    public static final String CONTRACT_STATUS_CANCELLED = "CANCELLED";   // 已取消

    // 合同类型常量
    public static final String CONTRACT_TYPE_ONLINE = "ONLINE";           // 线上创建
    public static final String CONTRACT_TYPE_OFFLINE = "OFFLINE";         // 线下签署

    // 合同来源常量
    public static final String CONTRACT_SOURCE_PLATFORM_CREATED = "PLATFORM_CREATED";  // 平台创建
    public static final String CONTRACT_SOURCE_UPLOADED = "UPLOADED";                  // 上传

    // 确认方类型常量
    public static final String PARTY_TYPE_SECURITY_COMPANY = "SECURITY_COMPANY";
    public static final String PARTY_TYPE_CLIENT_COMPANY = "CLIENT_COMPANY";

    // 支持的文件类型
    private static final String[] SUPPORTED_FILE_TYPES = {".pdf", ".doc", ".docx", ".jpg", ".jpeg", ".png"};
    
    // 最大文件大小 (10MB)
    private static final long MAX_FILE_SIZE = 10 * 1024 * 1024;

    /**
     * 创建服务合同(线上创建) - 写入dc_contract表
     * 
     * @param contractInfo 合同信息
     * @return 创建的合同对象
     */
    @Override
    @Transactional
    public Contract createContract(Contract contractInfo)
    {
        log.info("开始创建线上服务合同: {}", contractInfo.toString());
        
        // 记录前端发送的完整数据
        log.info("前端发送的数据详情:");
        log.info("- 合同标题: {}", contractInfo.getTitle());
        log.info("- 安保公司: {}", contractInfo.getSecurityCompany());
        log.info("- 甲方单位: {}", contractInfo.getClientCompany());
        log.info("- 合同金额: {}", contractInfo.getContractAmount());
        log.info("- 服务开始日期: {}", contractInfo.getStartDate());
        log.info("- 服务结束日期: {}", contractInfo.getEndDate());
        log.info("- 合同期限: {}", contractInfo.getContractTerm());
        log.info("- 合同条款: {}", contractInfo.getContractTerms());
        log.info("- 服务类型: {}", contractInfo.getServiceType());
        log.info("- 服务内容: {}", contractInfo.getServiceContent());
        log.info("- 付款到期日: {}", contractInfo.getPaymentDueDate());
        
        // 验证合同数据
        Map<String, Object> validationResult = validateContractData(contractInfo);
        if (!(Boolean) validationResult.get("valid")) {
            throw new RuntimeException("合同数据验证失败: " + validationResult.get("message"));
        }

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

        // 生成合同编号
        if (StringUtils.isEmpty(contractInfo.getContractNumber())) {
            contractInfo.setContractNumber(generateContractNumber());
        }

        // 校验合同编号唯一性
        if (!checkContractNumberUnique(contractInfo.getContractNumber())) {
            throw new RuntimeException("合同编号已存在: " + contractInfo.getContractNumber());
        }

        // 设置线上创建的合同属性
        contractInfo.setContractType("ONLINE");

        // 创建合同时始终设置为待确认状态，不允许前端指定状态
        String initialStatus = "PENDING";
        contractInfo.setContractStatus(initialStatus);

        // 设置创建信息
        contractInfo.setCreateBy(SecurityUtils.getUsername());
        contractInfo.setCreateTime(DateUtils.getNowDate());

        // 自动生成公司ID（如果前端没有提供的话）
        if (contractInfo.getSecurityCompanyId() == null) {
            // 基于公司名称生成一个唯一的ID
            contractInfo.setSecurityCompanyId(generateCompanyId(contractInfo.getSecurityCompany()));
            log.info("自动生成安保公司ID: {} for {}", contractInfo.getSecurityCompanyId(), contractInfo.getSecurityCompany());
        }
        
        if (contractInfo.getClientCompanyId() == null) {
            // 基于公司名称生成一个唯一的ID
            contractInfo.setClientCompanyId(generateCompanyId(contractInfo.getClientCompany()));
            log.info("自动生成甲方公司ID: {} for {}", contractInfo.getClientCompanyId(), contractInfo.getClientCompany());
        }

        // 保存合同到dc_contract表
        log.info("准备保存到dc_contract表，包含所有字段");
        int result = contractMapper.insertContract(contractInfo);
        if (result <= 0) {
            throw new RuntimeException("创建合同失败");
        }

        // 记录状态变更审计日志
        recordStatusChangeAudit(contractInfo.getContractId(), null, initialStatus, "线上合同创建，系统自动设置为待确认状态");

        log.info("成功创建线上服务合同，合同ID: {}, 合同编号: {}, 初始状态: {}", 
                contractInfo.getContractId(), contractInfo.getContractNumber(), initialStatus);
        
        return contractInfo;
    }

    /**
     * 上传已签署的线下合同 - 写入dc_contract表
     * 
     * @param contractFile 合同文件
     * @param contractInfo 合同基本信息
     * @return 上传的合同对象
     */
    @Override
    @Transactional
    public Contract uploadSignedContract(MultipartFile contractFile, Contract contractInfo)
    {
        log.info("开始上传线下签署合同，文件名: {}", contractFile.getOriginalFilename());
        
        // 1. 验证文件
        Map<String, Object> fileValidationResult = validateContractFile(contractFile);
        if (!(Boolean) fileValidationResult.get("valid")) {
            throw new RuntimeException("合同文件验证失败: " + fileValidationResult.get("message"));
        }

        // 2. 验证合同数据
        Map<String, Object> validationResult = validateContractData(contractInfo);
        if (!(Boolean) validationResult.get("valid")) {
            throw new RuntimeException("合同数据验证失败: " + validationResult.get("message"));
        }

        // 3. 生成合同编号
        if (StringUtils.isEmpty(contractInfo.getContractNumber())) {
            contractInfo.setContractNumber(generateContractNumber());
        }

        // 4. 校验合同编号唯一性
        if (!checkContractNumberUnique(contractInfo.getContractNumber())) {
            throw new RuntimeException("合同编号已存在: " + contractInfo.getContractNumber());
        }

        // 5. 设置线下合同属性
        contractInfo.setContractType("OFFLINE");
        contractInfo.setContractStatus("CONFIRMED"); // 线下合同默认为已确认状态

        // 6. 处理文件上传（这里简化处理，实际应该上传到文件服务器）
        try {
            String fileName = contractFile.getOriginalFilename();
            String fileHash = calculateFileHash(contractFile.getBytes());
            contractInfo.setFileUrl("/uploads/contracts/" + fileName);
            contractInfo.setContractFileHash(fileHash);
        } catch (Exception e) {
            throw new RuntimeException("处理合同文件失败: " + e.getMessage());
        }

        // 7. 设置创建信息
        contractInfo.setCreateBy(SecurityUtils.getUsername());
        contractInfo.setCreateTime(DateUtils.getNowDate());

        // 自动生成公司ID（如果前端没有提供的话）
        if (contractInfo.getSecurityCompanyId() == null) {
            contractInfo.setSecurityCompanyId(generateCompanyId(contractInfo.getSecurityCompany()));
            log.info("自动生成安保公司ID: {} for {}", contractInfo.getSecurityCompanyId(), contractInfo.getSecurityCompany());
        }
        
        if (contractInfo.getClientCompanyId() == null) {
            contractInfo.setClientCompanyId(generateCompanyId(contractInfo.getClientCompany()));
            log.info("自动生成甲方公司ID: {} for {}", contractInfo.getClientCompanyId(), contractInfo.getClientCompany());
        }

        // 8. 保存合同到dc_contract表
        int result = contractMapper.insertContract(contractInfo);
        if (result <= 0) {
            throw new RuntimeException("保存线下合同失败");
        }

        log.info("成功上传线下签署合同，合同ID: {}, 合同编号: {}", 
                contractInfo.getContractId(), contractInfo.getContractNumber());
        
        return contractInfo;
    }

    /**
     * 确认合同
     * 
     * @param contractId 合同ID
     * @param partyType 确认方类型
     * @return 操作结果
     */
    @Override
    @Transactional
    public boolean confirmContract(Long contractId, String partyType)
    {
        log.info("开始确认合同，合同ID: {}, 确认方类型: {}", contractId, partyType);
        
        // 查询合同 - 使用正确的 contractMapper 查询 dc_contract 表
        Contract contract = contractMapper.selectContractByContractId(contractId);
        if (contract == null) {
            throw new RuntimeException("合同不存在: " + contractId);
        }

        // 验证用户对该合同的访问权限
        departmentPermissionValidator.validateDataAccess(contractId, "dc_contract");

        // 验证合同状态
        if (!CONTRACT_STATUS_PENDING.equals(contract.getContractStatus())) {
            throw new RuntimeException("合同状态不允许确认，当前状态: " + contract.getContractStatus());
        }

        // 验证确认方类型
        if (!PARTY_TYPE_SECURITY_COMPANY.equals(partyType) && !PARTY_TYPE_CLIENT_COMPANY.equals(partyType)) {
            throw new RuntimeException("无效的确认方类型: " + partyType);
        }

        // 更新合同状态为已确认
        String oldStatus = contract.getContractStatus();
        String newStatus = CONTRACT_STATUS_CONFIRMED;
        
        // 使用 contractMapper 更新 dc_contract 表
        int result = contractMapper.updateContractStatus(contractId, newStatus);
        if (result <= 0) {
            log.error("确认合同失败，合同ID: {}", contractId);
            return false;
        }

        // 记录状态变更审计日志
        recordStatusChangeAudit(contractId, oldStatus, newStatus, "合同确认操作，确认方: " + partyType);

        log.info("成功确认合同，合同ID: {}, 状态变更: {} -> {}", 
                contractId, oldStatus, newStatus);
        
        return true;
    }

    /**
     * 更新合同状态
     * 
     * @param contractId 合同ID
     * @param status 新状态
     * @return 操作结果
     */
    @Override
    @Transactional
    public boolean updateContractStatus(Long contractId, String status)
    {
        log.info("更新合同状态，合同ID: {}, 新状态: {}", contractId, status);
        
        // 验证状态值
        if (!isValidContractStatus(status)) {
            throw new RuntimeException("无效的合同状态: " + status);
        }

        // 查询当前合同状态 - 使用正确的 contractMapper 查询 dc_contract 表
        Contract contract = contractMapper.selectContractByContractId(contractId);
        if (contract == null) {
            throw new RuntimeException("合同不存在: " + contractId);
        }

        // 验证状态转换是否合法
        if (!isValidStatusTransition(contract.getContractStatus(), status)) {
            throw new RuntimeException("不允许的状态转换: " + contract.getContractStatus() + " -> " + status);
        }

        String oldStatus = contract.getContractStatus();
        // 使用 contractMapper 更新 dc_contract 表
        int result = contractMapper.updateContractStatus(contractId, status);
        if (result <= 0) {
            log.error("更新合同状态失败，合同ID: {}", contractId);
            return false;
        }

        // 记录状态变更审计日志
        recordStatusChangeAudit(contractId, oldStatus, status, "系统状态更新操作");

        log.info("成功更新合同状态，合同ID: {}, 旧状态: {}, 新状态: {}", contractId, oldStatus, status);
        return true;
    }

    /**
     * 更新合同信息
     * 
     * @param serviceContract 合同信息
     * @return 操作结果
     */
    @Override
    @Transactional
    public boolean updateServiceContract(ServiceContract serviceContract)
    {
        log.info("更新合同信息，合同ID: {}", serviceContract.getContractId());
        
        // 验证合同是否存在
        ServiceContract existingContract = serviceContractMapper.selectServiceContractByContractId(serviceContract.getContractId());
        if (existingContract == null) {
            throw new RuntimeException("合同不存在: " + serviceContract.getContractId());
        }

        // 验证合同是否可以编辑
        if (!isContractEditable(existingContract.getContractStatus())) {
            throw new RuntimeException("当前状态的合同不允许编辑: " + existingContract.getContractStatus());
        }

        // 更新合同后重置状态为待确认
        serviceContract.setContractStatus("PENDING");
        serviceContract.setContractSource(existingContract.getContractSource());
        serviceContract.setCreateBy(existingContract.getCreateBy());
        serviceContract.setCreateTime(existingContract.getCreateTime());
        serviceContract.setUpdateBy(SecurityUtils.getUsername());
        serviceContract.setUpdateTime(DateUtils.getNowDate());

        // 如果合同编号发生变化，需要验证唯一性
        if (!existingContract.getContractNumber().equals(serviceContract.getContractNumber())) {
            if (!checkContractNumberUnique(serviceContract.getContractNumber())) {
                throw new RuntimeException("合同编号已存在: " + serviceContract.getContractNumber());
            }
        }

        int result = serviceContractMapper.updateServiceContract(serviceContract);
        if (result <= 0) {
            log.error("更新合同信息失败，合同ID: {}", serviceContract.getContractId());
            return false;
        }

        // 记录状态变更审计日志（如果状态发生了变化）
        if (!existingContract.getContractStatus().equals("PENDING")) {
            recordStatusChangeAudit(serviceContract.getContractId(), 
                                  existingContract.getContractStatus(), 
                                  "PENDING", 
                                  "合同信息更新，状态重置为待确认");
        }

        log.info("成功更新合同信息，合同ID: {}，状态重置为PENDING", serviceContract.getContractId());
        return true;
    }

    /**
     * 验证合同是否可以编辑
     * 
     * @param status 合同状态
     * @return 是否可编辑
     */
    private boolean isContractEditable(String status) {
        // 已完成、已取消、已过期的合同不允许编辑
        return !"COMPLETED".equals(status) && 
               !"CANCELLED".equals(status) && 
               !"EXPIRED".equals(status);
    }

    /**
     * 验证合同数据完整性
     * 
     * @param contractInfo 合同信息
     * @return 验证结果
     */
    public Map<String, Object> validateContractData(ServiceContract contractInfo)
    {
        Map<String, Object> result = new HashMap<>();
        StringBuilder errorMessage = new StringBuilder();
        boolean isValid = true;

        // 验证必填字段
        if (StringUtils.isBlank(contractInfo.getSecurityCompany())) {
            isValid = false;
            errorMessage.append("安保公司名称不能为空; ");
        }

        if (StringUtils.isBlank(contractInfo.getClientCompany())) {
            isValid = false;
            errorMessage.append("甲方单位名称不能为空; ");
        }

        // 服务内容验证 - 如果为空，尝试从合同条款生成
        if (StringUtils.isEmpty(contractInfo.getServiceContent())) {
            // 如果有合同条款，可以作为服务内容的默认值
            if (StringUtils.isNotEmpty(contractInfo.getRemark())) {
                contractInfo.setServiceContent(contractInfo.getRemark());
                log.info("服务内容为空，使用备注作为服务内容: {}", contractInfo.getRemark());
            } else {
                // 设置默认服务内容
                contractInfo.setServiceContent("安保服务");
                log.info("服务内容为空，设置默认服务内容: 安保服务");
            }
        }

        if (contractInfo.getContractAmount() == null || contractInfo.getContractAmount().compareTo(java.math.BigDecimal.ZERO) <= 0) {
            isValid = false;
            errorMessage.append("合同金额必须大于0; ");
        }

        if (contractInfo.getStartDate() == null) {
            isValid = false;
            errorMessage.append("服务开始日期不能为空; ");
        }

        if (contractInfo.getEndDate() == null) {
            isValid = false;
            errorMessage.append("服务结束日期不能为空; ");
        }

        if (contractInfo.getPaymentDueDate() == null) {
            isValid = false;
            errorMessage.append("付款到期日不能为空; ");
        }

        // 验证日期逻辑
        if (contractInfo.getStartDate() != null && contractInfo.getEndDate() != null) {
            if (contractInfo.getStartDate().after(contractInfo.getEndDate())) {
                isValid = false;
                errorMessage.append("服务开始日期不能晚于结束日期; ");
            }
        }

        // 修改付款到期日验证逻辑 - 允许付款到期日等于服务结束日期
        if (contractInfo.getEndDate() != null && contractInfo.getPaymentDueDate() != null) {
            if (contractInfo.getPaymentDueDate().before(contractInfo.getEndDate())) {
                isValid = false;
                errorMessage.append("付款到期日不能早于服务结束日期; ");
            }
        }

        // 验证业务规则
        if (StringUtils.isNotBlank(contractInfo.getSecurityCompany()) && StringUtils.isNotBlank(contractInfo.getClientCompany())) {
            if (contractInfo.getSecurityCompany().equals(contractInfo.getClientCompany())) {
                isValid = false;
                errorMessage.append("安保公司和甲方单位不能是同一个; ");
            }
        }

        result.put("valid", isValid);
        result.put("message", errorMessage.toString());
        
        log.debug("合同数据验证结果: {}", result);
        return result;
    }

    /**
     * 基于公司名称生成唯一的公司ID
     * 使用一致性哈希算法，确保相同名称总是生成相同的ID
     * 
     * @param companyName 公司名称
     * @return 生成的公司ID
     */
    private Long generateCompanyId(String companyName) {
        if (StringUtils.isEmpty(companyName)) {
            return 1000000L; // 默认ID
        }
        
        try {
            // 使用 MD5 哈希确保一致性
            java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
            byte[] hash = md.digest(companyName.getBytes("UTF-8"));
            
            // 取前8个字节转换为long
            long hashLong = 0;
            for (int i = 0; i < 8 && i < hash.length; i++) {
                hashLong = (hashLong << 8) | (hash[i] & 0xFF);
            }
            
            // 确保ID为正数，并且在合理范围内 (1000000-9999999)
            long companyId = Math.abs(hashLong) % 9000000 + 1000000;
            
            log.debug("为公司 '{}' 生成一致性ID: {}", companyName, companyId);
            return companyId;
            
        } catch (Exception e) {
            log.warn("生成公司ID时发生异常，使用备用方案: {}", e.getMessage());
            // 备用方案：使用简单哈希
            int hash = companyName.hashCode();
            long companyId = Math.abs((long) hash) % 9000000 + 1000000;
            return companyId;
        }
    }

    /**
     * 生成合同编号
     * 
     * @return 合同编号
     */
    @Override
    public String generateContractNumber()
    {
        // 格式: CT + YYYYMMDD + 6位序号
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String dateStr = sdf.format(new Date());
        
        // 生成6位随机序号
        int sequence = (int) (Math.random() * 900000) + 100000;
        
        String contractNumber = "CT" + dateStr + sequence;
        
        // 确保编号唯一性
        while (!checkContractNumberUnique(contractNumber)) {
            sequence = (int) (Math.random() * 900000) + 100000;
            contractNumber = "CT" + dateStr + sequence;
        }
        
        log.debug("生成合同编号: {}", contractNumber);
        return contractNumber;
    }

    /**
     * 查询合同详情
     */
    @Override
    public ServiceContract selectServiceContractByContractId(Long contractId)
    {
        ServiceContract contract = serviceContractMapper.selectServiceContractByContractId(contractId);
        if (contract != null) {
            // 验证用户是否有权限访问该合同
            departmentPermissionValidator.validateDataAccess(contractId, "dc_service_contract");
        }
        return contract;
    }

    /**
     * 查询合同列表
     */
    @Override
    public List<ServiceContract> selectServiceContractList(ServiceContract serviceContract)
    {
        log.debug("开始查询合同列表，查询条件: {}", serviceContract);
        
        try {
            // 输入参数验证 - 确保参数不为null
            if (serviceContract == null) {
                log.debug("查询参数为null，使用默认空查询条件");
                serviceContract = new ServiceContract();
            }
            
            // 应用部门过滤 - 非超级管理员只能查看自己部门的数据
            if (!DepartmentContextHolder.isSuperAdmin()) {
                Long currentDeptId = DepartmentContextHolder.getCurrentDeptId();
                if (currentDeptId != null) {
                    serviceContract.setDeptId(currentDeptId);
                    log.debug("应用部门过滤，部门ID: {}", currentDeptId);
                }
            }
            
            // 记录查询参数
            log.debug("查询参数详情 - 合同编号: {}, 状态: {}, 安保公司: {}, 甲方单位: {}, 部门ID: {}", 
                     serviceContract.getContractNumber(), 
                     serviceContract.getContractStatus(),
                     serviceContract.getSecurityCompany(),
                     serviceContract.getClientCompany(),
                     serviceContract.getDeptId());
            
            // 执行查询
            List<ServiceContract> result = serviceContractMapper.selectServiceContractList(serviceContract);
            
            // 确保永远不返回null
            if (result == null) {
                log.debug("Mapper返回null，转换为空列表");
                result = Collections.emptyList();
            }
            
            // 如果需要过滤有服务周期和员工贷款申请的合同
            if (serviceContract.getHasServicePeriod() != null && serviceContract.getHasServicePeriod() &&
                serviceContract.getHasEmployeeLoanApplication() != null && serviceContract.getHasEmployeeLoanApplication()) {
                result = filterContractsWithServicePeriodAndLoans(result);
            }
            
            // 记录查询结果统计
            log.debug("查询完成，返回记录数: {}", result.size());
            if (log.isDebugEnabled() && !result.isEmpty()) {
                log.debug("查询结果摘要 - 第一条记录ID: {}, 最后一条记录ID: {}", 
                         result.get(0).getContractId(), 
                         result.get(result.size() - 1).getContractId());
            }
            
            return result;
            
        } catch (Exception e) {
            // 异常情况下返回空列表而不是null
            log.error("查询合同列表异常，查询条件: {}, 错误信息: {}", serviceContract, e.getMessage(), e);
            log.info("异常恢复：返回空列表确保系统稳定性");
            return Collections.emptyList();
        }
    }

    /**
     * 根据合同编号查询合同
     */
    public ServiceContract selectServiceContractByContractNumber(String contractNumber)
    {
        return serviceContractMapper.selectServiceContractByContractNumber(contractNumber);
    }

    /**
     * 根据状态查询合同列表
     */
    public List<ServiceContract> selectServiceContractByStatus(String contractStatus)
    {
        return serviceContractMapper.selectServiceContractByStatus(contractStatus);
    }

    /**
     * 查询即将到期的合同
     */
    @Override
    public List<Contract> selectExpiringContracts(int days)
    {
        // 这里需要返回Contract类型的列表，而不是ServiceContract
        // 可以从基础合同表查询，或者转换ServiceContract到Contract
        return contractMapper.selectExpiringContracts(days);
    }

    /**
     * 删除合同
     */
    @Transactional
    public int deleteServiceContractByContractId(Long contractId)
    {
        log.info("删除合同，合同ID: {}", contractId);
        return serviceContractMapper.deleteServiceContractByContractId(contractId);
    }

    /**
     * 批量删除合同
     */
    @Override
    @Transactional
    public int deleteServiceContractByContractIds(Long[] contractIds)
    {
        log.info("批量删除合同，合同ID数组: {}", java.util.Arrays.toString(contractIds));
        return serviceContractMapper.deleteServiceContractByContractIds(contractIds);
    }

    /**
     * 校验合同编号唯一性
     */
    @Override
    public boolean checkContractNumberUnique(String contractNumber)
    {
        boolean isUnique = serviceContractMapper.checkContractNumberUnique(contractNumber);
        return isUnique;
    }

    /**
     * 验证上传合同文件的完整性和格式
     * 
     * @param contractFile 合同文件
     * @return 验证结果
     */
    @Override
    public Map<String, Object> validateContractFile(MultipartFile contractFile)
    {
        Map<String, Object> result = new HashMap<>();
        StringBuilder errorMessage = new StringBuilder();
        boolean isValid = true;

        // 1. 检查文件是否为空
        if (contractFile == null || contractFile.isEmpty()) {
            isValid = false;
            errorMessage.append("合同文件不能为空; ");
        } else {
            // 2. 检查文件大小
            if (contractFile.getSize() > MAX_FILE_SIZE) {
                isValid = false;
                errorMessage.append("文件大小不能超过10MB; ");
            }

            // 3. 检查文件类型
            String originalFilename = contractFile.getOriginalFilename();
            if (originalFilename == null || originalFilename.trim().isEmpty()) {
                isValid = false;
                errorMessage.append("文件名不能为空; ");
            } else {
                boolean supportedType = false;
                String lowerFilename = originalFilename.toLowerCase();
                for (String type : SUPPORTED_FILE_TYPES) {
                    if (lowerFilename.endsWith(type)) {
                        supportedType = true;
                        break;
                    }
                }
                if (!supportedType) {
                    isValid = false;
                    errorMessage.append("不支持的文件类型，支持的类型: PDF, DOC, DOCX, JPG, JPEG, PNG; ");
                }
            }

            // 4. 检查文件内容类型
            String contentType = contractFile.getContentType();
            if (StringUtils.isEmpty(contentType)) {
                isValid = false;
                errorMessage.append("无法识别文件类型; ");
            }
        }

        result.put("valid", isValid);
        result.put("message", errorMessage.toString());
        
        log.debug("合同文件验证结果: {}", result);
        return result;
    }

    /**
     * 从上传的合同文件中提取关键信息
     * 
     * @param contractFile 合同文件
     * @return 提取的信息
     */
    @Override
    public Map<String, Object> extractContractInfo(MultipartFile contractFile)
    {
        Map<String, Object> extractedInfo = new HashMap<>();
        
        try {
            // 这里是一个简化的实现，实际应该使用OCR或文档解析技术
            String filename = contractFile.getOriginalFilename();
            String safeFilename = StringUtils.isEmpty(filename) ? "unknown_file" : filename;
            long fileSize = contractFile.getSize();
            String contentType = contractFile.getContentType();
            String safeContentType = StringUtils.isEmpty(contentType) ? "application/octet-stream" : contentType;
            
            // 模拟提取的关键信息
            extractedInfo.put("filename", safeFilename);
            extractedInfo.put("fileSize", fileSize);
            extractedInfo.put("contentType", safeContentType);
            extractedInfo.put("extractedDate", DateUtils.getNowDate());
            
            // 模拟提取的合同要素(实际应该通过OCR等技术提取)
            extractedInfo.put("partyA", "待识别甲方");
            extractedInfo.put("partyB", "待识别乙方");
            extractedInfo.put("contractAmount", "待识别金额");
            extractedInfo.put("serviceContent", "待识别服务内容");
            extractedInfo.put("contractPeriod", "待识别合同期限");
            
            // 生成信息摘要
            StringBuilder summary = new StringBuilder();
            summary.append("文件名: ").append(safeFilename)
                   .append(", 大小: ").append(fileSize).append("字节")
                   .append(", 类型: ").append(safeContentType)
                   .append(", 提取时间: ").append(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.getNowDate()));
            
            extractedInfo.put("summary", summary.toString());
            
            log.info("成功提取合同文件信息: {}", extractedInfo);
            
        } catch (Exception e) {
            log.error("提取合同文件信息失败", e);
            extractedInfo.put("error", "信息提取失败: " + e.getMessage());
            extractedInfo.put("summary", "信息提取失败");
        }
        
        return extractedInfo;
    }

    /**
     * 关联线下合同与平台记录
     * 
     * @param contractId 合同ID
     * @param uploadedFileId 上传文件ID
     * @return 操作结果
     */
    @Override
    @Transactional
    public boolean linkOfflineContract(Long contractId, Long uploadedFileId)
    {
        log.info("关联线下合同与平台记录，合同ID: {}, 文件ID: {}", contractId, uploadedFileId);
        
        try {
            // 更新合同的附件ID
            ServiceContract contract = serviceContractMapper.selectServiceContractByContractId(contractId);
            if (contract == null) {
                throw new RuntimeException("合同不存在: " + contractId);
            }
            
            contract.setAttachmentId(uploadedFileId);
            contract.setUpdateBy(SecurityUtils.getUsername());
            contract.setUpdateTime(DateUtils.getNowDate());
            
            int result = serviceContractMapper.updateServiceContract(contract);
            if (result <= 0) {
                log.error("关联线下合同失败，合同ID: {}", contractId);
                return false;
            }
            
            log.info("成功关联线下合同，合同ID: {}, 文件ID: {}", contractId, uploadedFileId);
            return true;
            
        } catch (RuntimeException e) {
            log.error("关联线下合同异常", e);
            return false;
        }
    }

    /**
     * 验证合同状态是否有效
     * 
     * @param status 状态
     * @return 是否有效
     */
    private boolean isValidContractStatus(String status)
    {
        return CONTRACT_STATUS_DRAFT.equals(status) ||
               CONTRACT_STATUS_PENDING.equals(status) ||
               CONTRACT_STATUS_CONFIRMED.equals(status) ||
               CONTRACT_STATUS_COMPLETED.equals(status) ||
               CONTRACT_STATUS_CANCELLED.equals(status);
    }

    /**
     * 计算数据哈希
     * 
     * @param contract 合同对象
     * @return 数据哈希
     */
    private String calculateDataHash(ServiceContract contract)
    {
        // 简单的哈希计算，实际应该使用更安全的算法
        StringBuilder data = new StringBuilder();
        data.append(contract.getSecurityCompany())
            .append(contract.getClientCompany())
            .append(contract.getServiceContent())
            .append(contract.getContractAmount())
            .append(contract.getStartDate())
            .append(contract.getEndDate())
            .append(contract.getPaymentDueDate());
        
        return String.valueOf(data.toString().hashCode());
    }

    /**
     * 计算文件哈希值
     * 
     * @param fileContent 文件内容
     * @return 哈希值
     */
    private String calculateFileHash(byte[] fileContent) 
    {
        try {
            java.security.MessageDigest md = java.security.MessageDigest.getInstance("SHA-256");
            byte[] hash = md.digest(fileContent);
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            log.error("计算文件哈希值失败", e);
            return "hash_error_" + System.currentTimeMillis();
        }
    }

    /**
     * 验证状态转换是否合法
     * 
     * @param currentStatus 当前状态
     * @param newStatus 新状态
     * @return 是否合法
     */
    private boolean isValidStatusTransition(String currentStatus, String newStatus)
    {
        // 如果状态相同，允许（幂等操作）
        if (currentStatus.equals(newStatus)) {
            return true;
        }

        // 定义合法的状态转换规则
        switch (currentStatus) {
            case CONTRACT_STATUS_DRAFT:
                // 草稿状态可以转换为待确认或取消
                return CONTRACT_STATUS_PENDING.equals(newStatus) || 
                       CONTRACT_STATUS_CANCELLED.equals(newStatus);
                       
            case CONTRACT_STATUS_PENDING:
                // 待确认状态可以转换为已确认或取消
                return CONTRACT_STATUS_CONFIRMED.equals(newStatus) || 
                       CONTRACT_STATUS_CANCELLED.equals(newStatus);
                       
            case CONTRACT_STATUS_CONFIRMED:
                // 已确认状态可以转换为已完成或取消
                return CONTRACT_STATUS_COMPLETED.equals(newStatus) || 
                       CONTRACT_STATUS_CANCELLED.equals(newStatus);
                       
            case CONTRACT_STATUS_COMPLETED:
                // 已完成状态只能转换为取消（特殊情况）
                return CONTRACT_STATUS_CANCELLED.equals(newStatus);
                
            case CONTRACT_STATUS_CANCELLED:
                // 已取消状态不能转换为其他状态
                return false;
                
            default:
                // 未知状态不允许转换
                return false;
        }
    }

    /**
     * 记录合同状态变更审计日志
     * 
     * @param contractId 合同ID
     * @param oldStatus 原状态
     * @param newStatus 新状态
     * @param changeReason 变更原因
     */
    @Override
    public void recordStatusChangeAudit(Long contractId, String oldStatus, String newStatus, String changeReason)
    {
        try {
            // 使用日志记录状态变更审计信息
            // 这是一个简化的审计实现，实际生产环境中应该使用专门的审计日志系统
            
            String username = SecurityUtils.getUsername();
            Long userId = SecurityUtils.getUserId();
            Date changeTime = DateUtils.getNowDate();
            
            // 构建审计信息
            Map<String, Object> auditInfo = new HashMap<>();
            auditInfo.put("operationType", "CONTRACT_STATUS_CHANGE");
            auditInfo.put("contractId", contractId);
            auditInfo.put("oldStatus", oldStatus);
            auditInfo.put("newStatus", newStatus);
            auditInfo.put("changeReason", changeReason);
            auditInfo.put("userId", userId);
            auditInfo.put("username", username);
            auditInfo.put("changeTime", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, changeTime));
            auditInfo.put("riskLevel", "MEDIUM");
            
            // 记录到日志文件（生产环境中应该使用专门的审计日志表）
            log.info("合同状态变更审计日志: {}", objectMapper.writeValueAsString(auditInfo));
            
            // 可以在这里添加其他审计处理逻辑，如：
            // 1. 发送到审计日志队列
            // 2. 写入专门的审计数据库表
            // 3. 发送审计通知等
            
            log.info("记录合同状态变更审计日志成功，合同ID: {}, 状态变更: {} -> {}, 变更原因: {}", 
                    contractId, oldStatus, newStatus, changeReason);
            
        } catch (Exception e) {
            // 审计日志记录失败不应影响主业务流程
            log.error("记录合同状态变更审计日志失败，合同ID: {}, 状态变更: {} -> {}", 
                    contractId, oldStatus, newStatus, e);
        }
    }

    /**
     * 过滤有完整服务周期和员工贷款申请的合同
     * 
     * @param contracts 合同列表
     * @return 过滤后的合同列表
     */
    private List<ServiceContract> filterContractsWithServicePeriodAndLoans(List<ServiceContract> contracts) {
        log.info("开始过滤有完整服务周期和员工贷款申请的合同，原始数量: {}", contracts.size());
        
        List<ServiceContract> filteredContracts = new ArrayList<>();
        
        for (ServiceContract contract : contracts) {
            try {
                // 验证服务周期完整性
                if (!hasCompleteServicePeriod(contract)) {
                    log.debug("合同 {} 服务周期不完整，跳过", contract.getContractId());
                    continue;
                }
                
                // 验证是否有员工贷款申请
                if (!hasEmployeeLoanApplications(contract.getContractId())) {
                    log.debug("合同 {} 没有员工贷款申请，跳过", contract.getContractId());
                    continue;
                }
                
                // 添加服务周期和员工贷款信息到合同对象
                enrichContractWithAdditionalInfo(contract);
                
                filteredContracts.add(contract);
                log.debug("合同 {} 通过过滤条件", contract.getContractId());
                
            } catch (Exception e) {
                log.error("过滤合同 {} 时发生异常，跳过该合同", contract.getContractId(), e);
            }
        }
        
        log.info("过滤完成，符合条件的合同数量: {}", filteredContracts.size());
        return filteredContracts;
    }

    /**
     * 验证合同是否有完整的服务周期
     * 
     * @param contract 合同对象
     * @return 是否有完整服务周期
     */
    private boolean hasCompleteServicePeriod(ServiceContract contract) {
        // 检查合同的开始日期和结束日期是否都存在
        if (contract.getStartDate() == null || contract.getEndDate() == null) {
            log.debug("合同 {} 缺少服务开始或结束日期", contract.getContractId());
            return false;
        }
        
        // 检查日期逻辑是否正确
        if (contract.getStartDate().after(contract.getEndDate())) {
            log.debug("合同 {} 服务开始日期晚于结束日期", contract.getContractId());
            return false;
        }
        
        // 移除30天限制，只要有开始和结束日期就认为有完整服务周期
        log.debug("合同 {} 有完整的服务周期: {} 至 {}", 
                 contract.getContractId(), contract.getStartDate(), contract.getEndDate());
        return true;
    }

    /**
     * 验证合同是否有员工贷款申请
     * 
     * @param contractId 合同ID
     * @return 是否有员工贷款申请
     */
    private boolean hasEmployeeLoanApplications(Long contractId) {
        try {
            // 这里需要查询服务周期贷款表来验证是否有贷款申请
            // 由于我们没有直接的服务依赖，这里使用简化的查询逻辑
            
            log.debug("检查合同 {} 的员工贷款申请", contractId);
            
            // 模拟查询逻辑 - 实际应该查询 dc_service_period_loan 表
            // SELECT COUNT(*) FROM dc_service_period_loan spl 
            // JOIN dc_contract_employee ce ON spl.service_period_id = ce.service_period_id
            // WHERE ce.contract_id = ?
            
            // 暂时返回true，实际部署时需要实现真实的查询逻辑
            boolean hasLoans = checkEmployeeLoanApplicationsFromDatabase(contractId);
            
            log.debug("合同 {} 员工贷款申请检查结果: {}", contractId, hasLoans);
            return hasLoans;
            
        } catch (Exception e) {
            log.error("检查合同 {} 员工贷款申请时发生异常", contractId, e);
            return false;
        }
    }

    /**
     * 从数据库检查员工贷款申请
     * 
     * @param contractId 合同ID
     * @return 是否有贷款申请
     */
    private boolean checkEmployeeLoanApplicationsFromDatabase(Long contractId) {
        try {
            log.debug("查询合同 {} 的员工贷款申请", contractId);
            
            // 1. 根据合同ID查询所有服务周期
            List<ServicePeriod> servicePeriods = servicePeriodMapper.selectServicePeriodsByContractId(contractId);
            
            if (servicePeriods == null || servicePeriods.isEmpty()) {
                log.debug("合同 {} 没有关联的服务周期", contractId);
                return false;
            }
            
            // 2. 检查每个服务周期是否有贷款申请
            int totalLoanCount = 0;
            for (ServicePeriod servicePeriod : servicePeriods) {
                List<ServicePeriodLoan> loans = servicePeriodLoanMapper.selectServicePeriodLoansByPeriodId(servicePeriod.getServicePeriodId());
                if (loans != null && !loans.isEmpty()) {
                    // 统计所有贷款，不限制状态
                    totalLoanCount += loans.size();
                    
                    log.debug("服务周期 {} 有 {} 笔贷款", servicePeriod.getServicePeriodId(), loans.size());
                }
            }
            
            boolean hasLoans = totalLoanCount > 0;
            log.debug("合同 {} 员工贷款申请查询结果: 共 {} 笔贷款，结果: {}", contractId, totalLoanCount, hasLoans);
            
            return hasLoans;
            
        } catch (Exception e) {
            log.error("查询合同 {} 员工贷款申请时发生异常", contractId, e);
            return false;
        }
    }

    /**
     * 为合同对象添加额外信息
     * 
     * @param contract 合同对象
     */
    private void enrichContractWithAdditionalInfo(ServiceContract contract) {
        try {
            // 添加员工贷款信息
            Map<String, Object> loanInfo = getEmployeeLoanInfo(contract.getContractId());
            
            // 将贷款信息设置到合同对象的扩展字段中
            if (loanInfo != null) {
                contract.setEmployeeLoanTotalAmount((BigDecimal) loanInfo.get("totalAmount"));
                contract.setEmployeeLoanCount((Integer) loanInfo.get("applicationCount"));
            }
            
            log.debug("为合同 {} 添加了员工贷款信息", contract.getContractId());
            
        } catch (Exception e) {
            log.error("为合同 {} 添加额外信息时发生异常", contract.getContractId(), e);
        }
    }

    /**
     * 获取员工贷款信息
     * 
     * @param contractId 合同ID
     * @return 贷款信息
     */
    private Map<String, Object> getEmployeeLoanInfo(Long contractId) {
        try {
            Map<String, Object> loanInfo = new HashMap<>();
            
            // 1. 根据合同ID查询所有服务周期
            List<ServicePeriod> servicePeriods = servicePeriodMapper.selectServicePeriodsByContractId(contractId);
            
            if (servicePeriods == null || servicePeriods.isEmpty()) {
                log.debug("合同 {} 没有关联的服务周期", contractId);
                loanInfo.put("totalAmount", BigDecimal.ZERO);
                loanInfo.put("applicationCount", 0);
                return loanInfo;
            }
            
            // 2. 统计所有服务周期的贷款信息
            BigDecimal totalAmount = BigDecimal.ZERO;
            int applicationCount = 0;
            
            for (ServicePeriod servicePeriod : servicePeriods) {
                List<ServicePeriodLoan> loans = servicePeriodLoanMapper.selectServicePeriodLoansByPeriodId(servicePeriod.getServicePeriodId());
                
                if (loans != null && !loans.isEmpty()) {
                    for (ServicePeriodLoan loan : loans) {
                        // 统计所有贷款，不限制状态
                        if (loan.getLoanAmount() != null) {
                            totalAmount = totalAmount.add(loan.getLoanAmount());
                        }
                        applicationCount++;
                    }
                }
            }
            
            loanInfo.put("totalAmount", totalAmount);
            loanInfo.put("applicationCount", applicationCount);
            
            log.debug("获取合同 {} 员工贷款信息: 总额={}, 申请数量={}", 
                     contractId, totalAmount, applicationCount);
            
            return loanInfo;
            
        } catch (Exception e) {
            log.error("获取合同 {} 员工贷款信息时发生异常", contractId, e);
            // 返回默认值而不是null，避免空指针异常
            Map<String, Object> defaultInfo = new HashMap<>();
            defaultInfo.put("totalAmount", BigDecimal.ZERO);
            defaultInfo.put("applicationCount", 0);
            return defaultInfo;
        }
    }

    /**
     * 验证合同数据完整性 - 适配Contract对象
     */
    @Override
    public Map<String, Object> validateContractData(Contract contractInfo)
    {
        Map<String, Object> result = new HashMap<>();
        List<String> errors = new ArrayList<>();
        
        try {
            // 验证必填字段
            if (StringUtils.isBlank(contractInfo.getSecurityCompany())) {
                errors.add("安保公司名称不能为空");
            }

            if (StringUtils.isBlank(contractInfo.getClientCompany())) {
                errors.add("甲方单位名称不能为空");
            }

            if (contractInfo.getContractAmount() == null || contractInfo.getContractAmount().compareTo(BigDecimal.ZERO) <= 0) {
                errors.add("合同金额必须大于0");
            }

            if (contractInfo.getStartDate() == null) {
                errors.add("服务开始日期不能为空");
            }

            if (contractInfo.getEndDate() == null) {
                errors.add("服务结束日期不能为空");
            }

            // 验证日期逻辑
            if (contractInfo.getStartDate() != null && contractInfo.getEndDate() != null) {
                if (contractInfo.getStartDate().after(contractInfo.getEndDate())) {
                    errors.add("服务开始日期不能晚于结束日期");
                }
            }

            // 验证前端发送的额外字段（这些字段不会保存到数据库，但可以用于业务逻辑验证）
            if (contractInfo.getPaymentDueDate() != null && contractInfo.getEndDate() != null) {
                if (contractInfo.getPaymentDueDate().before(contractInfo.getEndDate())) {
                    log.warn("付款到期日早于服务结束日期，这可能不合理，但不阻止创建合同");
                    // 不添加到错误列表，只是警告
                }
            }

            // 验证服务内容（如果前端提供了的话）
            if (StringUtils.isNotBlank(contractInfo.getServiceContent())) {
                log.info("前端提供了服务内容: {}", contractInfo.getServiceContent());
            }

            // 验证服务类型（如果前端提供了的话）
            if (StringUtils.isNotBlank(contractInfo.getServiceType())) {
                log.info("前端提供了服务类型: {}", contractInfo.getServiceType());
            }

            result.put("valid", errors.isEmpty());
            result.put("message", String.join("; ", errors));
            
            // 添加额外信息
            result.put("hasExtraFields", contractInfo.getContractTerm() != null || 
                                        contractInfo.getContractTerms() != null || 
                                        contractInfo.getServiceType() != null || 
                                        contractInfo.getServiceContent() != null || 
                                        contractInfo.getPaymentDueDate() != null);
            
        } catch (Exception e) {
            result.put("valid", false);
            result.put("message", "验证过程中发生异常: " + e.getMessage());
        }
        
        return result;
    }

    // ========== Contract 相关方法 (基础合同表 dc_contract) ==========

    /**
     * 查询合同详情 - 从dc_contract表查询
     */
    @Override
    public Contract selectContractByContractId(Long contractId)
    {
        log.info("查询合同详情，合同ID: {}", contractId);
        try {
            Contract contract = contractMapper.selectContractByContractId(contractId);
            if (contract != null) {
                log.info("成功查询到合同: ID={}, 编号={}, 标题={}", 
                        contract.getContractId(), contract.getContractNumber(), contract.getTitle());
            } else {
                log.warn("未找到合同，ID: {}", contractId);
            }
            return contract;
        } catch (Exception e) {
            log.error("查询合同详情失败，合同ID: {}, 错误: {}", contractId, e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 查询合同列表 - 从dc_contract表查询
     */
    @Override
    public List<Contract> selectContractList(Contract contract)
    {
        try {
            log.debug("查询合同列表，查询条件: {}", contract);
            
            if (contract == null) {
                contract = new Contract();
            }
            
            // 执行查询
            List<Contract> result = contractMapper.selectContractList(contract);
            
            // 确保永远不返回null
            if (result == null) {
                result = new ArrayList<>();
            }
            
            log.debug("查询到合同数量: {}", result.size());
            if (!result.isEmpty()) {
                log.debug("第一条合同信息: ID={}, 编号={}, 标题={}", 
                         result.get(0).getContractId(), 
                         result.get(0).getContractNumber(), 
                         result.get(0).getTitle());
            }
            
            return result;
            
        } catch (Exception e) {
            log.error("查询合同列表失败", e);
            // 发生异常时返回空列表而不是null
            return new ArrayList<>();
        }
    }

    /**
     * 根据合同编号查询合同 - 从dc_contract表查询
     */
    @Override
    public Contract selectContractByContractNumber(String contractNumber)
    {
        return contractMapper.selectContractByContractNumber(contractNumber);
    }

    /**
     * 根据状态查询合同列表 - 从dc_contract表查询
     */
    @Override
    public List<Contract> selectContractByStatus(String contractStatus)
    {
        return contractMapper.selectContractByStatus(contractStatus);
    }

    /**
     * 查询即将到期的合同 - 从dc_contract表查询
     */
    public List<Contract> selectExpiringContractsFromContract(int days)
    {
        return contractMapper.selectExpiringContracts(days);
    }

    /**
     * 更新合同信息 - 更新dc_contract表
     */
    @Override
    public boolean updateContract(Contract contract)
    {
        log.info("更新合同信息，合同ID: {}", contract.getContractId());
        
        // 验证合同是否存在
        Contract existingContract = contractMapper.selectContractByContractId(contract.getContractId());
        if (existingContract == null) {
            throw new RuntimeException("合同不存在: " + contract.getContractId());
        }

        // 验证合同数据
        Map<String, Object> validationResult = validateContractData(contract);
        if (!(Boolean) validationResult.get("valid")) {
            throw new RuntimeException("合同数据验证失败: " + validationResult.get("message"));
        }

        // 设置更新信息
        contract.setUpdateBy(SecurityUtils.getUsername());
        contract.setUpdateTime(DateUtils.getNowDate());

        int result = contractMapper.updateContract(contract);
        if (result <= 0) {
            log.error("更新合同信息失败，合同ID: {}", contract.getContractId());
            return false;
        }

        log.info("成功更新合同信息，合同ID: {}", contract.getContractId());
        return true;
    }

    /**
     * 删除合同 - 从dc_contract表删除
     */
    @Override
    public int deleteContractByContractId(Long contractId)
    {
        log.info("删除合同，合同ID: {}", contractId);
        return contractMapper.deleteContractByContractId(contractId);
    }

    /**
     * 批量删除合同 - 从dc_contract表删除
     */
    @Override
    public int deleteContractByContractIds(Long[] contractIds)
    {
        log.info("批量删除合同，合同ID数组: {}", java.util.Arrays.toString(contractIds));
        return contractMapper.deleteContractByContractIds(contractIds);
    }

    /**
     * 创建服务合同详细信息（绑定服务周期时调用）
     * 
     * @param contractId 基础合同ID
     * @param serviceContractInfo 服务合同详细信息
     * @return 创建的服务合同对象
     */
    @Override
    @Transactional
    public ServiceContract createServiceContract(Long contractId, ServiceContract serviceContractInfo)
    {
        log.info("开始创建服务合同详细信息，基础合同ID: {}", contractId);
        
        // 1. 验证基础合同是否存在
        Contract baseContract = contractMapper.selectContractByContractId(contractId);
        if (baseContract == null) {
            throw new RuntimeException("基础合同不存在: " + contractId);
        }
        
        // 2. 从基础合同复制信息到服务合同
        serviceContractInfo.setContractId(contractId);
        serviceContractInfo.setContractNumber(baseContract.getContractNumber());
        serviceContractInfo.setTitle(baseContract.getTitle());
        serviceContractInfo.setSecurityCompany(baseContract.getSecurityCompany());
        serviceContractInfo.setClientCompany(baseContract.getClientCompany());
        serviceContractInfo.setContractAmount(baseContract.getContractAmount());
        serviceContractInfo.setStartDate(baseContract.getStartDate());
        serviceContractInfo.setEndDate(baseContract.getEndDate());
        serviceContractInfo.setContractStatus(baseContract.getContractStatus());
        serviceContractInfo.setContractType(baseContract.getContractType());
        
        // 从基础合同复制部门ID
        if (baseContract.getDeptId() != null) {
            serviceContractInfo.setDeptId(baseContract.getDeptId());
        }
        
        // 3. 设置服务合同来源
        serviceContractInfo.setContractSource("PLATFORM_CREATED");
        
        // 4. 设置创建信息
        serviceContractInfo.setCreateBy(SecurityUtils.getUsername());
        serviceContractInfo.setCreateTime(DateUtils.getNowDate());
        
        // 5. 计算数据哈希
        String dataHash = calculateDataHash(serviceContractInfo);
        serviceContractInfo.setDataHash(dataHash);
        
        // 6. 保存到dc_service_contract表，使用指定的contract_id
        int result = serviceContractMapper.insertServiceContractWithId(serviceContractInfo);
        if (result <= 0) {
            throw new RuntimeException("创建服务合同详细信息失败");
        }
        
        log.info("成功创建服务合同详细信息，合同ID: {}", contractId);
        return serviceContractInfo;
    }
}