package com.ruoyi.credit.service.impl;

import java.util.Date;
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 com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.credit.domain.ValidationLog;
import com.ruoyi.credit.mapper.ValidationLogMapper;
import com.ruoyi.credit.service.IValidationLogService;

/**
 * 验证日志Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-12-31
 */
@Service
public class ValidationLogServiceImpl implements IValidationLogService 
{
    private static final Logger log = LoggerFactory.getLogger(ValidationLogServiceImpl.class);

    @Autowired
    private ValidationLogMapper validationLogMapper;

    /**
     * 查询验证日志
     * 
     * @param logId 验证日志主键
     * @return 验证日志
     */
    @Override
    public ValidationLog selectValidationLogByLogId(Long logId)
    {
        return validationLogMapper.selectValidationLogByLogId(logId);
    }

    /**
     * 查询验证日志列表
     * 
     * @param validationLog 验证日志
     * @return 验证日志
     */
    @Override
    public List<ValidationLog> selectValidationLogList(ValidationLog validationLog)
    {
        return validationLogMapper.selectValidationLogList(validationLog);
    }

    /**
     * 根据验证记录ID查询日志
     * 
     * @param validationId 验证记录ID
     * @return 验证日志集合
     */
    @Override
    public List<ValidationLog> selectLogsByValidationId(Long validationId)
    {
        return validationLogMapper.selectLogsByValidationId(validationId);
    }

    /**
     * 根据贷款ID查询日志
     * 
     * @param loanId 贷款ID
     * @return 验证日志集合
     */
    @Override
    public List<ValidationLog> selectLogsByLoanId(Long loanId)
    {
        return validationLogMapper.selectLogsByLoanId(loanId);
    }

    /**
     * 根据时间范围查询日志
     * 
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 验证日志集合
     */
    @Override
    public List<ValidationLog> selectLogsByTimeRange(Date startTime, Date endTime)
    {
        return validationLogMapper.selectLogsByTimeRange(startTime, endTime);
    }

    /**
     * 根据日志级别查询日志
     * 
     * @param logLevel 日志级别
     * @return 验证日志集合
     */
    @Override
    public List<ValidationLog> selectLogsByLevel(String logLevel)
    {
        return validationLogMapper.selectLogsByLevel(logLevel);
    }

    /**
     * 根据日志类型查询日志
     * 
     * @param logType 日志类型
     * @return 验证日志集合
     */
    @Override
    public List<ValidationLog> selectLogsByType(String logType)
    {
        return validationLogMapper.selectLogsByType(logType);
    }

    /**
     * 根据时间范围和日志级别查询日志
     * 
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param logLevel 日志级别
     * @return 验证日志集合
     */
    @Override
    public List<ValidationLog> selectLogsByTimeRangeAndLevel(Date startTime, Date endTime, String logLevel)
    {
        return validationLogMapper.selectLogsByTimeRangeAndLevel(startTime, endTime, logLevel);
    }

    /**
     * 根据时间范围和日志类型查询日志
     * 
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param logType 日志类型
     * @return 验证日志集合
     */
    @Override
    public List<ValidationLog> selectLogsByTimeRangeAndType(Date startTime, Date endTime, String logType)
    {
        return validationLogMapper.selectLogsByTimeRangeAndType(startTime, endTime, logType);
    }

    /**
     * 根据操作用户查询日志
     * 
     * @param operatorUser 操作用户
     * @return 验证日志集合
     */
    @Override
    public List<ValidationLog> selectLogsByOperatorUser(String operatorUser)
    {
        return validationLogMapper.selectLogsByOperatorUser(operatorUser);
    }

    /**
     * 根据执行步骤查询日志
     * 
     * @param executionStep 执行步骤
     * @return 验证日志集合
     */
    @Override
    public List<ValidationLog> selectLogsByExecutionStep(String executionStep)
    {
        return validationLogMapper.selectLogsByExecutionStep(executionStep);
    }

