package com.qxgmat.service.extend;

import com.nuliji.tools.AbstractService;
import com.nuliji.tools.Tools;
import com.nuliji.tools.exception.ParameterException;
import com.nuliji.tools.exception.SystemException;
import com.qxgmat.data.constants.enums.module.PayModule;
import com.qxgmat.data.constants.enums.trade.PayType;
import com.qxgmat.data.constants.enums.trade.TradeStatus;
import com.qxgmat.data.dao.PayMapper;
import com.qxgmat.data.dao.entity.Pay;
import com.qxgmat.service.inline.UserClassService;
import com.qxgmat.service.inline.UserServiceService;
import com.qxgmat.util.annotation.Callback;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * Created by gaojie on 2017/11/13.
 */
@Service
public class TradeService extends AbstractService {

    @Resource
    private PayMapper payMapper;

    @Resource
    private UserServiceService userServiceService;
    @Resource
    private UserClassService userClassService;

    private Map<PayModule, Callback> payCallback;

    public TradeService(){
        payCallback = new HashMap<>();
        payCallback.put(PayModule.SERVICE, (pay)->{
            return userServiceService.payed((Pay)pay);
        });
        payCallback.put(PayModule.CLASS, (pay)->{
            return userClassService.payed((Pay)pay);
        });
    }

    public Pay pay(Number userId, String subject, String body, String module, String moduleExtend, BigDecimal money, PayType payType, HttpServletRequest request){
        if(!payCallback.containsKey(module))
            throw new ParameterException("不支持的支付模块");

        Pay pay = Pay.builder()
                .subject(subject)
                .body(body)
                .module(module)
                .moduleExtend(moduleExtend)
                .payType(payType.index)
                .money(money)
                .clientIp(Tools.getClientIp(request))
                .currency("cny")
                .channel("")
                .no(UUID.randomUUID().toString().substring(0, 32))
                .pid("")
                .transactionNo("")
                .tradeStatus(TradeStatus.WAIT.index)
                .build();
        int result = insert(payMapper, pay);

        // 账户交易直接走完成流程
        if(payType == PayType.ACCOUNT)
            pay = prepay(userId, pay);
        return pay;
    }

    private Pay prepay(Number userId, Pay pay){
        // todo 直接支付完成
        return payed(pay.getId());
    }

    public Pay payed(Long payId){
        Pay pay = one(payMapper, payId);
        if(pay == null)
            throw new ParameterException("支付信息错误");

        if(pay.getTradeStatus() == TradeStatus.SUCCESS.index
                || pay.getTradeStatus() == TradeStatus.FINISH.index)
            return pay;

        if(pay.getTradeStatus() == TradeStatus.CANCEL.index
                || pay.getTradeStatus() == TradeStatus.CLOSE.index)
            throw new ParameterException("该支付无效");

        Callback callback = payCallback.get(pay.getModule());
        try {
            boolean r = callback.callback(pay);
            if (!r)
                throw new SystemException("支付回调失败");
        }catch (Exception e){
            throw new SystemException("支付回调失败", e);
        }

        int result = update(payMapper, Pay.builder()
                .id(payId)
                .tradeStatus(TradeStatus.SUCCESS.index)
                .build());
        return pay;
    }

}
