package com.ruoyi.credit.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
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 com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.credit.domain.ServicePeriodLoan;
import com.ruoyi.credit.exception.BankSelectionException;
import com.ruoyi.credit.service.ErrorHandlingService;
import com.ruoyi.credit.service.IServicePeriodLoanService;

/**
 * 错误处理服务实现
 * 
 * @author ruoyi
 * @date 2025-12-24
 */
@Service
public class ErrorHandlingServiceImpl implements ErrorHandlingService {
    
    private static final Logger log = LoggerFactory.getLogger(ErrorHandlingServiceImpl.class);
    
    @Autowired
    private IServicePeriodLoanService servicePeriodLoanService;
    
    @Override
    public Map<String, Object> validateBankInformation(ServicePeriodLoan loan) {
        log.info("验证银行信息完整性: loanId={}", loan.getLinkId());
        
        Map<String, Object> result = new HashMap<>();
        List<String> missingFields = new ArrayList<>();
        List<String> suggestions = new ArrayList<>();
        
        try {
            // 检查银行ID
            if (loan.getBankInstitutionId() == null) {
                missingFields.add("银行机构");
                suggestions.add("请从可用银行列表中选择一个银行机构");
            }
            
            // 检查银行名称
            if (StringUtils.isEmpty(loan.getBankInstitutionName())) {
                missingFields.add("银行名称");
                suggestions.add("银行名称信息缺失，请重新选择银行");
            }
            
            // 检查利率信息
            if (loan.getInterestRate() == null || loan.getInterestRate() <= 0) {
                missingFields.add("利率信息");
                suggestions.add("利率信息无效，请重新选择银行或联系系统管理员");
            }
            
            // 检查月还款额
            if (loan.getMonthlyPayment() == null || loan.getMonthlyPayment().compareTo(BigDecimal.ZERO) <= 0) {
                missingFields.add("月还款额");
                suggestions.add("月还款额计算异常，请重新选择银行");
            }
            
            // 检查提交说明
            if (StringUtils.isEmpty(loan.getSubmitComments())) {
                missingFields.add("提交说明");
                suggestions.add("请填写提交给银行的说明信息，至少10个字符");
            } else if (loan.getSubmitComments().trim().length() < 10) {
                missingFields.add("提交说明长度不足");
                suggestions.add("提交说明至少需要10个字符，请补充详细信息");
            }
            
            // 检查银行选择时间
            if (loan.getBankSelectedTime() == null) {
                missingFields.add("银行选择时间");
                suggestions.add("银行选择时间缺失，请重新选择银行");
            }
            
            boolean isValid = missingFields.isEmpty();
            
            result.put("valid", isValid);
            result.put("missingFields", missingFields);
            result.put("suggestions", suggestions);
            
            if (isValid) {
                result.put("message", "银行信息验证通过");
            } else {
                String friendlyMessage = generateBankInfoMissingMessage(missingFields, suggestions);
                result.put("message", friendlyMessage);
                result.put("errorType", "BANK_INFO_MISSING");
                result.put("retryable", true);
            }
            
            log.info("银行信息验证完成: loanId={}, valid={}, missingCount={}", 
                    loan.getLinkId(), isValid, missingFields.size());
            
        } catch (Exception e) {
            log.error("验证银行信息失败: loanId={}", loan.getLinkId(), e);
            result.put("valid", false);
            result.put("message", "验证过程中发生错误: " + e.getMessage());
            result.put("errorType", "VALIDATION_ERROR");
            result.put("retryable", false);
        }
        
        return result;
    }
    