    /**
     * 查询异常日志
     * 
     * @return 验证日志集合
     */
    @Override
    public List<ValidationLog> selectExceptionLogs()
    {
        return validationLogMapper.selectExceptionLogs();
    }

    /**
     * 查询性能警告日志
     * 
     * @param minDuration 最小执行时长
     * @return 验证日志集合
     */
    @Override
    public List<ValidationLog> selectPerformanceWarningLogs(Long minDuration)
    {
        return validationLogMapper.selectPerformanceWarningLogs(minDuration);
    }

    /**
     * 新增验证日志
     * 
     * @param validationLog 验证日志
     * @return 结果
     */
    @Override
    public int insertValidationLog(ValidationLog validationLog)
    {
        validationLog.setCreateTime(DateUtils.getNowDate());
        validationLog.setUpdateTime(DateUtils.getNowDate());
        if (validationLog.getLogTime() == null) {
            validationLog.setLogTime(DateUtils.getNowDate());
        }
        return validationLogMapper.insertValidationLog(validationLog);
    }

    /**
     * 批量新增验证日志
     * 
     * @param validationLogs 验证日志列表
     * @return 结果
     */
    @Override
    public int batchInsertValidationLog(List<ValidationLog> validationLogs)
    {
        Date now = DateUtils.getNowDate();
        for (ValidationLog validationLog : validationLogs) {
            validationLog.setCreateTime(now);
            validationLog.setUpdateTime(now);
            if (validationLog.getLogTime() == null) {
                validationLog.setLogTime(now);
            }
        }
        return validationLogMapper.batchInsertValidationLog(validationLogs);
    }

    /**
     * 修改验证日志
     * 
     * @param validationLog 验证日志
     * @return 结果
     */
    @Override
    public int updateValidationLog(ValidationLog validationLog)
    {
        validationLog.setUpdateTime(DateUtils.getNowDate());
        return validationLogMapper.updateValidationLog(validationLog);
    }

    /**
     * 批量删除验证日志
     * 
     * @param logIds 需要删除的验证日志主键
     * @return 结果
     */
    @Override
    public int deleteValidationLogByLogIds(Long[] logIds)
    {
        return validationLogMapper.deleteValidationLogByLogIds(logIds);
    }

    /**
     * 删除验证日志信息
     * 
     * @param logId 验证日志主键
     * @return 结果
     */
    @Override
    public int deleteValidationLogByLogId(Long logId)
    {
        return validationLogMapper.deleteValidationLogByLogId(logId);
    }

    /**
     * 根据验证记录ID删除日志
     * 
     * @param validationId 验证记录ID
     * @return 结果
     */
    @Override
    public int deleteLogsByValidationId(Long validationId)
    {
        return validationLogMapper.deleteLogsByValidationId(validationId);
    }

    /**
     * 根据贷款ID删除日志
     * 
     * @param loanId 贷款ID
     * @return 结果
     */
    @Override
    public int deleteLogsByLoanId(Long loanId)
    {
        return validationLogMapper.deleteLogsByLoanId(loanId);
    }

    /**
     * 根据时间范围删除日志
     * 
     * @param endTime 结束时间
     * @return 结果
     */
    @Override
    public int deleteLogsByTimeRange(Date endTime)
    {
        return validationLogMapper.deleteLogsByTimeRange(endTime);
    }

    /**
     * 统计日志数量
     * 
     * @param validationLog 查询条件
     * @return 日志数量
     */
    @Override
    public int countValidationLogs(ValidationLog validationLog)
    {
        return validationLogMapper.countValidationLogs(validationLog);
    }

    /**
     * 统计各级别日志数量
     * 
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 统计结果
     */
    @Override
    public List<Map<String, Object>> countLogsByLevel(Date startTime, Date endTime)
    {
        return validationLogMapper.countLogsByLevel(startTime, endTime);
    }

