package com.iformall.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iformall.common.IdWorker;
import com.iformall.domain.po.*;
import com.iformall.domain.vo.WxCouponSendVo;
import com.iformall.enums.*;
import com.iformall.exception.MallinkException;
import com.iformall.mapper.WxCouponOrderMapper;
import com.iformall.mapper.WxCouponSendConfigMapper;
import com.iformall.mapper.WxCouponSendMapper;
import com.iformall.mapper.WxMerchantBUserMapper;
import com.iformall.service.*;
import com.iformall.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

@Service
public class WxCouponSendServiceImpl implements WxCouponSendService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    WxCouponSendMapper wxCouponSendMapper;
    @Autowired
    WxCouponOrderService wxCouponOrderService;
    @Autowired
    WxCouponService wxCouponService;
    @Autowired
    WxCouponActionLogService wxCouponActionLogService;
    @Autowired
    WxCouponSendConfigMapper wxCouponSendConfigMapper;
    @Autowired
    WxOrderService wxOrderService;
    @Autowired
    WxCouponOrderMapper wxCouponOrderMapper;
    @Autowired
    WxMerchantBUserMapper wxMerchantBUserMapper;
    @Autowired
    PushLimitService pushLimitService;


    @Override
    public PageInfo<WxCouponSendVo> listAsPage(WxCouponSend record, Integer pageIndex, Integer pageSize) {
        return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxCouponSendMapper.findListVo(record));
    }

    @Override
    public WxCouponSend getById(Long id) {
        return wxCouponSendMapper.selectByPrimaryKey(id);
    }

    @Override
    public void saveOrUpdate(WxCouponSend record) {
        if (record.getId() == null) {
            //record.setId(UUID.randomUUID().toString().replaceAll("-", ""));
            final IdWorker idWorker = IdWorker.get();
            record.setId(idWorker.nextId());
            wxCouponSendMapper.insertSelective(record);
        } else {
            wxCouponSendMapper.updateByPrimaryKeySelective(record);
        }
    }

    @Override
    public void deleteById(Long id) {
        wxCouponSendMapper.deleteByPrimaryKey(id);
    }

    private boolean isConditionAllowed(WxCouponSend wxCouponSend, Object param) {

        if (wxCouponSend.getSendType().equals(EnumCouponSendSendType.C_ORDER.getCode())){
            WxOrder wxOrder = (WxOrder)param;

            try {
                JSONObject jo = JSONObject.parseObject(wxCouponSend.getConditions());
                if (wxOrder.getProductId().equals(jo.getLong("id")))
                    return true;
            } catch (Exception e) {
                logger.error("交易发券条件判断错误:ID=" + wxCouponSend.getId() + e.getMessage());
            }
            return false;

        } else if (wxCouponSend.getSendType().equals(EnumCouponSendSendType.CAR_STOP.getCode())){

            try {
                JSONObject jo = JSONObject.parseObject(wxCouponSend.getConditions());

                if (DateUtils.isInDate(new Date(), jo.getString("startTime"), jo.getString("endTime"))){
                    return true;
                }

            } catch (Exception e) {
                logger.error("停车发券条件判断错误:ID=" + wxCouponSend.getId() + e.getMessage());
            }

            return false;
        }else if (wxCouponSend.getSendType().equals(EnumCouponSendSendType.B_MICROPAY.getCode())){

            WxOrder wxOrder = (WxOrder)param;

            try {
                JSONObject jo = JSONObject.parseObject(wxCouponSend.getConditions());
                WxMerchantBUser wxMerchantBUser = wxMerchantBUserMapper.selectByPrimaryKey(wxOrder.getProductId());

                if (wxMerchantBUser.getMerchantId()!= null
                        && wxMerchantBUser.getMerchantId().equals(jo.getLong("id"))) {
                    return true;
                }
            } catch (Exception e) {
                logger.error("收银发券条件判断错误:ID=" + wxCouponSend.getId() + e.getMessage());
            }
            return false;

        }else if (wxCouponSend.getSendType().equals(EnumCouponSendSendType.COUPON_VERIFY.getCode())){
            WxOrder wxOrder = (WxOrder)param;

            try {
                JSONObject jo = JSONObject.parseObject(wxCouponSend.getConditions());
                if (wxOrder.getProductId().equals(jo.getLong("id"))) {
                    return true;
                }
            } catch (Exception e) {
                logger.error("核销发券条件判断错误:ID=" + wxCouponSend.getId() + e.getMessage());
            }
            return false;

        }else {
            return false;
        }

    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class})
    public boolean sendCouponToUser(EnumCouponSendSendType type, Object param) {

        String tenantId;
        Long cUserId;
        switch (type) {
            case CAR_STOP:
                if (!param.getClass().equals(WxCUserCar.class))
                    return false;
                WxCUserCar wxCUserCar= (WxCUserCar)param;
                cUserId = wxCUserCar.getCUserId();
                tenantId = wxCUserCar.getTenantId();
                break;
            case COUPON_VERIFY:
            case B_MICROPAY:
            case C_ORDER:
                if (!param.getClass().equals(WxOrder.class))
                    return false;
                WxOrder order = (WxOrder)param;
                cUserId = order.getcUserId();
                tenantId = order.getTenantId();
                break;
            default:
                return false;
        }

        //查询开关是否打开
        WxCouponSendConfig wxCouponSendConfig = new WxCouponSendConfig();
        wxCouponSendConfig.setSendType(type.getCode());
        wxCouponSendConfig.setTenantId(tenantId);
        List<WxCouponSendConfig> configList = wxCouponSendConfigMapper.findList(wxCouponSendConfig);
        if (configList.size() > 0) {
            WxCouponSendConfig config = configList.get(0);
            if (config.getValue() == EnumEnableType.Disable.getCode()) {
                logger.info(config.getSendType() + ": disabled ");
                return false;
            }
        }

        boolean checkTime = false;
        try {
            checkTime = pushLimitService.checkSendTime(tenantId);
            if (!checkTime)
                return false;
        } catch (MallinkException e) {
            logger.error("push limit check time :" + e.getMessage());
            return false;
        }

        boolean bRet = false;

        WxCouponSend wxCouponSendQuery = new WxCouponSend();
        wxCouponSendQuery.setTenantId(tenantId);
        wxCouponSendQuery.setSendType(type.getCode());
        wxCouponSendQuery.setStatus(EnumCouponSendStatus.VALID.getCode());

        List<WxCouponSendVo> wxCouponSends = wxCouponSendMapper.findListVo(wxCouponSendQuery);
        for (WxCouponSend send : wxCouponSends) {
            boolean checkLimit = false;
            // 检查疲劳度
            try {
                checkLimit = pushLimitService.checkCoupon(tenantId, cUserId, send.getCouponId());
            } catch (MallinkException e) {
                logger.error("券达到limit: " + e.getMessage());
            }
            if (!checkLimit) {
                continue;
            }

            //检查条件
            if (!isConditionAllowed(send,param))
                continue;

            // 发放免费券
            WxCouponOrder couponOrder = null;
            try {
                couponOrder = wxOrderService.sendFreeCouponToUser(cUserId, send.getCouponId());
                if (couponOrder != null) {
                    wxCouponActionLogService.addOne(tenantId, send.getCouponId(), couponOrder.getId(), type.getCode(), send.getId());
                    bRet = true;
                }
            } catch (Exception e) {
                logger.error(e.getMessage());
            }
        }

        return bRet;
    }

    @Override
    public void updateStatusByCouponId(Long couponId, String tenantId, int status) {
        WxCouponSend wxCouponSend = new WxCouponSend();
        wxCouponSend.setTenantId(tenantId);
        wxCouponSend.setCouponId(couponId);
        wxCouponSend.setStatus(status);
        wxCouponSend.setUpdateDate(new Date());
        wxCouponSendMapper.updateStatusByCouponId(wxCouponSend);
    }
}
