package com.ruoyi.payment.service.impl;

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

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

import com.ruoyi.payment.domain.EscrowAccount;
import com.ruoyi.payment.mapper.EscrowAccountMapper;
import com.ruoyi.payment.service.IEscrowAccountService;

/**
 * 资金监管账户服务实现
 * 
 * @author ruoyi
 * @date 2025-12-19
 */
@Service
public class EscrowAccountServiceImpl implements IEscrowAccountService 
{
    private static final Logger log = LoggerFactory.getLogger(EscrowAccountServiceImpl.class);

    @Autowired
    private EscrowAccountMapper escrowAccountMapper;

    /**
     * 创建监管账户
     */
    @Override
    @Transactional
    public EscrowAccount createEscrowAccount(Long applicationId, BigDecimal totalAmount) 
    {
        log.info("创建监管账户: applicationId={}, totalAmount={}", applicationId, totalAmount);

        try {
            // 检查是否已存在账户
            EscrowAccount existingAccount = escrowAccountMapper.selectEscrowAccountByApplicationId(applicationId);
            if (existingAccount != null) {
                log.warn("融资申请已存在监管账户: applicationId={}, accountId={}", 
                         applicationId, existingAccount.getAccountId());
                return existingAccount;
            }

            // 创建新账户
            EscrowAccount account = new EscrowAccount();
            account.setAccountNumber(generateAccountNumber());
            account.setApplicationId(applicationId);
            account.setTotalAmount(totalAmount);
            account.setAvailableAmount(BigDecimal.ZERO); // 初始可用金额为0
            account.setFrozenAmount(BigDecimal.ZERO); // 初始冻结金额为0
            account.setAccountStatus("ACTIVE");
            account.setCreateTime(new Date());

            int result = escrowAccountMapper.insertEscrowAccount(account);
            if (result > 0) {
                log.info("监管账户创建成功: accountNumber={}, applicationId={}", 
                         account.getAccountNumber(), applicationId);
                return account;
            } else {
                throw new RuntimeException("监管账户创建失败");
            }
        } catch (Exception e) {
            log.error("创建监管账户异常: applicationId={}", applicationId, e);
            throw new RuntimeException("创建监管账户失败: " + e.getMessage());
        }
    }