    /**
     * 统计各类型日志数量
     * 
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 统计结果
     */
    @Override
    public List<Map<String, Object>> countLogsByType(Date startTime, Date endTime)
    {
        return validationLogMapper.countLogsByType(startTime, endTime);
    }

    /**
     * 记录验证开始日志
     * 
     * @param loanId 贷款ID
     * @param validationId 验证记录ID
     * @param operatorUser 操作用户
     * @param clientIp 客户端IP
     */
    @Override
    public void logValidationStart(Long loanId, Long validationId, String operatorUser, String clientIp)
    {
        try {
            ValidationLog validationLog = new ValidationLog();
            validationLog.setLoanId(loanId);
            validationLog.setValidationId(validationId);
            validationLog.setLogLevel(ValidationLog.LEVEL_INFO);
            validationLog.setLogType(ValidationLog.TYPE_VALIDATION_START);
            validationLog.setLogMessage("开始验证贷款一致性");
            validationLog.setLogDetails("贷款ID: " + loanId + ", 验证记录ID: " + validationId);
            validationLog.setExecutionStep("START");
            validationLog.setOperatorUser(operatorUser);
            validationLog.setClientIp(clientIp);
            
            insertValidationLog(validationLog);
            
            log.debug("记录验证开始日志成功，贷款ID: {}, 验证记录ID: {}", loanId, validationId);
        } catch (Exception e) {
            log.error("记录验证开始日志失败，贷款ID: {}, 验证记录ID: {}", loanId, validationId, e);
        }
    }

    /**
     * 记录验证步骤日志
     * 
     * @param loanId 贷款ID
     * @param validationId 验证记录ID
     * @param step 执行步骤
     * @param message 日志消息
     * @param details 详细信息
     * @param duration 执行时长
     * @param operatorUser 操作用户
     */
    @Override
    public void logValidationStep(Long loanId, Long validationId, String step, String message, String details, Long duration, String operatorUser)
    {
        try {
            ValidationLog validationLog = new ValidationLog();
            validationLog.setLoanId(loanId);
            validationLog.setValidationId(validationId);
            validationLog.setLogLevel(ValidationLog.LEVEL_DEBUG);
            validationLog.setLogType(ValidationLog.TYPE_VALIDATION_STEP);
            validationLog.setLogMessage(message);
            validationLog.setLogDetails(details);
            validationLog.setExecutionStep(step);
            validationLog.setExecutionDuration(duration);
            validationLog.setOperatorUser(operatorUser);
            
            insertValidationLog(validationLog);
            
            log.debug("记录验证步骤日志成功，贷款ID: {}, 步骤: {}, 耗时: {}ms", loanId, step, duration);
        } catch (Exception e) {
            log.error("记录验证步骤日志失败，贷款ID: {}, 步骤: {}", loanId, step, e);
        }
    }

    /**
     * 记录验证成功日志
     * 
     * @param loanId 贷款ID
     * @param validationId 验证记录ID
     * @param message 日志消息
     * @param details 详细信息
     * @param totalDuration 总执行时长
     * @param operatorUser 操作用户
     */
    @Override
    public void logValidationSuccess(Long loanId, Long validationId, String message, String details, Long totalDuration, String operatorUser)
    {
        try {
            ValidationLog validationLog = new ValidationLog();
            validationLog.setLoanId(loanId);
            validationLog.setValidationId(validationId);
            validationLog.setLogLevel(ValidationLog.LEVEL_INFO);
            validationLog.setLogType(ValidationLog.TYPE_VALIDATION_SUCCESS);
            validationLog.setLogMessage(message);
            validationLog.setLogDetails(details);
            validationLog.setExecutionStep("SUCCESS");
            validationLog.setExecutionDuration(totalDuration);
            validationLog.setOperatorUser(operatorUser);
            
            insertValidationLog(validationLog);
            
            log.info("记录验证成功日志，贷款ID: {}, 总耗时: {}ms", loanId, totalDuration);
        } catch (Exception e) {
            log.error("记录验证成功日志失败，贷款ID: {}", loanId, e);
        }
    }

