package com.izouma.nineth.service;

import com.izouma.nineth.domain.UserFundAccount;
import com.izouma.nineth.domain.WalletRenewOrder;
import com.izouma.nineth.dto.PageQuery;
import com.izouma.nineth.dto.PageWrapDTO;
import com.izouma.nineth.dto.pay.PayResult;
import com.izouma.nineth.enums.FundChangeType;
import com.izouma.nineth.enums.PayStatus;
import com.izouma.nineth.exception.BusinessException;
import com.izouma.nineth.repo.UserFundAccountRepo;
import com.izouma.nineth.repo.WalletRenewOrderRepo;
import com.izouma.nineth.service.pay.UniformPayConstants;
import com.izouma.nineth.utils.JpaUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;
import java.math.BigDecimal;

/**
 * 账户管理服务
 */
@Slf4j
@AllArgsConstructor
@Service
public class WalletRenewOrderService {

    private WalletRenewOrderRepo walletRenewOrderRepo;

    private LianlianPayService lianlianPayService;

    private EntityManager entityManager;

    private UserFundChangeLogService userFundChangeLogService;

    private UserFundAccountRepo userFundAccountRepo;



    public BigDecimal sumOrderAmount(Specification specification){
        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
        CriteriaQuery<BigDecimal> criteriaQuery = builder.createQuery(BigDecimal.class);
        Root<WalletRenewOrder> root = criteriaQuery.from(WalletRenewOrder.class);
        criteriaQuery.select(builder.sum(root.get("payAmt")));
        criteriaQuery.where(specification.toPredicate(root, criteriaQuery, builder));
        TypedQuery<BigDecimal> query = entityManager.createQuery(criteriaQuery);
        return query.getSingleResult();
    }


    public PageWrapDTO<WalletRenewOrder> all(PageQuery pageQuery) {
        Specification<WalletRenewOrder> specification = JpaUtils.toSpecification(pageQuery, WalletRenewOrder.class);
        Page<WalletRenewOrder> page = walletRenewOrderRepo.findAll(specification, JpaUtils.toPageRequest(pageQuery));
        PageWrapDTO pageWrapDTO = new PageWrapDTO(page.toList(), page.getPageable(), page.getTotalElements());
        BigDecimal totalAmount = sumOrderAmount(specification);
        pageWrapDTO.setTotalAmount(totalAmount);
        return pageWrapDTO;

    }


    /**
     * 查询支付结果
     * @param orderNo
     * @return
     */
    @Transactional
    public PayResult checkPayResult(String orderNo){
        WalletRenewOrder walletRenewOrder = walletRenewOrderRepo.findByOrderNo(orderNo).orElseThrow(new BusinessException("续费记录不存在"));

        PayResult payResult = null;
        if(UniformPayConstants.LIANLIANPAY_PLATFORM.equals(walletRenewOrder.getPayPlatform())){
            payResult = lianlianPayService.checkPayResult(orderNo);
        }else{
            throw new BusinessException("暂不支持该支付平台查询：" + walletRenewOrder.getPayPlatform());
        }

        payResult.setGoodsTitle(walletRenewOrder.getGoodsTitle());
        payResult.setPayPlatform(walletRenewOrder.getPayPlatform());

        //更新支付结果
        if(walletRenewOrder.getStatus() == PayStatus.UNPAID || walletRenewOrder.getStatus() == PayStatus.PENDING){
            if(payResult.getStatus() == PayStatus.HAVE_PAID){
                //修正未完成的状态，检查订单
                walletRenewOrder.setPayTime(payResult.getPayTime());
                walletRenewOrder.setTransactionId(payResult.getTransactionNo());
                walletRenewOrder.setStatus(PayStatus.HAVE_PAID);
                walletRenewOrder.setResult("同步状态成功");
                walletRenewOrderRepo.saveAndFlush(walletRenewOrder);
                //更新资金流水
                userFundChangeLogService.updateSuccess(walletRenewOrder.getUserId(), FundChangeType.RENEW,
                        walletRenewOrder.getOrderNo());

                //更新续费时长
                UserFundAccount userFundAccount = userFundAccountRepo.findById(walletRenewOrder.getUserFundAccountId()).orElse(null);
                if(userFundAccount != null){
                    userFundAccount.setExpireTime(walletRenewOrder.getEndTime());
                    userFundAccountRepo.save(userFundAccount);
                }
            }else if(payResult.getStatus() == PayStatus.FAILED_PAID){
                //支付失败记录
                walletRenewOrder.setStatus(PayStatus.FAILED_PAID);
                walletRenewOrder.setResult("同步支付状态");
                walletRenewOrder.setTransactionId(payResult.getTransactionNo());
                walletRenewOrder.setPayTime(payResult.getPayTime());
                walletRenewOrderRepo.save(walletRenewOrder);
                //更新流水记录
                userFundChangeLogService.updateFailed(walletRenewOrder.getUserId(), FundChangeType.RENEW, walletRenewOrder.getOrderNo());
            }

        }

        return payResult;
    }




}
