package com.erp.example.seata;

import com.erp.example.seata.entity.Account;
import com.erp.example.seata.entity.TransactionLog;
import com.erp.example.seata.mapper.AccountMapper;
import com.erp.example.seata.mapper.TransactionLogMapper;
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 java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.UUID;

/**
 * 财务服务 - AT模式实现
 */
@Service
public class FinanceService {

    private static final Logger log = LoggerFactory.getLogger(FinanceService.class);

    @Autowired
    private AccountMapper accountMapper;

    @Autowired
    private TransactionLogMapper transactionLogMapper;

    /**
     * 冻结资金
     * AT模式自动记录前后镜像，异常时自动回滚
     */
    @Transactional
    public void freezeAmount(Long customerId, Long amount, String orderNo) {
        log.info("冻结资金: 客户ID={}, 金额={}, 订单={}", customerId, amount, orderNo);
        
        Account account = accountMapper.findByCustomerId(customerId);
        if (account == null) {
            throw new RuntimeException("账户不存在: " + customerId);
        }
        
        BigDecimal availableAmount = account.getBalance().subtract(account.getFrozenAmount());
        BigDecimal freezeAmount = BigDecimal.valueOf(amount);
        
        if (availableAmount.compareTo(freezeAmount) < 0) {
            throw new RuntimeException("余额不足: 可用=" + availableAmount + ", 需要=" + freezeAmount);
        }
        
        // 冻结资金 = 增加冻结金额
        account.setFrozenAmount(account.getFrozenAmount().add(freezeAmount));
        accountMapper.update(account);
        
        // 记录交易流水
        TransactionLog txLog = new TransactionLog();
        txLog.setTxNo("TX" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 8));
        txLog.setOrderNo(orderNo);
        txLog.setCustomerId(customerId);
        txLog.setAmount(freezeAmount);
        txLog.setType("FREEZE");
        txLog.setStatus("SUCCESS");
        txLog.setCreateTime(LocalDateTime.now());
        transactionLogMapper.insert(txLog);
        
        log.info("资金冻结成功: {}", account);
    }

    /**
     * 解冻资金（取消冻结）
     * 用于订单取消时回滚
     */
    @Transactional
    public void unfreezeAmount(Long customerId, Long amount, String orderNo) {
        log.info("解冻资金: 客户ID={}, 金额={}, 订单={}", customerId, amount, orderNo);
        
        Account account = accountMapper.findByCustomerId(customerId);
        if (account == null) {
            log.warn("账户不存在: {}", customerId);
            return;
        }
        
        BigDecimal unfreezeAmount = BigDecimal.valueOf(amount);
        BigDecimal actualUnfreeze = unfreezeAmount.min(account.getFrozenAmount());
        
        // 解冻资金 = 减少冻结金额
        account.setFrozenAmount(account.getFrozenAmount().subtract(actualUnfreeze));
        accountMapper.update(account);
        
        // 记录交易流水
        TransactionLog txLog = new TransactionLog();
        txLog.setTxNo("TX" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 8));
        txLog.setOrderNo(orderNo);
        txLog.setCustomerId(customerId);
        txLog.setAmount(actualUnfreeze);
        txLog.setType("UNFREEZE");
        txLog.setStatus("SUCCESS");
        txLog.setCreateTime(LocalDateTime.now());
        transactionLogMapper.insert(txLog);
        
        log.info("资金解冻成功: {}", account);
    }

    /**
     * 消费资金（正式扣减）
     * 订单支付成功后调用
     */
    @Transactional
    public void consumeAmount(Long customerId, Long amount, String orderNo) {
        log.info("消费资金: 客户ID={}, 金额={}, 订单={}", customerId, amount, orderNo);
        
        Account account = accountMapper.findByCustomerId(customerId);
        if (account == null) {
            throw new RuntimeException("账户不存在: " + customerId);
        }
        
        BigDecimal consumeAmount = BigDecimal.valueOf(amount);
        
        // 消费资金 = 减少余额和冻结金额
        account.setBalance(account.getBalance().subtract(consumeAmount));
        account.setFrozenAmount(account.getFrozenAmount().subtract(consumeAmount));
        accountMapper.update(account);
        
        // 记录交易流水
        TransactionLog txLog = new TransactionLog();
        txLog.setTxNo("TX" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 8));
        txLog.setOrderNo(orderNo);
        txLog.setCustomerId(customerId);
        txLog.setAmount(consumeAmount);
        txLog.setType("CONSUME");
        txLog.setStatus("SUCCESS");
        txLog.setCreateTime(LocalDateTime.now());
        transactionLogMapper.insert(txLog);
        
        log.info("资金消费成功: {}", account);
    }

    /**
     * 退款
     * 订单取消或退款时调用
     */
    @Transactional
    public void refundAmount(Long customerId, Long amount, String orderNo) {
        log.info("退款: 客户ID={}, 金额={}, 订单={}", customerId, amount, orderNo);
        
        Account account = accountMapper.findByCustomerId(customerId);
        if (account == null) {
            throw new RuntimeException("账户不存在: " + customerId);
        }
        
        BigDecimal refundAmount = BigDecimal.valueOf(amount);
        
        // 退款 = 增加余额
        account.setBalance(account.getBalance().add(refundAmount));
        accountMapper.update(account);
        
        // 记录交易流水
        TransactionLog txLog = new TransactionLog();
        txLog.setTxNo("TX" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 8));
        txLog.setOrderNo(orderNo);
        txLog.setCustomerId(customerId);
        txLog.setAmount(refundAmount);
        txLog.setType("REFUND");
        txLog.setStatus("SUCCESS");
        txLog.setCreateTime(LocalDateTime.now());
        transactionLogMapper.insert(txLog);
        
        log.info("退款成功: {}", account);
    }

    /**
     * 查询账户
     */
    public Account findByCustomerId(Long customerId) {
        return accountMapper.findByCustomerId(customerId);
    }
}
