package com.qxgmat.service.inline;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.nuliji.tools.AbstractService;
import com.nuliji.tools.Tools;
import com.nuliji.tools.exception.ParameterException;
import com.nuliji.tools.exception.SystemException;
import com.nuliji.tools.mybatis.Example;
import com.nuliji.tools.pay.common.PayInfo;
import com.nuliji.tools.pay.common.ResultInfo;
import com.nuliji.tools.pay.enums.TradeStatus;
import com.qxgmat.data.dao.PayMapper;
import com.qxgmat.data.dao.entity.Pay;
import com.qxgmat.service.annotation.PayModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
public class PayService extends AbstractService {
    private static final Logger logger = LoggerFactory.getLogger(PayService.class);

    @Resource
    private PayMapper payMapper;

    /**
     * 发起充值
     * @param pay
     * @param info
     * @return
     */
    public int start(Pay pay, PayInfo info){
        pay.setPayInfo(JSON.toJSONString(info));
        pay.setTradeStatus(TradeStatus.WAIT_BUYER_PAY);
        return payMapper.updateByPrimaryKey(pay);
    }

    /**
     * 系统支付错误
     * @param pay
     * @param info
     * @return
     */
    public int system(Pay pay, PayInfo info){
        pay.setPayInfo(JSON.toJSONString(info));
        pay.setTradeStatus(TradeStatus.SYSTEM);
        return payMapper.updateByPrimaryKey(pay);
    }

    /**
     * 系统结果错误
     * @param pay
     * @param info
     * @return
     */
    public int system(Pay pay, ResultInfo info){
        pay.setResultInfo(JSON.toJSONString(info));
        pay.setTradeStatus(TradeStatus.SYSTEM);
        return payMapper.updateByPrimaryKey(pay);
    }

    /**
     * 支付流程异常
     * @param pay
     * @param info
     * @return
     */
    public int exception(Pay pay, ResultInfo info){
        pay.setPayInfo(JSON.toJSONString(info));
        pay.setTradeStatus(TradeStatus.EXCEPTION);
        return payMapper.updateByPrimaryKey(pay);
    }

    /**
     * 支付关闭
     * @param pay
     * @param info
     * @return
     */
    public int close(Pay pay, ResultInfo info){
        pay.setPayInfo(JSON.toJSONString(info));
        pay.setTransactionNo(info.getTransaction_no());
        pay.setTradeStatus(TradeStatus.CLOSE);
        return payMapper.updateByPrimaryKey(pay);
    }

    /**
     * 支付错误，需要重新支付
     * @param pay
     * @param info
     * @return
     */
    public int error(Pay pay, ResultInfo info){
        pay.setPayInfo(JSON.toJSONString(info));
        pay.setTransactionNo(info.getTransaction_no());
        pay.setTradeStatus(TradeStatus.ERROR);
        return payMapper.updateByPrimaryKey(pay);
    }

    /**
     * 支付取消
     * @param pay
     * @param info
     * @return
     */
    public int cancel(Pay pay, ResultInfo info){
        pay.setPayInfo(JSON.toJSONString(info));
        pay.setTransactionNo(info.getTransaction_no());
        pay.setTradeStatus(TradeStatus.CANCEL);
        return payMapper.updateByPrimaryKey(pay);
    }

    /**
     * 支付完成
     * @param pay
     * @param info
     * @param finish
     * @return
     */
    public int payed(Pay pay, ResultInfo info, boolean finish){
//        int timestamp = Math.toIntExact(System.currentTimeMillis() / 1000);
        pay.setTransactionNo(info.getTransaction_no());
        pay.setResultInfo(JSON.toJSONString(info));
        pay.setPayTime(new Date());
        pay.setTradeStatus(finish ? TradeStatus.FINISH : TradeStatus.SUCCESS);
        return payMapper.updateByPrimaryKey(pay);
    }

    /**
     * 已支付
     * @param pay
     * @return boolean
     */
    public boolean isPayed(Pay pay){
        return TradeStatus.isPayed(pay.getTradeStatus());
    }

    /**
     * 支付中
     * @param pay
     * @return boolean
     */
    public boolean isPaying(Pay pay){
        return TradeStatus.isPaying(pay.getTradeStatus());
    }

    /**
     * 无效支付
     * @param pay
     * @return boolean
     */
    public boolean isInvalid(Pay pay){
        return TradeStatus.isInvalid(pay.getTradeStatus());
    }

    /**
     * 支付错误
     * @param pay
     * @return boolean
     */
    public boolean isError(Pay pay){
        return TradeStatus.isError(pay.getTradeStatus());
    }

    /**
     * 获取支付信息
     * @param pay
     * @return boolean
     */
    public PayInfo getInfo(Pay pay){
        return JSON.parseObject(pay.getPayInfo(), PayInfo.class);
    }

    /**
     * 创建支付记录
     * @param userId
     * @param payType
     * @param channel
     * @param money
     * @param module
     * @param moduleExtend
     * @param pid
     * @param subject
     * @param body
     * @param clientIp
     * @return Pay
     */
    public Pay make(Integer userId, String payType, String channel, BigDecimal money, String module, String moduleExtend, String pid, String subject, String body, String clientIp){
        Pay pay = Pay.builder()
                .subject(subject)
                .body(body)
                .userId(userId)
                .module(module)
                .moduleExtend(moduleExtend)
                .payType(payType)
                .money(money)
                .clientIp(clientIp)
                .currency("cny")
                .channel(channel)
                .no(UUID.randomUUID().toString().substring(0, 32))
                .pid(pid)
                .transactionNo("") // 发起支付后得到
                .tradeStatus(com.qxgmat.data.constants.enums.trade.TradeStatus.WAIT.index)
                .resultInfo("") // 支付返回后得到
                .payInfo("") // 发起支付的请求参数
                .build();
        int result = insert(payMapper, pay);
        return pay;
    }

    public Pay getByNo(String no){
        Example example = new Example(Pay.class);
        example.and(
                example.createCriteria()
                .andEqualTo("no", no)
        );
        return one(payMapper, example);
    }

    public Pay add(Pay pay){
        int result = insert(payMapper, pay);
        pay = one(payMapper, pay.getId());
        if(pay == null){
            throw new SystemException("添加失败");
        }
        return pay;
    }

    public Pay edit(Pay pay){
        Pay in = one(payMapper, pay.getId());
        if(in == null){
            throw new ParameterException("支付不存在");
        }
        int result = update(payMapper, pay);
        return pay;
    }

    public boolean delete(Number id){
        Pay in = payMapper.selectByPrimaryKey(id);
        if(in == null){
            throw new ParameterException("支付不存在");
        }
        int result = payMapper.deleteByPrimaryKey(id);
        return result > 0;
    }

    public Pay get(Number id){
        Pay in = payMapper.selectByPrimaryKey(id);

        if(in == null){
            throw new ParameterException("支付不存在");
        }
        return in;
    }

    public Page<Pay> select(int page, int pageSize){
        return select(payMapper, page, pageSize);
    }

    public List<Pay> select(Collection ids){
        return select(payMapper, ids);
    }

}