    @Override
    public Map<String, Object> autoRepairDataInconsistency(ServicePeriodLoan loan) {
        log.info("自动修复数据不一致问题: loanId={}", loan.getLinkId());
        
        Map<String, Object> result = new HashMap<>();
        List<String> repairedItems = new ArrayList<>();
        boolean needsUpdate = false;
        
        try {
            // 1. 修复银行选择状态不一致
            if (loan.getBankInstitutionId() != null && loan.getBankSelectedTime() == null) {
                loan.setBankSelectedTime(DateUtils.getNowDate());
                repairedItems.add("补充银行选择时间");
                needsUpdate = true;
            }
            
            // 2. 修复一键提交状态不一致
            boolean shouldEnableQuickSubmit = loan.getBankInstitutionId() != null 
                                            && StringUtils.isNotEmpty(loan.getSubmitComments())
                                            && loan.getLoanAmount() != null
                                            && loan.getLoanAmount().compareTo(BigDecimal.ZERO) > 0
                                            && ServicePeriodLoan.STATUS_PENDING.equals(loan.getLoanStatus());
            
            if (loan.getQuickSubmitEnabled() == null || loan.getQuickSubmitEnabled() != shouldEnableQuickSubmit) {
                loan.setQuickSubmitEnabled(shouldEnableQuickSubmit);
                repairedItems.add("修正一键提交状态为: " + (shouldEnableQuickSubmit ? "启用" : "禁用"));
                needsUpdate = true;
            }
            
            // 3. 修复月还款额计算不一致
            if (loan.getInterestRate() != null && loan.getInterestRate() > 0 
                && loan.getLoanAmount() != null && loan.getLoanAmount().compareTo(BigDecimal.ZERO) > 0
                && loan.getLoanTermMonths() != null && loan.getLoanTermMonths() > 0) {
                
                BigDecimal calculatedMonthlyPayment = calculateMonthlyPayment(
                    loan.getLoanAmount(), loan.getInterestRate(), loan.getLoanTermMonths());
                
                if (loan.getMonthlyPayment() == null || 
                    Math.abs(loan.getMonthlyPayment().subtract(calculatedMonthlyPayment).doubleValue()) > 0.01) {
                    loan.setMonthlyPayment(calculatedMonthlyPayment);
                    repairedItems.add("重新计算月还款额: " + calculatedMonthlyPayment);
                    needsUpdate = true;
                }
            }
            
            // 4. 修复银行选择历史记录格式
            if (StringUtils.isNotEmpty(loan.getBankSelectionHistory())) {
                String formattedHistory = formatBankSelectionHistory(loan.getBankSelectionHistory());
                if (!formattedHistory.equals(loan.getBankSelectionHistory())) {
                    loan.setBankSelectionHistory(formattedHistory);
                    repairedItems.add("格式化银行选择历史记录");
                    needsUpdate = true;
                }
            }
            
            // 5. 修复贷款状态与审批状态不一致
            if (ServicePeriodLoan.STATUS_SUBMITTED.equals(loan.getLoanStatus()) 
                && !ServicePeriodLoan.APPROVAL_SUBMITTED.equals(loan.getApprovalStatus())) {
                loan.setApprovalStatus(ServicePeriodLoan.APPROVAL_SUBMITTED);
                repairedItems.add("同步审批状态为已提交");
                needsUpdate = true;
            }
            
            // 6. 如果需要更新，执行数据库更新
            if (needsUpdate) {
                try {
                    servicePeriodLoanService.updateServicePeriodLoan(loan);
                    result.put("success", true);
                    result.put("message", "数据不一致问题已自动修复");
                    result.put("repairedItems", repairedItems);
                    result.put("repairedCount", repairedItems.size());
                    
                    log.info("数据不一致自动修复成功: loanId={}, repairedCount={}", 
                            loan.getLinkId(), repairedItems.size());
                } catch (Exception updateException) {
                    log.error("更新修复后的数据失败: loanId={}", loan.getLinkId(), updateException);
                    result.put("success", false);
                    result.put("message", "数据修复失败: " + updateException.getMessage());
                    result.put("errorType", "UPDATE_ERROR");
                }
            } else {
                result.put("success", true);
                result.put("message", "数据一致性检查通过，无需修复");
                result.put("repairedItems", repairedItems);
                result.put("repairedCount", 0);
            }
            
        } catch (Exception e) {
            log.error("自动修复数据不一致失败: loanId={}", loan.getLinkId(), e);
            result.put("success", false);
            result.put("message", "自动修复过程中发生错误: " + e.getMessage());
            result.put("errorType", "REPAIR_ERROR");
        }
        
        return result;
    }
    
