package com.ruoyi.payment.service.impl;

import java.math.BigDecimal;
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.blockchain.service.BlockchainIntegrator;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.payment.domain.PaymentRecord;
import com.ruoyi.payment.mapper.PaymentRecordMapper;
import com.ruoyi.payment.service.IPaymentService;

/**
 * 支付处理服务实现
 * 
 * @author ruoyi
 */
@Service
public class PaymentServiceImpl implements IPaymentService {
    
    private static final Logger log = LoggerFactory.getLogger(PaymentServiceImpl.class);
    
    @Autowired
    private PaymentRecordMapper paymentRecordMapper;
    
    @Autowired
    private BlockchainIntegrator blockchainIntegrator;
    
    // 支付状态常量
    private static final String PAYMENT_STATUS_PENDING = "PENDING";
    private static final String PAYMENT_STATUS_PROCESSING = "PROCESSING";
    private static final String PAYMENT_STATUS_SUCCESS = "SUCCESS";
    private static final String PAYMENT_STATUS_FAILED = "FAILED";
    private static final String PAYMENT_STATUS_CONFIRMED = "CONFIRMED";
    
    @Override
    @Transactional
    public PaymentRecord processPayment(Long contractId, Long payerId, Long payeeId, 
                                      BigDecimal paymentAmount, String paymentMethod, String transactionId) {
        log.info("开始处理支付: contractId={}, payerId={}, payeeId={}, amount={}", 
                contractId, payerId, payeeId, paymentAmount);
        
        // 验证支付数据
        if (!validatePaymentData(contractId, paymentAmount, payerId)) {
            throw new RuntimeException("支付数据验证失败");
        }
        
        // 创建支付记录
        PaymentRecord paymentRecord = new PaymentRecord();
        paymentRecord.setPaymentNumber(generatePaymentNumber());
        paymentRecord.setContractId(contractId);
        paymentRecord.setPayerId(payerId);
        paymentRecord.setPayeeId(payeeId);
        paymentRecord.setPaymentAmount(paymentAmount);
        paymentRecord.setPaymentMethod(paymentMethod);
        paymentRecord.setPaymentStatus(PAYMENT_STATUS_PENDING);
        paymentRecord.setPaymentTime(DateUtils.getNowDate());
        paymentRecord.setTransactionId(transactionId);
        paymentRecord.setCreateTime(DateUtils.getNowDate());
        
        try {
            // 插入支付记录
            int result = paymentRecordMapper.insertPaymentRecord(paymentRecord);
            if (result <= 0) {
                throw new RuntimeException("创建支付记录失败");
            }
            
            // 更新状态为处理中
            updatePaymentStatus(paymentRecord.getPaymentId(), PAYMENT_STATUS_PROCESSING);
            
            log.info("支付记录创建成功: paymentId={}, paymentNumber={}", 
                    paymentRecord.getPaymentId(), paymentRecord.getPaymentNumber());
            
            return paymentRecord;
            
        } catch (Exception e) {
            log.error("处理支付失败: {}", e.getMessage(), e);
            if (paymentRecord.getPaymentId() != null) {
                handlePaymentException(paymentRecord.getPaymentId(), e.getMessage());
            }
            throw new RuntimeException("支付处理失败: " + e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public boolean confirmPayment(Long paymentId) {
        log.info("确认支付: paymentId={}", paymentId);
        
        try {
            PaymentRecord paymentRecord = paymentRecordMapper.selectPaymentRecordByPaymentId(paymentId);
            if (paymentRecord == null) {
                log.error("支付记录不存在: paymentId={}", paymentId);
                return false;
            }
            
            // 检查支付状态
            if (!PAYMENT_STATUS_PROCESSING.equals(paymentRecord.getPaymentStatus()) &&
                !PAYMENT_STATUS_SUCCESS.equals(paymentRecord.getPaymentStatus())) {
                log.error("支付状态不允许确认: paymentId={}, status={}", 
                         paymentId, paymentRecord.getPaymentStatus());
                return false;
            }
            
            // 确认支付
            Date confirmTime = DateUtils.getNowDate();
            int result = paymentRecordMapper.confirmPayment(paymentId, confirmTime);
            if (result > 0) {
                // 更新状态为已确认
                updatePaymentStatus(paymentId, PAYMENT_STATUS_CONFIRMED);
                log.info("支付确认成功: paymentId={}", paymentId);
                return true;
            }
            
            return false;
            
        } catch (Exception e) {
            log.error("确认支付失败: paymentId={}, error={}", paymentId, e.getMessage(), e);
            handlePaymentException(paymentId, "确认支付失败: " + e.getMessage());
            return false;
        }
    }
    
    @Override
    @Transactional
    public String confirmPaymentAndTriggerContract(Long paymentId, String contractAddress) {
        log.info("确认支付并触发智能合约: paymentId={}, contractAddress={}", paymentId, contractAddress);
        
        try {
            // 先确认支付
            if (!confirmPayment(paymentId)) {
                throw new RuntimeException("支付确认失败");
            }
            
            // 获取支付记录
            PaymentRecord paymentRecord = paymentRecordMapper.selectPaymentRecordByPaymentId(paymentId);
            if (paymentRecord == null) {
                throw new RuntimeException("支付记录不存在");
            }
            
            // 触发智能合约
            String contractResult = executePaymentContract(paymentRecord, contractAddress);
            
            log.info("智能合约执行成功: paymentId={}, contractResult={}", paymentId, contractResult);
            return contractResult;
            
        } catch (Exception e) {
            log.error("确认支付并触发智能合约失败: paymentId={}, error={}", paymentId, e.getMessage(), e);
            handlePaymentException(paymentId, "智能合约执行失败: " + e.getMessage());
            throw new RuntimeException("智能合约执行失败: " + e.getMessage());
        }
    }
    
    /**
     * 执行支付相关智能合约
     */
    private String executePaymentContract(PaymentRecord paymentRecord, String contractAddress) {
        try {
            // 准备合约参数
            Object[] params = {
                paymentRecord.getContractId(),
                paymentRecord.getPaymentAmount().toString(),
                paymentRecord.getPaymentTime().getTime(),
                paymentRecord.getTransactionId()
            };
            
            // 执行智能合约
            String result = blockchainIntegrator.executeSmartContract(
                contractAddress, "processPayment", params);
            
            log.info("智能合约执行结果: paymentId={}, result={}", 
                    paymentRecord.getPaymentId(), result);
            
            return result;
            
        } catch (Exception e) {
            log.error("执行智能合约失败: {}", e.getMessage(), e);
            throw new RuntimeException("智能合约执行失败: " + e.getMessage());
        }
    }
    
    @Override
    public String getPaymentStatus(Long paymentId) {
        PaymentRecord paymentRecord = paymentRecordMapper.selectPaymentRecordByPaymentId(paymentId);
        return paymentRecord != null ? paymentRecord.getPaymentStatus() : null;
    }
    
    @Override
    public List<PaymentRecord> getPaymentsByContractId(Long contractId) {
        return paymentRecordMapper.selectPaymentRecordByContractId(contractId);
    }
    
    @Override
    public PaymentRecord getPaymentByTransactionId(String transactionId) {
        return paymentRecordMapper.selectPaymentRecordByTransactionId(transactionId);
    }
    
    @Override
    @Transactional
    public boolean updatePaymentStatus(Long paymentId, String status) {
        try {
            int result = paymentRecordMapper.updatePaymentStatus(paymentId, status);
            if (result > 0) {
                log.info("支付状态更新成功: paymentId={}, status={}", paymentId, status);
                return true;
            }
            return false;
        } catch (Exception e) {
            log.error("更新支付状态失败: paymentId={}, status={}, error={}", 
                     paymentId, status, e.getMessage(), e);
            return false;
        }
    }
    
    @Override
    @Transactional
    public boolean handlePaymentException(Long paymentId, String errorMessage) {
        log.error("处理支付异常: paymentId={}, error={}", paymentId, errorMessage);
        
        try {
            // 更新支付状态为失败
            updatePaymentStatus(paymentId, PAYMENT_STATUS_FAILED);
            
            // 记录错误信息到备注字段
            PaymentRecord paymentRecord = paymentRecordMapper.selectPaymentRecordByPaymentId(paymentId);
            if (paymentRecord != null) {
                paymentRecord.setRemarks("错误: " + errorMessage);
                paymentRecord.setUpdateTime(DateUtils.getNowDate());
                paymentRecordMapper.updatePaymentRecord(paymentRecord);
            }
            
            return true;
            
        } catch (Exception e) {
            log.error("处理支付异常失败: {}", e.getMessage(), e);
            return false;
        }
    }
    
    @Override
    public boolean validatePaymentData(Long contractId, BigDecimal paymentAmount, Long payerId) {
        // 验证必要参数
        if (contractId == null || contractId <= 0) {
            log.error("合同ID无效: {}", contractId);
            return false;
        }
        
        if (paymentAmount == null || paymentAmount.compareTo(BigDecimal.ZERO) <= 0) {
            log.error("支付金额无效: {}", paymentAmount);
            return false;
        }
        
        if (payerId == null || payerId <= 0) {
            log.error("支付方ID无效: {}", payerId);
            return false;
        }
        
        // TODO: 可以添加更多业务验证逻辑
        // 例如：验证合同是否存在、验证支付方权限等
        
        return true;
    }
    
    @Override
    public String generatePaymentNumber() {
        // 生成格式: PAY + 年月日 + 6位随机数
        String dateStr = DateUtils.dateTimeNow("yyyyMMdd");
        String randomStr = IdUtils.randomUUID().substring(0, 6).toUpperCase();
        return "PAY" + dateStr + randomStr;
    }
    
    @Override
    public Map<String, Object> getPaymentStatistics(Long contractId) {
        Map<String, Object> statistics = new HashMap<>();
        
        try {
            if (contractId != null) {
                // 合同相关统计
                List<PaymentRecord> payments = paymentRecordMapper.selectPaymentRecordByContractId(contractId);
                BigDecimal totalAmount = paymentRecordMapper.selectPaymentAmountByContractId(contractId);
                
                statistics.put("paymentCount", payments.size());
                statistics.put("totalAmount", totalAmount != null ? totalAmount : BigDecimal.ZERO);
                statistics.put("payments", payments);
            } else {
                // 全局统计
                BigDecimal totalAmount = paymentRecordMapper.selectTotalPaymentAmount();
                List<Map<String, Object>> countByStatus = paymentRecordMapper.selectPaymentCountByStatus();
                List<Map<String, Object>> countByMethod = paymentRecordMapper.selectPaymentCountByMethod();
                
                statistics.put("totalAmount", totalAmount != null ? totalAmount : BigDecimal.ZERO);
                statistics.put("countByStatus", countByStatus);
                statistics.put("countByMethod", countByMethod);
            }
            
        } catch (Exception e) {
            log.error("获取支付统计失败: {}", e.getMessage(), e);
            statistics.put("error", e.getMessage());
        }
        
        return statistics;
    }
    
    @Override
    public boolean isPaymentCompleted(Long contractId) {
        try {
            List<PaymentRecord> payments = paymentRecordMapper.selectPaymentRecordByContractId(contractId);
            
            // 检查是否有已确认的支付记录
            for (PaymentRecord payment : payments) {
                if (PAYMENT_STATUS_CONFIRMED.equals(payment.getPaymentStatus())) {
                    return true;
                }
            }
            
            return false;
            
        } catch (Exception e) {
            log.error("检查支付完成状态失败: contractId={}, error={}", contractId, e.getMessage(), e);
            return false;
        }
    }
    
    @Override
    public BigDecimal calculateContractReceivableAmount(Long contractId) {
        // TODO: 这里应该从合同服务获取合同金额
        // 暂时返回0，实际实现需要调用合同服务
        log.warn("calculateContractReceivableAmount 需要集成合同服务: contractId={}", contractId);
        return BigDecimal.ZERO;
    }
    
    @Override
    public BigDecimal calculateContractReceivedAmount(Long contractId) {
        try {
            BigDecimal receivedAmount = paymentRecordMapper.selectPaymentAmountByContractId(contractId);
            return receivedAmount != null ? receivedAmount : BigDecimal.ZERO;
        } catch (Exception e) {
            log.error("计算已收金额失败: contractId={}, error={}", contractId, e.getMessage(), e);
            return BigDecimal.ZERO;
        }
    }
}