package com.ruoyi.bst.creditPay.service.impl;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import com.github.pagehelper.PageHelper;
import com.ruoyi.bst.credit.service.CreditService;
import com.ruoyi.bst.creditPay.domain.CreditPay;
import com.ruoyi.bst.creditPay.domain.CreditPayQuery;
import com.ruoyi.bst.creditPay.domain.CreditPayVO;
import com.ruoyi.bst.creditPay.domain.enums.CreditPayStatus;
import com.ruoyi.bst.creditPay.mapper.CreditPayMapper;
import com.ruoyi.bst.creditPay.service.CreditPayService;
import com.ruoyi.bst.creditUser.domain.CreditUserVO;
import com.ruoyi.bst.creditUser.service.CreditUserService;
import com.ruoyi.bst.pay.domain.PayVO;
import com.ruoyi.bst.pay.service.PayService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.pay.PayApi;
import com.ruoyi.common.pay.Payable;
import com.ruoyi.common.pay.Refundable;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.SnowFlakeUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.collection.CollectionUtils;

/**
 * 挂账支付Service业务层处理
 *
 * @author ruoyi
 * @date 2025-05-28
 */
@Service
public class CreditPayServiceImpl implements CreditPayService, PayApi
{
    @Autowired
    private CreditPayMapper creditPayMapper;

    @Autowired
    private CreditUserService creditUserService;

    @Autowired
    private CreditService creditService;

    @Autowired
    private PayService payService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    /**
     * 查询挂账支付
     *
     * @param id 挂账支付主键
     * @return 挂账支付
     */
    @Override
    public CreditPayVO selectCreditPayById(Long id)
    {
        return creditPayMapper.selectCreditPayById(id);
    }

    /**
     * 查询挂账支付列表
     *
     * @param creditPay 挂账支付
     * @return 挂账支付
     */
    @Override
    public List<CreditPayVO> selectCreditPayList(CreditPayQuery creditPay)
    {
        return creditPayMapper.selectCreditPayList(creditPay);
    }

    /**
     * 新增挂账支付
     *
     * @param creditPay 挂账支付
     * @return 结果
     */
    @Override
    public int insertCreditPay(CreditPay creditPay)
    {
        creditPay.setCreateTime(DateUtils.getNowDate());
        creditPay.setNo(String.valueOf(SnowFlakeUtil.newId()));
        return creditPayMapper.insertCreditPay(creditPay);
    }

    /**
     * 修改挂账支付
     *
     * @param creditPay 挂账支付
     * @return 结果
     */
    @Override
    public int updateCreditPay(CreditPay creditPay)
    {
        return creditPayMapper.updateCreditPay(creditPay);
    }

    /**
     * 批量删除挂账支付
     *
     * @param ids 需要删除的挂账支付主键
     * @return 结果
     */
    @Override
    public int deleteCreditPayByIds(Long[] ids)
    {
        return creditPayMapper.deleteCreditPayByIds(ids);
    }

    /**
     * 删除挂账支付信息
     *
     * @param id 挂账支付主键
     * @return 结果
     */
    @Override
    public int deleteCreditPayById(Long id)
    {
        return creditPayMapper.deleteCreditPayById(id);
    }


    // 查询挂账支付单
    private CreditPayVO selectCreditPayByOutTradeNo(String outTradeNo) {
        if (StringUtils.isBlank(outTradeNo)) {
            return null;
        }
        CreditPayQuery query = new CreditPayQuery();
        query.setEqOutTradeNo(outTradeNo);
        return this.selectOne(query);
    }

    private CreditPayVO selectOne(CreditPayQuery query) {
        PageHelper.startPage(1, 1);
        List<CreditPayVO> list = this.selectCreditPayList(query);
        return CollectionUtils.firstElement(list);
    }
    
