package com.izouma.nineth.service;

import com.izouma.nineth.domain.*;
import com.izouma.nineth.dto.PageQuery;
import com.izouma.nineth.dto.PageWrapDTO;
import com.izouma.nineth.dto.pay.PayResult;
import com.izouma.nineth.dto.pay.RechargeResult;
import com.izouma.nineth.enums.*;
import com.izouma.nineth.exception.BusinessException;
import com.izouma.nineth.repo.RechargeOrderRepo;
import com.izouma.nineth.repo.UserBankCardRepo;
import com.izouma.nineth.repo.UserFundAccountRepo;
import com.izouma.nineth.service.pay.PayHelper;
import com.izouma.nineth.service.pay.UniformPayConstants;
import com.izouma.nineth.utils.JpaUtils;
import com.izouma.nineth.utils.SnowflakeIdWorker;
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;

/**
 * 充值服务
 */
@Service
@AllArgsConstructor
@Slf4j
public class RechargeOrderService {

    private SandAccountService sandAccountService;

    private UserFundAccountRepo userFundAccountRepo;

    private UserFundAccountService userFundAccountService;

    private RechargeOrderRepo rechargeOrderRepo;

    private SnowflakeIdWorker snowflakeIdWorker;

    private PayHelper payHelper;

    private UserBankCardRepo userBankCardRepo;

    private UserFundChangeLogService userFundChangeLogService;

    private LianlianPayService lianlianPayService;

    private EntityManager entityManager;

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


    public PageWrapDTO<RechargeOrder> all(PageQuery pageQuery) {
        Specification<RechargeOrder> specification = JpaUtils.toSpecification(pageQuery, RechargeOrder.class);
        Page<RechargeOrder> page = rechargeOrderRepo.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 RechargeResult checkRechargeResult(String orderNo){
        RechargeOrder rechargeOrder = rechargeOrderRepo.findByOrderNo(orderNo).orElseThrow(new BusinessException("充值记录不存在"));

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

        rechargeResult.setGoodsTitle(rechargeOrder.getTitle());
        rechargeResult.setPayPlatform(rechargeOrder.getPayPlatform());

        //更新支付结果
        if(rechargeResult.getStatus() == RechargeStatus.SUCCESS
                && (rechargeOrder.getStatus() == RechargeStatus.CREATED|| rechargeOrder.getStatus() == RechargeStatus.PENDING)){
            //修正未完成的状态，检查订单
            rechargeOrder.setFinishTime(rechargeResult.getPayTime());
            rechargeOrder.setTransactionId(rechargeResult.getTransactionNo());
            rechargeOrder.setStatus(RechargeStatus.SUCCESS);
            rechargeOrder.setResult("同步状态成功");
            rechargeOrderRepo.saveAndFlush(rechargeOrder);
            //更新资金流水
            userFundChangeLogService.updateSuccess(rechargeOrder.getUserId(), FundChangeType.RECHARGE,
                    rechargeOrder.getOrderNo());
        }

        return rechargeResult;
    }


    public BigDecimal lastDayRechargeNum() {
        return rechargeOrderRepo.lastDayRechargeNum();
    }
}