    @Override
    public Map<String, Object> handleNetworkErrorRetry(String operation, int retryCount, Exception lastError) {
        log.info("处理网络错误重试: operation={}, retryCount={}", operation, retryCount);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 最大重试次数
            final int MAX_RETRY_COUNT = 3;
            
            // 重试间隔（毫秒）
            final long[] RETRY_INTERVALS = {1000, 2000, 5000}; // 1秒, 2秒, 5秒
            
            if (retryCount >= MAX_RETRY_COUNT) {
                // 超过最大重试次数
                result.put("shouldRetry", false);
                result.put("message", String.format("操作 '%s' 已重试 %d 次仍然失败，请检查网络连接或稍后再试", 
                                                   operation, retryCount));
                result.put("errorType", "NETWORK_ERROR_MAX_RETRY");
                result.put("suggestion", "请检查网络连接，或联系系统管理员");
                result.put("retryable", false);
            } else {
                // 可以继续重试
                long waitTime = retryCount < RETRY_INTERVALS.length ? 
                               RETRY_INTERVALS[retryCount] : RETRY_INTERVALS[RETRY_INTERVALS.length - 1];
                
                result.put("shouldRetry", true);
                result.put("waitTime", waitTime);
                result.put("retryCount", retryCount + 1);
                result.put("message", String.format("网络错误，将在 %d 秒后进行第 %d 次重试", 
                                                   waitTime / 1000, retryCount + 1));
                result.put("errorType", "NETWORK_ERROR_RETRY");
                result.put("retryable", true);
                
                // 分析错误类型，提供更具体的建议
                String errorAnalysis = analyzeNetworkError(lastError);
                result.put("errorAnalysis", errorAnalysis);
            }
            
            // 记录重试历史
            result.put("retryHistory", generateRetryHistory(operation, retryCount, lastError));
            
        } catch (Exception e) {
            log.error("处理网络错误重试失败: operation={}", operation, e);
            result.put("shouldRetry", false);
            result.put("message", "处理重试逻辑时发生错误: " + e.getMessage());
            result.put("errorType", "RETRY_HANDLER_ERROR");
        }
        