    // 发起支付
    @Override
    public Object pay(Payable payable, Object config) {
        ServiceUtil.assertion(payable == null, "参数错误");
        ServiceUtil.assertion(StringUtils.isBlank(payable.payableAccount()), "参数错误：挂账用户ID不允许为空");

        // 查询用户挂账信息
        Long creditUserId = Long.parseLong(payable.payableAccount());
        CreditUserVO creditUser = creditUserService.selectCreditUserById(creditUserId);
        ServiceUtil.assertion(creditUser == null, "ID为%s的挂账用户不存在", creditUserId);

        // 查询支付单
        PayVO pay = payService.selectByNo(payable.payableOutTradeNo());
        ServiceUtil.assertion(pay == null, "编号为%s的支付单不存在", payable.payableOutTradeNo());

        // 创建挂账支付单
        CreditPay po = new CreditPay();
        po.setOutTradeNo(payable.payableOutTradeNo());
        po.setAmount(payable.payableYuan());
        po.setDescription(payable.payableDescription());
        po.setStatus(CreditPayStatus.WAIT_PAYMENT.getCode());
        // 挂账方及用户信息
        po.setCreditId(creditUser.getCreditId());
        po.setCreditUserId(creditUser.getId());
        po.setUserId(creditUser.getUserId());
        po.setAreaId(creditUser.getAreaId());
        po.setAreaName(creditUser.getAreaName());
        po.setCreditName(creditUser.getCreditName());
        po.setCreditUserName(creditUser.getUserName());
        // 业务信息
        po.setBstId(pay.getBstId());
        po.setBstType(pay.getBstType());

        transactionTemplate.execute(status -> {
            // 插入挂账支付单
            int rows = this.insertCreditPay(po);
            ServiceUtil.assertion(rows != 1, "创建挂账支付单失败");

            // 增加挂账方已用金额
            int addCredit = creditService.addUsedAmount(po.getCreditId(), po.getAmount());
            ServiceUtil.assertion(addCredit != 1, "挂账方记账失败，请检查可用金额是否充足。所需金额：%s，挂账方ID：%s", po.getAmount(), po.getCreditId());

            // 增加挂账用户本月已用金额
            int addCreditUser = creditUserService.addUsedAmount(po.getCreditUserId(), po.getAmount());
            ServiceUtil.assertion(addCreditUser != 1, "挂账用户记账失败，请检查可用金额是否充足。所需金额：%s，挂账方ID：%s", po.getAmount(), po.getCreditUserId());

            return rows;
        });

        return this.selectCreditPayById(po.getId());
    }

    // 关闭支付单
    @Override
    public void closeByOutTradeNo(String outTradeNo, Object config) {
        // 支付单无法关闭
        throw new ServiceException("挂账支付无法关闭：" + outTradeNo);
    }

    // 查询支付单
    @Override
    public Object queryByOutTradeNo(String outTradeNo, LocalDate orderDate, Object config) {
        return this.selectCreditPayByOutTradeNo(outTradeNo);
    }

    // 退款
    @Override
    public Object refund(Refundable refundAble, Object config) {
        // TODO 创建退款单

        // TODO 增加退款金额

        // TODO 减少挂账方已用金额（注意0值，可为负数）

        // TODO 减少挂账用户已用金额（注意0值，不可为负数）
        return null;
    }

    // 是否支付成功
    @Override
    public boolean isPaySuccessByOutTradeNo(String outTradeNo, LocalDate orderDate, Object config) {
        CreditPayVO pay = this.selectCreditPayByOutTradeNo(outTradeNo);
        return isPaySuccess(pay);
    }

    // 是否支付成功
    @Override
    public boolean isPaySuccess(Object result) {
        if (result == null) {
            return false;
        }
        CreditPayVO pay = (CreditPayVO) result;
        return pay != null && CreditPayStatus.WAIT_PAYMENT.getCode().equals(pay.getStatus());
    }

    // 获取支付成功的时间
    @Override
    public LocalDateTime getPayTime(Object result) {
        if (result == null) {
            return null;
        }
        CreditPayVO pay = (CreditPayVO) result;
        return pay.getPayTime();
    }
}