    /**
     * 资金存入
     */
    @Override
    @Transactional
    public boolean depositFunds(Long accountId, BigDecimal amount) 
    {
        log.info("资金存入: accountId={}, amount={}", accountId, amount);

        try {
            if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
                log.error("存入金额无效: amount={}", amount);
                return false;
            }

            EscrowAccount account = escrowAccountMapper.selectEscrowAccountByAccountId(accountId);
            if (account == null) {
                log.error("监管账户不存在: accountId={}", accountId);
                return false;
            }

            if (!"ACTIVE".equals(account.getAccountStatus())) {
                log.error("账户状态不允许存入: accountId={}, status={}", accountId, account.getAccountStatus());
                return false;
            }

            // 更新可用金额
            BigDecimal newAvailableAmount = account.getAvailableAmount().add(amount);
            BigDecimal newTotalAmount = account.getTotalAmount().add(amount); // 存入时总金额也增加
            int result = escrowAccountMapper.updateAccountBalance(accountId, newTotalAmount, newAvailableAmount, account.getFrozenAmount());

            if (result > 0) {
                log.info("资金存入成功: accountId={}, amount={}, newBalance={}", 
                         accountId, amount, newAvailableAmount);
                return true;
            } else {
                log.error("资金存入失败: accountId={}", accountId);
                return false;
            }
        } catch (Exception e) {
            log.error("资金存入异常: accountId={}, amount={}", accountId, amount, e);
            return false;
        }
    }

    /**
     * 资金分配
     */
    @Override
    @Transactional
    public boolean distributeFunds(Long accountId, Map<String, BigDecimal> distributionPlan) 
    {
        log.info("资金分配: accountId={}, distributionPlan={}", accountId, distributionPlan);

        try {
            EscrowAccount account = escrowAccountMapper.selectEscrowAccountByAccountId(accountId);
            if (account == null) {
                log.error("监管账户不存在: accountId={}", accountId);
                return false;
            }

            // 计算总分配金额
            BigDecimal totalDistribution = distributionPlan.values().stream()
                .reduce(BigDecimal.ZERO, BigDecimal::add);

            // 验证余额充足
            if (account.getAvailableAmount().compareTo(totalDistribution) < 0) {
                log.error("账户余额不足: accountId={}, available={}, required={}", 
                         accountId, account.getAvailableAmount(), totalDistribution);
                return false;
            }

            // 执行分配（这里简化处理，实际应该调用具体的转账逻辑）
            BigDecimal newAvailableAmount = account.getAvailableAmount().subtract(totalDistribution);
            int result = escrowAccountMapper.updateAccountBalance(accountId, account.getTotalAmount(), newAvailableAmount, account.getFrozenAmount());

            if (result > 0) {
                log.info("资金分配成功: accountId={}, totalDistribution={}, remainingBalance={}", 
                         accountId, totalDistribution, newAvailableAmount);
                
                // 记录分配详情
                for (Map.Entry<String, BigDecimal> entry : distributionPlan.entrySet()) {
                    log.info("分配详情: recipient={}, amount={}", entry.getKey(), entry.getValue());
                }
                
                return true;
            } else {
                log.error("资金分配失败: accountId={}", accountId);
                return false;
            }
        } catch (Exception e) {
            log.error("资金分配异常: accountId={}", accountId, e);
            return false;
        }
    }

    /**
     * 资金转账
     */
    @Override
    @Transactional
    public boolean transferFunds(Long fromAccountId, Long toAccountId, BigDecimal amount) 
    {
        log.info("资金转账: fromAccountId={}, toAccountId={}, amount={}", fromAccountId, toAccountId, amount);

        try {
            if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
                log.error("转账金额无效: amount={}", amount);
                return false;
            }

            // 验证转出账户
            EscrowAccount fromAccount = escrowAccountMapper.selectEscrowAccountByAccountId(fromAccountId);
            if (fromAccount == null || !"ACTIVE".equals(fromAccount.getAccountStatus())) {
                log.error("转出账户无效: fromAccountId={}", fromAccountId);
                return false;
            }

            // 验证转入账户
            EscrowAccount toAccount = escrowAccountMapper.selectEscrowAccountByAccountId(toAccountId);
            if (toAccount == null || !"ACTIVE".equals(toAccount.getAccountStatus())) {
                log.error("转入账户无效: toAccountId={}", toAccountId);
                return false;
            }

            // 验证余额充足
            if (fromAccount.getAvailableAmount().compareTo(amount) < 0) {
                log.error("转出账户余额不足: fromAccountId={}, available={}, required={}", 
                         fromAccountId, fromAccount.getAvailableAmount(), amount);
                return false;
            }

            // 执行转账
            BigDecimal newFromBalance = fromAccount.getAvailableAmount().subtract(amount);
            BigDecimal newToBalance = toAccount.getAvailableAmount().add(amount);

            int fromResult = escrowAccountMapper.updateAccountBalance(fromAccountId, fromAccount.getTotalAmount(), newFromBalance, fromAccount.getFrozenAmount());
            int toResult = escrowAccountMapper.updateAccountBalance(toAccountId, toAccount.getTotalAmount(), newToBalance, toAccount.getFrozenAmount());

            if (fromResult > 0 && toResult > 0) {
                log.info("资金转账成功: fromAccountId={}, toAccountId={}, amount={}", 
                         fromAccountId, toAccountId, amount);
                return true;
            } else {
                log.error("资金转账失败: fromAccountId={}, toAccountId={}", fromAccountId, toAccountId);
                return false;
            }
        } catch (Exception e) {
            log.error("资金转账异常: fromAccountId={}, toAccountId={}, amount={}", 
                     fromAccountId, toAccountId, amount, e);
            return false;
        }
    }

    /**
     * 冻结资金
     */
    @Override
    @Transactional
    public boolean freezeFunds(Long accountId, BigDecimal amount) 
    {
        log.info("冻结资金: accountId={}, amount={}", accountId, amount);

        try {
            if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
                log.error("冻结金额无效: amount={}", amount);
                return false;
            }

            EscrowAccount account = escrowAccountMapper.selectEscrowAccountByAccountId(accountId);
            if (account == null) {
                log.error("监管账户不存在: accountId={}", accountId);
                return false;
            }

            // 验证可用余额充足
            if (account.getAvailableAmount().compareTo(amount) < 0) {
                log.error("可用余额不足: accountId={}, available={}, required={}", 
                         accountId, account.getAvailableAmount(), amount);
                return false;
            }

            // 执行冻结
            BigDecimal newAvailableAmount = account.getAvailableAmount().subtract(amount);
            BigDecimal newFrozenAmount = account.getFrozenAmount().add(amount);

            int result = escrowAccountMapper.updateAccountBalance(accountId, account.getTotalAmount(), newAvailableAmount, newFrozenAmount);

            if (result > 0) {
                log.info("资金冻结成功: accountId={}, amount={}, availableBalance={}, frozenBalance={}", 
                         accountId, amount, newAvailableAmount, newFrozenAmount);
                return true;
            } else {
                log.error("资金冻结失败: accountId={}", accountId);
                return false;
            }
        } catch (Exception e) {
            log.error("资金冻结异常: accountId={}, amount={}", accountId, amount, e);
            return false;
        }
    }

    /**
     * 解冻资金
     */
    @Override
    @Transactional
    public boolean unfreezeFunds(Long accountId, BigDecimal amount) 
    {
        log.info("解冻资金: accountId={}, amount={}", accountId, amount);

        try {
            if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
                log.error("解冻金额无效: amount={}", amount);
                return false;
            }

            EscrowAccount account = escrowAccountMapper.selectEscrowAccountByAccountId(accountId);
            if (account == null) {
                log.error("监管账户不存在: accountId={}", accountId);
                return false;
            }

            // 验证冻结余额充足
            if (account.getFrozenAmount().compareTo(amount) < 0) {
                log.error("冻结余额不足: accountId={}, frozen={}, required={}", 
                         accountId, account.getFrozenAmount(), amount);
                return false;
            }

            // 执行解冻
            BigDecimal newAvailableAmount = account.getAvailableAmount().add(amount);
            BigDecimal newFrozenAmount = account.getFrozenAmount().subtract(amount);

            int result = escrowAccountMapper.updateAccountBalance(accountId, account.getTotalAmount(), newAvailableAmount, newFrozenAmount);

            if (result > 0) {
                log.info("资金解冻成功: accountId={}, amount={}, availableBalance={}, frozenBalance={}", 
                         accountId, amount, newAvailableAmount, newFrozenAmount);
                return true;
            } else {
                log.error("资金解冻失败: accountId={}", accountId);
                return false;
            }
        } catch (Exception e) {
            log.error("资金解冻异常: accountId={}, amount={}", accountId, amount, e);
            return false;
        }
    }

    /**
     * 查询账户余额
     */
    @Override
    public Map<String, BigDecimal> getAccountBalance(Long accountId) 
    {
        log.info("查询账户余额: accountId={}", accountId);

        Map<String, BigDecimal> balance = new HashMap<>();
        
        try {
            EscrowAccount account = escrowAccountMapper.selectEscrowAccountByAccountId(accountId);
            if (account != null) {
                balance.put("totalAmount", account.getTotalAmount());
                balance.put("availableAmount", account.getAvailableAmount());
                balance.put("frozenAmount", account.getFrozenAmount());
                balance.put("usedAmount", account.getTotalAmount().subtract(account.getAvailableAmount()).subtract(account.getFrozenAmount()));
            } else {
                log.warn("监管账户不存在: accountId={}", accountId);
            }
        } catch (Exception e) {
            log.error("查询账户余额异常: accountId={}", accountId, e);
        }
        
        return balance;
    }

    /**
     * 监控账户状态
     */
    @Override
    public Map<String, Object> monitorAccountStatus(Long accountId) 
    {
        log.info("监控账户状态: accountId={}", accountId);

        Map<String, Object> status = new HashMap<>();
        
        try {
            EscrowAccount account = escrowAccountMapper.selectEscrowAccountByAccountId(accountId);
            if (account != null) {
                status.put("accountId", account.getAccountId());
                status.put("accountNumber", account.getAccountNumber());
                status.put("accountStatus", account.getAccountStatus());
                status.put("applicationId", account.getApplicationId());
                status.put("totalAmount", account.getTotalAmount());
                status.put("availableAmount", account.getAvailableAmount());
                status.put("frozenAmount", account.getFrozenAmount());
                status.put("createTime", account.getCreateTime());
                status.put("updateTime", account.getUpdateTime());
                
                // 计算使用率
                BigDecimal usedAmount = account.getTotalAmount().subtract(account.getAvailableAmount()).subtract(account.getFrozenAmount());
                BigDecimal usageRate = account.getTotalAmount().compareTo(BigDecimal.ZERO) > 0 ? 
                    usedAmount.divide(account.getTotalAmount(), 4, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
                status.put("usageRate", usageRate);
                
                // 账户健康状态
                String healthStatus = "HEALTHY";
                if (account.getAvailableAmount().compareTo(BigDecimal.ZERO) == 0) {
                    healthStatus = "NO_FUNDS";
                } else if (usageRate.compareTo(new BigDecimal("0.9")) > 0) {
                    healthStatus = "HIGH_USAGE";
                } else if (usageRate.compareTo(new BigDecimal("0.7")) > 0) {
                    healthStatus = "MEDIUM_USAGE";
                }
                status.put("healthStatus", healthStatus);
                
            } else {
                status.put("error", "监管账户不存在");
            }
        } catch (Exception e) {
            log.error("监控账户状态异常: accountId={}", accountId, e);
            status.put("error", "监控失败: " + e.getMessage());
        }
        
        return status;
    }

    /**
     * 跟踪资金流向
     */
    @Override
    public List<Map<String, Object>> trackFundFlow(Long accountId) 
    {
        log.info("跟踪资金流向: accountId={}", accountId);

        List<Map<String, Object>> flowRecords = new ArrayList<>();
        
        try {
            // 这里简化处理，实际应该查询资金流转记录表
            EscrowAccount account = escrowAccountMapper.selectEscrowAccountByAccountId(accountId);
            if (account != null) {
                Map<String, Object> record = new HashMap<>();
                record.put("accountId", accountId);
                record.put("accountNumber", account.getAccountNumber());
                record.put("currentBalance", account.getAvailableAmount());
                record.put("frozenAmount", account.getFrozenAmount());
                record.put("lastUpdateTime", account.getUpdateTime());
                record.put("flowType", "BALANCE_INQUIRY");
                record.put("description", "账户余额查询");
                
                flowRecords.add(record);
            }
        } catch (Exception e) {
            log.error("跟踪资金流向异常: accountId={}", accountId, e);
        }
        
        return flowRecords;
    }

    /**
     * 查询监管账户
     */
    @Override
    public EscrowAccount selectEscrowAccountById(Long accountId) 
    {
        return escrowAccountMapper.selectEscrowAccountByAccountId(accountId);
    }

    /**
     * 根据申请ID查询监管账户
     */
    @Override
    public EscrowAccount selectEscrowAccountByApplicationId(Long applicationId) 
    {
        return escrowAccountMapper.selectEscrowAccountByApplicationId(applicationId);
    }

    /**
     * 查询监管账户列表
     */
    @Override
    public List<EscrowAccount> selectEscrowAccountList(EscrowAccount escrowAccount) 
    {
        return escrowAccountMapper.selectEscrowAccountList(escrowAccount);
    }

    /**
     * 更新账户状态
     */
    @Override
    @Transactional
    public boolean updateAccountStatus(Long accountId, String status) 
    {
        try {
            int result = escrowAccountMapper.updateAccountStatus(accountId, status);
            return result > 0;
        } catch (Exception e) {
            log.error("更新账户状态异常: accountId={}, status={}", accountId, status, e);
            return false;
        }
    }

    /**
     * 生成账户号码
     */
    @Override
    public String generateAccountNumber() 
    {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String dateStr = sdf.format(new Date());
        long timestamp = System.currentTimeMillis() % 100000;
        return "ESC" + dateStr + String.format("%05d", timestamp);
    }

    /**
     * 验证账户余额充足
     */
    @Override
    public boolean validateSufficientBalance(Long accountId, BigDecimal amount) 
    {
        try {
            EscrowAccount account = escrowAccountMapper.selectEscrowAccountByAccountId(accountId);
            if (account == null) {
                return false;
            }
            return account.getAvailableAmount().compareTo(amount) >= 0;
        } catch (Exception e) {
            log.error("验证账户余额异常: accountId={}, amount={}", accountId, amount, e);
            return false;
        }
    }
}