package com.izouma.nineth.service;

import com.izouma.nineth.domain.WithdrawApply;
import com.izouma.nineth.dto.PageQuery;
import com.izouma.nineth.dto.PageWrapDTO;
import com.izouma.nineth.dto.pay.WithdrawResult;
import com.izouma.nineth.enums.FundChangeType;
import com.izouma.nineth.enums.WithdrawStatus;
import com.izouma.nineth.exception.BusinessException;
import com.izouma.nineth.repo.UserBankCardRepo;
import com.izouma.nineth.repo.UserFundAccountRepo;
import com.izouma.nineth.repo.WithdrawApplyRepo;
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 WithdrawApplyService {

    private SandAccountService sandAccountService;

    private UserFundAccountRepo userFundAccountRepo;

    private UserFundAccountService userFundAccountService;

    private WithdrawApplyRepo withdrawApplyRepo;

    private PayHelper payHelper;

    private SnowflakeIdWorker snowflakeIdWorker;

    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<WithdrawApply> root = criteriaQuery.from(WithdrawApply.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<WithdrawApply> all(PageQuery pageQuery) {
        Specification<WithdrawApply> specification = JpaUtils.toSpecification(pageQuery, WithdrawApply.class);
        Page<WithdrawApply> page = withdrawApplyRepo.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 WithdrawResult checkWithdrawResult(String orderNo){
        WithdrawApply withdrawApply = withdrawApplyRepo.findByOrderNo(orderNo).orElseThrow(new BusinessException("提现记录不存在"));

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


        withdrawResult.setGoodsTitle(withdrawApply.getTitle());
        withdrawResult.setPayPlatform(withdrawApply.getPayPlatform());

        //更新支付结果
        if(withdrawResult.getStatus() == WithdrawStatus.SUCCESS
                && (withdrawApply.getStatus() == WithdrawStatus.CREATED|| withdrawApply.getStatus() == WithdrawStatus.PENDING)){
            //修正未完成的状态，检查订单
            withdrawApply.setFinishTime(withdrawResult.getPayTime());
            withdrawApply.setTransactionId(withdrawResult.getTransactionNo());
            withdrawApply.setStatus(WithdrawStatus.SUCCESS);
            withdrawApply.setResult("同步状态成功");
            withdrawApplyRepo.saveAndFlush(withdrawApply);
            //更新提现流水
            userFundChangeLogService.updateSuccess(withdrawApply.getUserId(), FundChangeType.WITHDRAW, withdrawApply.getOrderNo());
        }

        return withdrawResult;
    }


    public BigDecimal lastDayWithdrawNum() {
        return withdrawApplyRepo.lastDayWithdrawNum();
    }
}
