package com.bonus.canteen.core.account.v4.web.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.canteen.core.account.v4.constant.CardStatusEnum;
import com.bonus.canteen.core.account.v4.web.mapper.AccCardMapper;
import com.bonus.canteen.core.account.v4.web.model.AccCard;
import com.bonus.canteen.core.account.vo.AccCardBaseInfoVO;
import com.bonus.canteen.core.customer.api.CustAccTempApi;
import com.bonus.canteen.core.customer.model.CustInfo;
import com.bonus.canteen.core.customer.mq.DelayedMessageSender;
import com.bonus.canteen.core.customer.mq.DelayedMessageTypeEnum;
import com.bonus.canteen.core.device.door.api.DcPushUserDataServiceApi;
import com.bonus.common.houqin.i18n.I18n;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import com.bonus.canteen.core.customer.business.CardInfoBurialPointBusiness;
import com.bonus.canteen.core.customer.service.CustInfoService;
import com.bonus.canteen.core.customer.v4.web.dto.CardInfoDTO;
import com.bonus.canteen.core.customer.v4.web.vo.CardInfoDetailVO;
import com.bonus.canteen.core.customer.v4.web.vo.CardInfoVO;
import com.bonus.common.houqin.utils.LeBeanUtil;
import org.springframework.stereotype.Service;

import java.util.List;

import javax.annotation.Resource;

@Service
public class CardInfoV4Service extends ServiceImpl<AccCardMapper, AccCard> {

    @Autowired
    @Lazy
    private AccCardMapper accCardMapper;

    public List<AccCardBaseInfoVO> listAccCardBaseInfo() {
        return this.accCardMapper.listAccCardBaseInfo();
    }
    @Resource
    @Lazy
    CustInfoService custInfoService;
    @Resource
    @Lazy
    private CardInfoBurialPointBusiness cardInfoBurialPointBusiness;
    @Autowired
    @Lazy
    private CustAccTempApi custAccTempApi;
    @Autowired
    @Lazy
    private DcPushUserDataServiceApi dcPushUserDataServiceApi;
    @Autowired
    @Lazy
    private DelayedMessageSender delayedMessageSender;

    public CardInfoDetailVO queryCardsByCustId(CardInfoDTO content) {
        CustInfo custInfo = (CustInfo)this.custInfoService.getOne(Wrappers.lambdaQuery(CustInfo.class)
                .eq(CustInfo::getCustId, content.getCustId()));
        if (custInfo == null) {
            return new CardInfoDetailVO();
        } else {
            CardInfoDetailVO cardInfoDetailVO = (CardInfoDetailVO) LeBeanUtil.copyCreateProperties(custInfo, CardInfoDetailVO.class);
            List<AccCard> cards = this.list(Wrappers.lambdaQuery(AccCard.class)
                    .eq(AccCard::getCustId, content.getCustId())
                    .in(AccCard::getCardStatus,
                    CardStatusEnum.normalAndLoss()));
            if (cards == null) {
                return cardInfoDetailVO;
            } else {
                List<CardInfoVO> cardInfoVO = BeanUtil.copyToList(cards, CardInfoVO.class);
                cardInfoDetailVO.setCardInfoList(cardInfoVO);
                this.cardInfoBurialPointBusiness.didGetCardList(cardInfoDetailVO);
                return cardInfoDetailVO;
            }
        }
    }

    public void lossReportingCard(CardInfoDTO content) {
        AccCard accCard = this.getOneAndCheckExist(content.getCustId(), content.getSerialNum());
        if (CardStatusEnum.LOSS.getKey().equals(accCard.getCardStatus())) {
            throw new ServiceException(I18n.getMessage("customer.card.freeze", new Object[0]));
        } else {
            this.updateCardStatus(content.getCustId(), CardStatusEnum.LOSS.getKey(), content.getSerialNum());
            this.custAccTempApi.updateCardStatus(accCard.getCustId(), CardStatusEnum.LOSS);
            this.dcPushUserDataServiceApi.editUser(accCard.getCustId());
            this.cardInfoBurialPointBusiness.didLossReportingCard(content);
            this.delayedMessageSender.asyncDelaySendToDevice(DelayedMessageTypeEnum.CARD);
        }
    }

    protected AccCard getOneAndCheckExist(long custId, String serialNum) {
        AccCard accCard = this.getOne(Wrappers
                .lambdaQuery(AccCard.class).eq(AccCard::getCustId, custId)
                .in(AccCard::getCardStatus, CardStatusEnum.normalAndLoss())
                .eq(AccCard::getSerialNum, serialNum));
        if (ObjectUtil.isNull(accCard)) {
            throw new ServiceException(I18n.getMessage("customer.card.serialNum.inExists", new Object[0]));
        } else {
            return accCard;
        }
    }

    public void updateCardStatus(Long custId, Integer cardStatus, String serialNum) {
        this.update(Wrappers
                .lambdaUpdate(AccCard.class).eq(AccCard::getSerialNum, serialNum)
                .eq(AccCard::getCustId, custId).in(AccCard::getCardStatus, CardStatusEnum.normalAndLoss())
                .set(AccCard::getCardStatus, cardStatus));
    }

    public void cancelLossReportingCard(CardInfoDTO content) {
        AccCard accCard = this.getOneAndCheckExist(content.getCustId(), content.getSerialNum());
        if (!CardStatusEnum.LOSS.getKey().equals(accCard.getCardStatus())) {
            throw new ServiceException(I18n.getMessage("customer.card.unloss", new Object[0]));
        } else {
            this.updateCardStatus(content.getCustId(), CardStatusEnum.NORMAL.getKey(), content.getSerialNum());
            this.custAccTempApi.updateCardStatus(accCard.getCustId(), CardStatusEnum.NORMAL);
            this.dcPushUserDataServiceApi.editUser(accCard.getCustId());
            this.cardInfoBurialPointBusiness.didCancelLossReportingCard(content);
            this.delayedMessageSender.asyncDelaySendToDevice(DelayedMessageTypeEnum.CARD);
        }
    }

}