        return result;
    }
    
    @Override
    public Map<String, Object> generateFriendlyErrorMessage(String errorType, Map<String, Object> context) {
        log.info("生成友好错误提示: errorType={}", errorType);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            String title = "";
            String message = "";
            String suggestion = "";
            String actionText = "";
            boolean showRetryButton = false;
            
            switch (errorType) {
                case "BANK_INFO_MISSING":
                    title = "银行信息不完整";
                    message = "您的贷款申请缺少必要的银行信息，无法继续处理。";
                    suggestion = "请完善银行选择信息后再试。";
                    actionText = "选择银行";
                    break;
                    
                case "BANK_SERVICE_UNAVAILABLE":
                    title = "银行服务暂时不可用";
                    message = "所选银行的服务暂时无法访问，这可能是临时的网络问题。";
                    suggestion = "您可以选择其他银行，或稍后重试。";
                    actionText = "选择其他银行";
                    showRetryButton = true;
                    break;
                    
                case "DATA_INCONSISTENCY":
                    title = "数据不一致";
                    message = "系统检测到您的贷款信息存在不一致的地方。";
                    suggestion = "系统将尝试自动修复，如果问题持续存在，请联系客服。";
                    actionText = "自动修复";
                    break;
                    
                case "NETWORK_ERROR":
                    title = "网络连接问题";
                    message = "网络连接不稳定，操作未能完成。";
                    suggestion = "请检查您的网络连接，然后重试。";
                    actionText = "重试";
                    showRetryButton = true;
                    break;
                    
                case "VALIDATION_ERROR":
                    title = "信息验证失败";
                    message = "您提交的信息未通过系统验证。";
                    suggestion = "请检查并修正标红的字段，然后重新提交。";
                    actionText = "重新填写";
                    break;
                    
                case "SUBMISSION_ERROR":
                    title = "提交失败";
                    message = "贷款申请提交过程中发生错误。";
                    suggestion = "请稍后重试，如果问题持续存在，请联系客服。";
                    actionText = "重新提交";
                    showRetryButton = true;
                    break;
                    
                default:
                    title = "操作失败";
                    message = "系统处理您的请求时发生了未知错误。";
                    suggestion = "请稍后重试，如果问题持续存在，请联系系统管理员。";
                    actionText = "重试";
                    showRetryButton = true;
                    break;
            }
            
            // 根据上下文信息个性化消息
            if (context != null) {
                if (context.containsKey("bankName")) {
                    message = message.replace("所选银行", "银行 " + context.get("bankName"));
                }
                if (context.containsKey("loanAmount")) {
                    message += String.format(" (贷款金额: ¥%s)", context.get("loanAmount"));
                }
                if (context.containsKey("retryCount")) {
                    int retryCount = (Integer) context.get("retryCount");
                    if (retryCount > 0) {
                        message += String.format(" (已重试 %d 次)", retryCount);
                    }
                }
            }
            
            result.put("title", title);
            result.put("message", message);
            result.put("suggestion", suggestion);
            result.put("actionText", actionText);
            result.put("showRetryButton", showRetryButton);
            result.put("errorType", errorType);
            result.put("timestamp", DateUtils.getTime());
            
        } catch (Exception e) {
            log.error("生成友好错误提示失败: errorType={}", errorType, e);
            result.put("title", "系统错误");
            result.put("message", "生成错误提示时发生异常");
            result.put("suggestion", "请联系系统管理员");
            result.put("actionText", "确定");
            result.put("showRetryButton", false);
        }
        
        return result;
    }
    
    @Override
    public Map<String, Object> checkAndRepairBankSelectionStatus(ServicePeriodLoan loan) {
        log.info("检查并修复银行选择状态: loanId={}", loan.getLinkId());
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 先进行数据一致性修复
            Map<String, Object> repairResult = autoRepairDataInconsistency(loan);
            
            // 然后验证银行信息
            Map<String, Object> validationResult = validateBankInformation(loan);
            
            boolean isHealthy = (Boolean) repairResult.get("success") && (Boolean) validationResult.get("valid");
            
            result.put("healthy", isHealthy);
            result.put("repairResult", repairResult);
            result.put("validationResult", validationResult);
            
            if (isHealthy) {
                result.put("message", "银行选择状态正常");
                result.put("status", "HEALTHY");
            } else {
                result.put("message", "银行选择状态存在问题，已尝试自动修复");
                result.put("status", "REPAIRED");
                
                // 如果修复后仍有问题，提供详细信息
                if (!(Boolean) validationResult.get("valid")) {
                    result.put("remainingIssues", validationResult.get("missingFields"));
                    result.put("suggestions", validationResult.get("suggestions"));
                }
            }
            
        } catch (Exception e) {
            log.error("检查并修复银行选择状态失败: loanId={}", loan.getLinkId(), e);
            result.put("healthy", false);
            result.put("message", "状态检查过程中发生错误: " + e.getMessage());
            result.put("status", "ERROR");
        }
        
        return result;
    }
    
    @Override
    public Map<String, Object> validateLoanSubmissionData(ServicePeriodLoan loan) {
        log.info("验证贷款提交前的数据完整性: loanId={}", loan.getLinkId());
        
        Map<String, Object> result = new HashMap<>();
        List<String> errors = new ArrayList<>();
        List<String> warnings = new ArrayList<>();
        
        try {
            // 1. 基础信息验证
            if (loan.getLoanAmount() == null || loan.getLoanAmount().compareTo(BigDecimal.ZERO) <= 0) {
                errors.add("贷款金额无效");
            }
            
            if (loan.getLoanTermMonths() == null || loan.getLoanTermMonths() <= 0) {
                errors.add("贷款期限无效");
            }
            
            if (StringUtils.isEmpty(loan.getLoanPurpose())) {
                errors.add("贷款用途不能为空");
            }
            
            // 2. 银行信息验证
            Map<String, Object> bankValidation = validateBankInformation(loan);
            if (!(Boolean) bankValidation.get("valid")) {
                errors.addAll((List<String>) bankValidation.get("missingFields"));
            }
            
            // 3. 状态验证
            if (!ServicePeriodLoan.STATUS_PENDING.equals(loan.getLoanStatus())) {
                errors.add("只有待提交状态的贷款才能提交");
            }
            
            // 4. 业务规则验证
            if (loan.getLoanAmount() != null && loan.getLoanAmount().compareTo(new BigDecimal("10000000")) > 0) {
                warnings.add("贷款金额较大，可能需要额外审批");
            }
            
            if (loan.getInterestRate() != null && loan.getInterestRate() > 0.15) {
                warnings.add("利率较高，建议重新选择银行");
            }
            
            // 5. 数据一致性验证
            if (loan.getMonthlyPayment() != null && loan.getInterestRate() != null 
                && loan.getLoanAmount() != null && loan.getLoanTermMonths() != null) {
                BigDecimal calculatedPayment = calculateMonthlyPayment(
                    loan.getLoanAmount(), loan.getInterestRate(), loan.getLoanTermMonths());
                
                if (Math.abs(loan.getMonthlyPayment().subtract(calculatedPayment).doubleValue()) > 1.0) {
                    warnings.add("月还款额与计算值不一致，建议重新计算");
                }
            }
            
            boolean isValid = errors.isEmpty();
            
            result.put("valid", isValid);
            result.put("errors", errors);
            result.put("warnings", warnings);
            result.put("errorCount", errors.size());
            result.put("warningCount", warnings.size());
            
            if (isValid) {
                if (warnings.isEmpty()) {
                    result.put("message", "数据验证通过，可以提交");
                    result.put("level", "SUCCESS");
                } else {
                    result.put("message", "数据验证通过，但有 " + warnings.size() + " 个警告");
                    result.put("level", "WARNING");
                }
            } else {
                result.put("message", "数据验证失败，发现 " + errors.size() + " 个错误");
                result.put("level", "ERROR");
            }
            
        } catch (Exception e) {
            log.error("验证贷款提交数据失败: loanId={}", loan.getLinkId(), e);
            result.put("valid", false);
            result.put("message", "验证过程中发生错误: " + e.getMessage());
            result.put("level", "ERROR");
        }
        
        return result;
    }
    
    @Override
    public Map<String, Object> handleBankServiceUnavailable(Long bankId, Long servicePeriodId) {
        log.info("处理银行服务不可用: bankId={}, servicePeriodId={}", bankId, servicePeriodId);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 获取备选银行列表
            Map<String, Object> alternativeBanks = servicePeriodLoanService.selectBankFinancingByContractTerm(servicePeriodId, 12);
            
            List<Map<String, Object>> availableAlternatives = new ArrayList<>();
            if (alternativeBanks.containsKey("matchedProducts")) {
                List<Map<String, Object>> products = (List<Map<String, Object>>) alternativeBanks.get("matchedProducts");
                for (Map<String, Object> product : products) {
                    Long productBankId = (Long) product.get("bankId");
                    if (!productBankId.equals(bankId)) {
                        availableAlternatives.add(product);
                    }
                }
            }
            
            result.put("hasAlternatives", !availableAlternatives.isEmpty());
            result.put("alternatives", availableAlternatives);
            result.put("alternativeCount", availableAlternatives.size());
            
            if (!availableAlternatives.isEmpty()) {
                result.put("message", String.format("找到 %d 个备选银行，建议选择其中一个继续申请", 
                                                   availableAlternatives.size()));
                result.put("suggestion", "选择备选银行");
                result.put("recommendedBank", availableAlternatives.get(0)); // 推荐第一个
            } else {
                result.put("message", "暂时没有可用的备选银行");
                result.put("suggestion", "请稍后重试，或联系客服寻求帮助");
            }
            
            result.put("retryable", true);
            result.put("errorType", "BANK_SERVICE_UNAVAILABLE");
            
        } catch (Exception e) {
            log.error("处理银行服务不可用失败: bankId={}", bankId, e);
            result.put("hasAlternatives", false);
            result.put("message", "获取备选银行信息失败: " + e.getMessage());
            result.put("suggestion", "请稍后重试");
        }
        
        return result;
    }
    
    // ==================== 私有辅助方法 ====================
    
    /**
     * 生成银行信息缺失的友好提示
     */
    private String generateBankInfoMissingMessage(List<String> missingFields, List<String> suggestions) {
        StringBuilder message = new StringBuilder();
        message.append("您的贷款申请缺少以下信息：");
        
        for (int i = 0; i < missingFields.size(); i++) {
            message.append("\n").append(i + 1).append(". ").append(missingFields.get(i));
        }
        
        message.append("\n\n建议操作：");
        for (int i = 0; i < suggestions.size(); i++) {
            message.append("\n").append("• ").append(suggestions.get(i));
        }
        
        return message.toString();
    }
    
    /**
     * 计算月还款额
     */
    private BigDecimal calculateMonthlyPayment(BigDecimal loanAmount, Double annualRate, Integer termMonths) {
        if (loanAmount == null || annualRate == null || termMonths == null || termMonths <= 0) {
            return BigDecimal.ZERO;
        }
        
        double monthlyRate = annualRate / 12;
        if (monthlyRate == 0) {
            return loanAmount.divide(new BigDecimal(termMonths), 2, BigDecimal.ROUND_HALF_UP);
        }
        
        double factor = Math.pow(1 + monthlyRate, termMonths);
        double monthlyPayment = loanAmount.doubleValue() * monthlyRate * factor / (factor - 1);
        
        return new BigDecimal(monthlyPayment).setScale(2, BigDecimal.ROUND_HALF_UP);
    }
    
    /**
     * 格式化银行选择历史记录
     */
    private String formatBankSelectionHistory(String history) {
        if (StringUtils.isEmpty(history)) {
            return history;
        }
        
        // 简单的格式化：确保每条记录都在新行
        return history.replaceAll(";\\s*", "\n").trim();
    }
    
    /**
     * 分析网络错误类型
     */
    private String analyzeNetworkError(Exception error) {
        if (error == null) {
            return "未知网络错误";
        }
        
        String errorMessage = error.getMessage();
        if (errorMessage == null) {
            return "网络连接异常";
        }
        
        if (errorMessage.contains("timeout")) {
            return "网络超时，请检查网络连接";
        } else if (errorMessage.contains("connection")) {
            return "连接失败，请检查网络设置";
        } else if (errorMessage.contains("refused")) {
            return "连接被拒绝，服务可能暂时不可用";
        } else {
            return "网络通信错误: " + errorMessage;
        }
    }
    
    /**
     * 生成重试历史记录
     */
    private Map<String, Object> generateRetryHistory(String operation, int retryCount, Exception lastError) {
        Map<String, Object> history = new HashMap<>();
        history.put("operation", operation);
        history.put("retryCount", retryCount);
        history.put("lastErrorTime", DateUtils.getTime());
        history.put("lastErrorMessage", lastError != null ? lastError.getMessage() : "未知错误");
        return history;
    }
}