    /**
     * 记录验证失败日志
     * 
     * @param loanId 贷款ID
     * @param validationId 验证记录ID
     * @param message 日志消息
     * @param failureReason 失败原因
     * @param totalDuration 总执行时长
     * @param operatorUser 操作用户
     */
    @Override
    public void logValidationFailure(Long loanId, Long validationId, String message, String failureReason, Long totalDuration, String operatorUser)
    {
        try {
            ValidationLog validationLog = new ValidationLog();
            validationLog.setLoanId(loanId);
            validationLog.setValidationId(validationId);
            validationLog.setLogLevel(ValidationLog.LEVEL_WARN);
            validationLog.setLogType(ValidationLog.TYPE_VALIDATION_FAILURE);
            validationLog.setLogMessage(message);
            validationLog.setLogDetails("失败原因: " + failureReason);
            validationLog.setExecutionStep("FAILURE");
            validationLog.setExecutionDuration(totalDuration);
            validationLog.setOperatorUser(operatorUser);
            
            insertValidationLog(validationLog);
            
            log.warn("记录验证失败日志，贷款ID: {}, 失败原因: {}, 总耗时: {}ms", loanId, failureReason, totalDuration);
        } catch (Exception e) {
            log.error("记录验证失败日志失败，贷款ID: {}", loanId, e);
        }
    }

    /**
     * 记录验证错误日志
     * 
     * @param loanId 贷款ID
     * @param validationId 验证记录ID
     * @param message 日志消息
     * @param exception 异常信息
     * @param operatorUser 操作用户
     */
    @Override
    public void logValidationError(Long loanId, Long validationId, String message, Exception exception, String operatorUser)
    {
        try {
            ValidationLog validationLog = new ValidationLog();
            validationLog.setLoanId(loanId);
            validationLog.setValidationId(validationId);
            validationLog.setLogLevel(ValidationLog.LEVEL_ERROR);
            validationLog.setLogType(ValidationLog.TYPE_VALIDATION_ERROR);
            validationLog.setLogMessage(message);
            validationLog.setLogDetails("异常类型: " + exception.getClass().getSimpleName());
            validationLog.setExecutionStep("ERROR");
            validationLog.setExceptionInfo(getExceptionStackTrace(exception));
            validationLog.setOperatorUser(operatorUser);
            
            insertValidationLog(validationLog);
            
            log.error("记录验证错误日志，贷款ID: {}, 异常: {}", loanId, exception.getMessage());
        } catch (Exception e) {
            log.error("记录验证错误日志失败，贷款ID: {}", loanId, e);
        }
    }

    /**
     * 记录缓存操作日志
     * 
     * @param loanId 贷款ID
     * @param operation 操作类型
     * @param message 日志消息
     * @param details 详细信息
     * @param operatorUser 操作用户
     */
    @Override
    public void logCacheOperation(Long loanId, String operation, String message, String details, String operatorUser)
    {
        try {
            ValidationLog validationLog = new ValidationLog();
            validationLog.setLoanId(loanId);
            validationLog.setLogLevel(ValidationLog.LEVEL_DEBUG);
            validationLog.setLogType(ValidationLog.TYPE_CACHE_OPERATION);
            validationLog.setLogMessage(message);
            validationLog.setLogDetails(details);
            validationLog.setExecutionStep(operation);
            validationLog.setOperatorUser(operatorUser);
            
            insertValidationLog(validationLog);
            
            log.debug("记录缓存操作日志，贷款ID: {}, 操作: {}", loanId, operation);
        } catch (Exception e) {
            log.error("记录缓存操作日志失败，贷款ID: {}, 操作: {}", loanId, operation, e);
        }
    }

