package com.ruoyi.payment.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.payment.domain.EscrowAccount;
import com.ruoyi.payment.domain.FundTransfer;
import com.ruoyi.payment.mapper.EscrowAccountMapper;
import com.ruoyi.payment.mapper.FundTransferMapper;
import com.ruoyi.payment.service.ISettlementService;

/**
 * 资金分配和结算服务实现
 * 
 * @author ruoyi
 */
@Service
public class SettlementServiceImpl implements ISettlementService {
    
    private static final Logger log = LoggerFactory.getLogger(SettlementServiceImpl.class);
    
    @Autowired
    private EscrowAccountMapper escrowAccountMapper;
    
    @Autowired
    private FundTransferMapper fundTransferMapper;
    
    // 转账类型常量
    private static final String TRANSFER_TYPE_REPAYMENT = "REPAYMENT";
    private static final String TRANSFER_TYPE_DISTRIBUTION = "DISTRIBUTION";
    private static final String TRANSFER_TYPE_SETTLEMENT = "SETTLEMENT";
    
    // 转账状态常量
    private static final String TRANSFER_STATUS_SUCCESS = "SUCCESS";
    private static final String TRANSFER_STATUS_PENDING = "PENDING";
    private static final String TRANSFER_STATUS_FAILED = "FAILED";
    
    @Override
    @Transactional
    public Map<String, Object> executeSettlement(Long escrowAccountId, BigDecimal totalAmount) {
        log.info("开始执行资金分配和结算: escrowAccountId={}, totalAmount={}", escrowAccountId, totalAmount);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 验证资金分配的合法性
            if (!validateSettlement(escrowAccountId, totalAmount)) {
                throw new RuntimeException("资金分配验证失败");
            }
            
            // 获取监管账户信息
            EscrowAccount escrowAccount = escrowAccountMapper.selectEscrowAccountByAccountId(escrowAccountId);
            if (escrowAccount == null) {
                throw new RuntimeException("监管账户不存在");
            }
            
            Long applicationId = escrowAccount.getApplicationId();
            BigDecimal availableAmount = totalAmount;
            
            // 第一步：偿还贷款本金和利息（优先级最高）
            Map<String, Object> loanRepaymentResult = repayLoan(applicationId, availableAmount);
            BigDecimal remainingAfterLoan = (BigDecimal) loanRepaymentResult.get("remainingAmount");
            
            result.put("loanRepayment", loanRepaymentResult);
            
            // 第二步：分配剩余资金给安保公司
            if (remainingAfterLoan.compareTo(BigDecimal.ZERO) > 0) {
                // 这里需要从合同ID获取，暂时使用applicationId作为contractId
                Long contractId = applicationId; // TODO: 从融资申请获取实际的合同ID
                
                FundTransfer distributionTransfer = distributeRemainingFunds(contractId, remainingAfterLoan);
                result.put("remainingDistribution", distributionTransfer);
                
                // 第三步：更新债权状态为已结清
                // TODO: 需要从合同获取债权ID
                Long creditId = contractId; // TODO: 从合同获取实际的债权ID
                boolean creditUpdated = updateCreditStatusToSettled(creditId);
                result.put("creditStatusUpdated", creditUpdated);
            }
            
            result.put("success", true);
            result.put("totalAmount", totalAmount);
            result.put("finalRemainingAmount", remainingAfterLoan);
            
            log.info("资金分配和结算完成: escrowAccountId={}, result={}", escrowAccountId, result);
            
        } catch (Exception e) {
            log.error("资金分配和结算失败: escrowAccountId={}, error={}", escrowAccountId, e.getMessage(), e);
            result.put("success", false);
            result.put("error", e.getMessage());
            throw new RuntimeException("资金分配和结算失败: " + e.getMessage());
        }
        
        return result;
    }
    
    @Override
    @Transactional
    public Map<String, Object> repayLoan(Long applicationId, BigDecimal availableAmount) {
        log.info("开始偿还贷款: applicationId={}, availableAmount={}", applicationId, availableAmount);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 计算贷款偿还金额
            Map<String, BigDecimal> repaymentAmounts = calculateLoanRepaymentAmount(applicationId);
            BigDecimal principalAmount = repaymentAmounts.get("principal");
            BigDecimal interestAmount = repaymentAmounts.get("interest");
            BigDecimal totalRepaymentAmount = repaymentAmounts.get("total");
            
            if (availableAmount.compareTo(totalRepaymentAmount) < 0) {
                throw new RuntimeException("可用金额不足以偿还贷款: 需要=" + totalRepaymentAmount + ", 可用=" + availableAmount);
            }
            
            // 执行贷款偿还转账
            // TODO: 这里需要实际的金融机构账户ID，暂时使用固定值
            Long financialInstitutionAccountId = 999L; // TODO: 从融资申请获取金融机构账户ID
            Long escrowAccountId = 1L; // TODO: 从参数获取实际的监管账户ID
            
            FundTransfer repaymentTransfer = executeFundTransfer(
                escrowAccountId, 
                financialInstitutionAccountId, 
                totalRepaymentAmount, 
                TRANSFER_TYPE_REPAYMENT, 
                "贷款偿还: 本金=" + principalAmount + ", 利息=" + interestAmount
            );
            
            BigDecimal remainingAmount = availableAmount.subtract(totalRepaymentAmount);
            
            result.put("success", true);
            result.put("principalAmount", principalAmount);
            result.put("interestAmount", interestAmount);
            result.put("totalRepaymentAmount", totalRepaymentAmount);
            result.put("remainingAmount", remainingAmount);
            result.put("repaymentTransfer", repaymentTransfer);
            
            log.info("贷款偿还完成: applicationId={}, repaymentAmount={}, remaining={}", 
                    applicationId, totalRepaymentAmount, remainingAmount);
            
        } catch (Exception e) {
            log.error("贷款偿还失败: applicationId={}, error={}", applicationId, e.getMessage(), e);
            result.put("success", false);
            result.put("error", e.getMessage());
            result.put("remainingAmount", availableAmount);
            throw new RuntimeException("贷款偿还失败: " + e.getMessage());
        }
        
        return result;
    }
    
    @Override
    @Transactional
    public FundTransfer distributeRemainingFunds(Long contractId, BigDecimal remainingAmount) {
        log.info("开始分配剩余资金: contractId={}, remainingAmount={}", contractId, remainingAmount);
        
        try {
            if (remainingAmount.compareTo(BigDecimal.ZERO) <= 0) {
                throw new RuntimeException("剩余金额必须大于0");
            }
            
            // TODO: 这里需要从合同获取安保公司账户ID，暂时使用固定值
            Long securityCompanyAccountId = 888L; // TODO: 从合同获取安保公司账户ID
            Long escrowAccountId = 1L; // TODO: 从参数获取实际的监管账户ID
            
            FundTransfer distributionTransfer = executeFundTransfer(
                escrowAccountId,
                securityCompanyAccountId,
                remainingAmount,
                TRANSFER_TYPE_DISTRIBUTION,
                "剩余资金分配给安保公司: 合同ID=" + contractId
            );
            
            log.info("剩余资金分配完成: contractId={}, amount={}, transferId={}", 
                    contractId, remainingAmount, distributionTransfer.getTransferId());
            
            return distributionTransfer;
            
        } catch (Exception e) {
            log.error("剩余资金分配失败: contractId={}, error={}", contractId, e.getMessage(), e);
            throw new RuntimeException("剩余资金分配失败: " + e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public boolean updateCreditStatusToSettled(Long creditId) {
        log.info("更新债权状态为已结清: creditId={}", creditId);
        
        try {
            // TODO: 这里需要调用债权服务来更新债权状态
            // 暂时返回true表示更新成功
            log.info("债权状态更新为已结清: creditId={}", creditId);
            return true;
            
        } catch (Exception e) {
            log.error("更新债权状态失败: creditId={}, error={}", creditId, e.getMessage(), e);
            return false;
        }
    }
    
    @Override
    public Map<String, BigDecimal> calculateLoanRepaymentAmount(Long applicationId) {
        log.info("计算贷款偿还金额: applicationId={}", applicationId);
        
        Map<String, BigDecimal> amounts = new HashMap<>();
        
        try {
            // TODO: 这里需要从融资申请获取实际的贷款信息
            // 暂时使用模拟数据
            BigDecimal principalAmount = new BigDecimal("100000.00"); // 本金
            BigDecimal interestRate = new BigDecimal("0.05"); // 5%年利率
            BigDecimal interestAmount = principalAmount.multiply(interestRate); // 利息
            BigDecimal totalAmount = principalAmount.add(interestAmount);
            
            amounts.put("principal", principalAmount);
            amounts.put("interest", interestAmount);
            amounts.put("total", totalAmount);
            
            log.info("贷款偿还金额计算完成: applicationId={}, principal={}, interest={}, total={}", 
                    applicationId, principalAmount, interestAmount, totalAmount);
            
        } catch (Exception e) {
            log.error("计算贷款偿还金额失败: applicationId={}, error={}", applicationId, e.getMessage(), e);
            // 返回默认值
            amounts.put("principal", BigDecimal.ZERO);
            amounts.put("interest", BigDecimal.ZERO);
            amounts.put("total", BigDecimal.ZERO);
        }
        
        return amounts;
    }
    
    @Override
    public boolean validateSettlement(Long escrowAccountId, BigDecimal totalAmount) {
        try {
            // 验证监管账户是否存在
            EscrowAccount escrowAccount = escrowAccountMapper.selectEscrowAccountByAccountId(escrowAccountId);
            if (escrowAccount == null) {
                log.error("监管账户不存在: escrowAccountId={}", escrowAccountId);
                return false;
            }
            
            // 验证账户状态
            if (!"ACTIVE".equals(escrowAccount.getAccountStatus())) {
                log.error("监管账户状态不正确: escrowAccountId={}, status={}", 
                         escrowAccountId, escrowAccount.getAccountStatus());
                return false;
            }
            
            // 验证金额
            if (totalAmount == null || totalAmount.compareTo(BigDecimal.ZERO) <= 0) {
                log.error("总金额无效: totalAmount={}", totalAmount);
                return false;
            }
            
            // 验证账户余额
            if (escrowAccount.getAvailableAmount().compareTo(totalAmount) < 0) {
                log.error("账户可用余额不足: available={}, required={}", 
                         escrowAccount.getAvailableAmount(), totalAmount);
                return false;
            }
            
            return true;
            
        } catch (Exception e) {
            log.error("验证资金分配失败: escrowAccountId={}, error={}", escrowAccountId, e.getMessage(), e);
            return false;
        }
    }
    
    @Override
    public Map<String, Object> getSettlementPlan(Long escrowAccountId, BigDecimal totalAmount) {
        Map<String, Object> plan = new HashMap<>();
        
        try {
            EscrowAccount escrowAccount = escrowAccountMapper.selectEscrowAccountByAccountId(escrowAccountId);
            if (escrowAccount == null) {
                throw new RuntimeException("监管账户不存在");
            }
            
            Long applicationId = escrowAccount.getApplicationId();
            
            // 计算贷款偿还金额
            Map<String, BigDecimal> repaymentAmounts = calculateLoanRepaymentAmount(applicationId);
            BigDecimal totalRepaymentAmount = repaymentAmounts.get("total");
            BigDecimal remainingAmount = totalAmount.subtract(totalRepaymentAmount);
            
            plan.put("totalAmount", totalAmount);
            plan.put("loanRepayment", repaymentAmounts);
            plan.put("remainingForDistribution", remainingAmount.max(BigDecimal.ZERO));
            plan.put("canFullyRepayLoan", totalAmount.compareTo(totalRepaymentAmount) >= 0);
            
        } catch (Exception e) {
            log.error("获取结算计划失败: escrowAccountId={}, error={}", escrowAccountId, e.getMessage(), e);
            plan.put("error", e.getMessage());
        }
        
        return plan;
    }
    
    @Override
    @Transactional
    public FundTransfer executeFundTransfer(Long fromAccountId, Long toAccountId, 
                                          BigDecimal amount, String transferType, String description) {
        log.info("执行资金转账: from={}, to={}, amount={}, type={}", 
                fromAccountId, toAccountId, amount, transferType);
        
        try {
            // 创建资金流转记录
            FundTransfer fundTransfer = new FundTransfer();
            fundTransfer.setTransferNumber(generateTransferNumber());
            fundTransfer.setFromAccountId(fromAccountId);
            fundTransfer.setToAccountId(toAccountId);
            fundTransfer.setTransferAmount(amount);
            fundTransfer.setTransferType(transferType);
            fundTransfer.setTransferStatus(TRANSFER_STATUS_PENDING);
            fundTransfer.setDescription(description);
            fundTransfer.setTransferTime(DateUtils.getNowDate());
            fundTransfer.setCreateTime(DateUtils.getNowDate());
            
            // 插入转账记录
            int result = fundTransferMapper.insertFundTransfer(fundTransfer);
            if (result <= 0) {
                throw new RuntimeException("创建资金流转记录失败");
            }
            
            // 更新转账状态为成功
            fundTransferMapper.updateTransferStatus(fundTransfer.getTransferId(), TRANSFER_STATUS_SUCCESS);
            fundTransfer.setTransferStatus(TRANSFER_STATUS_SUCCESS);
            
            log.info("资金转账完成: transferId={}, transferNumber={}", 
                    fundTransfer.getTransferId(), fundTransfer.getTransferNumber());
            
            return fundTransfer;
            
        } catch (Exception e) {
            log.error("执行资金转账失败: from={}, to={}, amount={}, error={}", 
                     fromAccountId, toAccountId, amount, e.getMessage(), e);
            throw new RuntimeException("资金转账失败: " + e.getMessage());
        }
    }
    
    @Override
    public List<FundTransfer> getSettlementHistory(Long escrowAccountId) {
        try {
            // 查询与该监管账户相关的所有转账记录
            List<FundTransfer> fromTransfers = fundTransferMapper.selectFundTransferByFromAccountId(escrowAccountId);
            List<FundTransfer> toTransfers = fundTransferMapper.selectFundTransferByToAccountId(escrowAccountId);
            
            List<FundTransfer> allTransfers = new ArrayList<>();
            allTransfers.addAll(fromTransfers);
            allTransfers.addAll(toTransfers);
            
            return allTransfers;
            
        } catch (Exception e) {
            log.error("获取结算历史失败: escrowAccountId={}, error={}", escrowAccountId, e.getMessage(), e);
            return new ArrayList<>();
        }
    }
    
    @Override
    public boolean isAllDebtsSettled(Long contractId) {
        try {
            // TODO: 这里需要检查合同相关的所有债务是否已结清
            // 暂时返回true
            log.info("检查债务结清状态: contractId={}", contractId);
            return true;
            
        } catch (Exception e) {
            log.error("检查债务结清状态失败: contractId={}, error={}", contractId, e.getMessage(), e);
            return false;
        }
    }
    
    @Override
    public Map<String, Object> generateSettlementReport(Long escrowAccountId) {
        Map<String, Object> report = new HashMap<>();
        
        try {
            EscrowAccount escrowAccount = escrowAccountMapper.selectEscrowAccountByAccountId(escrowAccountId);
            List<FundTransfer> history = getSettlementHistory(escrowAccountId);
            
            report.put("escrowAccount", escrowAccount);
            report.put("transferHistory", history);
            report.put("totalTransfers", history.size());
            report.put("generatedAt", DateUtils.getNowDate());
            
            // 计算总转入和转出金额
            BigDecimal totalInflow = BigDecimal.ZERO;
            BigDecimal totalOutflow = BigDecimal.ZERO;
            
            for (FundTransfer transfer : history) {
                if (escrowAccountId.equals(transfer.getToAccountId())) {
                    totalInflow = totalInflow.add(transfer.getTransferAmount());
                } else if (escrowAccountId.equals(transfer.getFromAccountId())) {
                    totalOutflow = totalOutflow.add(transfer.getTransferAmount());
                }
            }
            
            report.put("totalInflow", totalInflow);
            report.put("totalOutflow", totalOutflow);
            report.put("netAmount", totalInflow.subtract(totalOutflow));
            
        } catch (Exception e) {
            log.error("生成结算报告失败: escrowAccountId={}, error={}", escrowAccountId, e.getMessage(), e);
            report.put("error", e.getMessage());
        }
        
        return report;
    }
    
    /**
     * 生成转账编号
     */
    private String generateTransferNumber() {
        String dateStr = DateUtils.dateTimeNow("yyyyMMdd");
        String randomStr = IdUtils.randomUUID().substring(0, 6).toUpperCase();
        return "TRF" + dateStr + randomStr;
    }
}