    /**
     * 记录通知发送日志
     * 
     * @param loanId 贷款ID
     * @param validationId 验证记录ID
     * @param notificationType 通知类型
     * @param message 日志消息
     * @param success 是否成功
     * @param operatorUser 操作用户
     */
    @Override
    public void logNotificationSent(Long loanId, Long validationId, String notificationType, String message, boolean success, String operatorUser)
    {
        try {
            ValidationLog validationLog = new ValidationLog();
            validationLog.setLoanId(loanId);
            validationLog.setValidationId(validationId);
            validationLog.setLogLevel(success ? ValidationLog.LEVEL_INFO : ValidationLog.LEVEL_WARN);
            validationLog.setLogType(ValidationLog.TYPE_NOTIFICATION_SENT);
            validationLog.setLogMessage(message);
            validationLog.setLogDetails("通知类型: " + notificationType + ", 结果: " + (success ? "成功" : "失败"));
            validationLog.setExecutionStep("NOTIFICATION");
            validationLog.setOperatorUser(operatorUser);
            
            insertValidationLog(validationLog);
            
            log.debug("记录通知发送日志，贷款ID: {}, 通知类型: {}, 结果: {}", loanId, notificationType, success ? "成功" : "失败");
        } catch (Exception e) {
            log.error("记录通知发送日志失败，贷款ID: {}, 通知类型: {}", loanId, notificationType, e);
        }
    }

    /**
     * 记录性能警告日志
     * 
     * @param loanId 贷款ID
     * @param validationId 验证记录ID
     * @param operation 操作类型
     * @param duration 执行时长
     * @param threshold 阈值
     * @param operatorUser 操作用户
     */
    @Override
    public void logPerformanceWarning(Long loanId, Long validationId, String operation, Long duration, Long threshold, String operatorUser)
    {
        try {
            ValidationLog validationLog = new ValidationLog();
            validationLog.setLoanId(loanId);
            validationLog.setValidationId(validationId);
            validationLog.setLogLevel(ValidationLog.LEVEL_WARN);
            validationLog.setLogType(ValidationLog.TYPE_PERFORMANCE_WARNING);
            validationLog.setLogMessage("性能警告: " + operation + "执行时间超过阈值");
            validationLog.setLogDetails("执行时长: " + duration + "ms, 阈值: " + threshold + "ms");
            validationLog.setExecutionStep("PERFORMANCE_WARNING");
            validationLog.setExecutionDuration(duration);
            validationLog.setOperatorUser(operatorUser);
            
            insertValidationLog(validationLog);
            
            log.warn("记录性能警告日志，贷款ID: {}, 操作: {}, 执行时长: {}ms, 阈值: {}ms", loanId, operation, duration, threshold);
        } catch (Exception e) {
            log.error("记录性能警告日志失败，贷款ID: {}, 操作: {}", loanId, operation, e);
        }
    }

    /**
     * 获取异常堆栈信息
     * 
     * @param exception 异常
     * @return 堆栈信息字符串
     */
    private String getExceptionStackTrace(Exception exception) {
        if (exception == null) {
            return null;
        }
        
        StringBuilder sb = new StringBuilder();
        sb.append(exception.getClass().getName()).append(": ").append(exception.getMessage()).append("\n");
        
        StackTraceElement[] stackTrace = exception.getStackTrace();
        int maxLines = Math.min(stackTrace.length, 10); // 限制堆栈信息长度
        
        for (int i = 0; i < maxLines; i++) {
            sb.append("\tat ").append(stackTrace[i].toString()).append("\n");
        }
        
        if (stackTrace.length > maxLines) {
            sb.append("\t... ").append(stackTrace.length - maxLines).append(" more\n");
        }
        
        // 限制总长度，避免数据库字段溢出
        String result = sb.toString();
        if (result.length() > 3900) {
            result = result.substring(0, 3900) + "...[truncated]";
        }
        
        return result;
    }
}