package com.neusoft.smart.pos.mq.helper;

import com.alibaba.fastjson.JSONObject;
import com.neusoft.smart.pos.card.constants.CardCapitalChangeType;
import com.neusoft.smart.pos.card.dto.UpdateCardRequest;
import com.neusoft.smart.pos.card.persistent.domain.Card;
import com.neusoft.smart.pos.card.persistent.domain.CardCapitalChange;
import com.neusoft.smart.pos.card.persistent.domain.CardOrder;
import com.neusoft.smart.pos.card.persistent.repository.CardCapitalChangeRepository;
import com.neusoft.smart.pos.card.persistent.repository.ICardRelationRepository;
import com.neusoft.smart.pos.card.service.CardService;
import com.neusoft.smart.pos.card.service.CardTradeService;
import com.neusoft.smart.pos.constants.DictionaryConstant;
import com.neusoft.smart.pos.dto.card.request.RechargeRequest;
import com.neusoft.smart.pos.dto.order.response.GetAllOrderInfoResponse;
import com.neusoft.smart.pos.exchangeStrategy.constants.ExchangeStrategyConstants;
import com.neusoft.smart.pos.exchangeStrategy.persistent.domain.ExchangeStrategy;
import com.neusoft.smart.pos.exchangeStrategy.persistent.domain.ExchangeStrategyTypeDict;
import com.neusoft.smart.pos.exchangeStrategy.persistent.repository.IExchangeStrategy;
import com.neusoft.smart.pos.exchangeStrategy.service.ExchangeStrategyTypeDictService;
import com.neusoft.smart.pos.framework.utils.DateUtils;
import com.neusoft.smart.pos.framework.utils.SpringUtils;
import com.neusoft.smart.pos.mq.util.JsonUtil;

import lombok.val;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.SerializationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@Component
public class MemberMQReceiverHelper {

    private static Logger logger = LoggerFactory.getLogger(MemberMQReceiverHelper.class);

    @Resource
    private CardTradeService cardTradeService;

    @Resource
    private CardService cardService;

    @Resource
    private ExchangeStrategyTypeDictService exchangeStrategyTypeDictService;

    @Resource
    private CardCapitalChangeRepository cardCapitalChangeRepository;

    /**
     * 充值订单完成后，要更新卡内余额
     * @param content
     */
    //rabbitmq
    @Transactional
    public void processOrderCompleteMessage(byte[] content) {
        logger.info("消息接收者接收到来自【order.complete队列二】的消息，消息内容:{}",content);
        GetAllOrderInfoResponse info = (GetAllOrderInfoResponse) SerializationUtils.deserialize(content);
        logger.info("反序列化消息内容:{}",info);
        processOrderCompleteMessage(info);
    }
    
    //aliyunRocketMq
    @Transactional
    public void processOrderCompleteStringMessage(String content) {
        logger.info("消息接收者接收到来自【order.complete队列二】的消息，消息内容:{}",content);
        GetAllOrderInfoResponse info = (GetAllOrderInfoResponse) JsonUtil.readValue(content, GetAllOrderInfoResponse.class);
        logger.info("反序列化消息内容:{}",info);
        processOrderCompleteMessage(info);
    }
    
    public void processOrderCompleteMessage(GetAllOrderInfoResponse info) {
    	String orderType = info.getOrderType();
        if(orderType.equals(DictionaryConstant.ORDER_TYPE_HYCZ.getCode())
                && info.getOrderStatus().equals(DictionaryConstant.ORDER_UPDATE_STATUS_ZFWC.getCode())) { //充值订单并且状态为支付完成
            List<GetAllOrderInfoResponse.PayInfo> payInfos = info.getPayInfos();
            for (GetAllOrderInfoResponse.PayInfo payInfo : payInfos) {
                RechargeRequest rechargeRequest = new RechargeRequest();
                try {
                    JSONObject RequestDetailInfoJsonObject = JSONObject.parseObject(payInfo.getRequestDetailInfo());
                    rechargeRequest.setCardNum(RequestDetailInfoJsonObject.getString("cardNum"));
                } catch (Exception e) {
                    logger.error("获取cardNum失败");
                    return;
                }
                if(StringUtils.isEmpty(rechargeRequest.getCardNum())) {
                    logger.error("cardNum为空");
                    return;
                }
                rechargeRequest.setOutRechargeOrderNo(payInfo.getTradeId());
                rechargeRequest.setRechargeAmount(payInfo.getPayAmount());
                rechargeRequest.setRechargeMode(Integer.parseInt(payInfo.getPayType()));
                rechargeRequest.setRechargeTime(DateUtils.parse(payInfo.getPayTime(), DateUtils.FORMAT_LONG));
                doRecharge(rechargeRequest, info.getSerialNo(), info.getOrgId(), info.getShopId());
            }
        }
    }
    
    

    public void doRecharge(RechargeRequest rechargeRequest, String sn, Integer orgId, Integer shopId) {
        logger.info("doRecharge");
        Card card = cardService.getSingleCard(rechargeRequest.getCardNum(), rechargeRequest.getCardAnotherId(), rechargeRequest.getCardOtherId(), sn, orgId, shopId);
        if(card == null) {
            logger.error("缺少充值参数");
            return;
        }
        Long balance = card.getCardBalance();
        Long rechargeAmount = convertAmount(card,rechargeRequest.getRechargeAmount());
        CardOrder cardOrder = cardTradeService.createRechargeOrder(rechargeRequest, card.getCardId());

        //更新卡数据
        int res = this.updateCard(card.getCardNum(), balance, card.getCardPoint(), balance+rechargeAmount,card.getCardPoint(), rechargeAmount);
        if(res <= 0) {
            logger.error("充值失败，卡数据写入失败");
            return;
        }

        //存变更数据
        Long afterBalance = balance+rechargeAmount;
        this.createCardCapitalChange(card.getCardId(),card.getCardNum(),cardOrder.getCardTradeNum(),
                rechargeAmount, balance, afterBalance, //正数 意味着加钱
                null, null, null,
                "充值:"+rechargeRequest.getRechargeMode(), CardCapitalChangeType.RECHARGE.getCode(), rechargeRequest.getRechargeTime());

    }

    public int updateCard(String cardNum, Long beforeBalance, Integer beforePoint, Long afterBalance, Integer afterPoint, Long rechargeAmount) {
        UpdateCardRequest updateCardRequest = new UpdateCardRequest();
        updateCardRequest.setCardNum(cardNum);
        updateCardRequest.setCardBeforeBalance(beforeBalance);
        updateCardRequest.setCardBeforePoint(beforePoint);
        updateCardRequest.setCardAfterBalance(afterBalance);
        updateCardRequest.setCardAfterPoint(afterPoint);
        updateCardRequest.setRechargeAmount(rechargeAmount);
        return cardService.updateCard(updateCardRequest);
    }

    public void createCardCapitalChange(Integer cardId, String cardNum, String cardTradeNum,
                                        Long changeAmount, Long amountBefore, Long amountAfter,
                                        Integer changePoint, Integer pointBefore, Integer pointAfter,
                                        String content, int changeType, Date changeTime) {
        CardCapitalChange cardCapitalChange = new CardCapitalChange();
        cardCapitalChange.setCardId(cardId);
        cardCapitalChange.setCardNum(cardNum);
        cardCapitalChange.setChangeOrderId(cardTradeNum);
        cardCapitalChange.setAmountChange(changeAmount);//正数 意味着加钱, 负数 意味着减钱
        cardCapitalChange.setAmountBefore(amountBefore);
        cardCapitalChange.setAmountAfter(amountAfter);
        cardCapitalChange.setPointChange(changePoint);
        cardCapitalChange.setPointBefore(pointBefore);
        cardCapitalChange.setPointAfter(pointAfter);
        cardCapitalChange.setContent(content);
        cardCapitalChange.setChangeType(changeType);
        cardCapitalChange.setChangeTime(changeTime);
        cardCapitalChangeRepository.createChange(cardCapitalChange);
    }

    // 使用充值转换策略服务
    public Long convertAmount(Card card, Long orderAmount) {
        Long newAmount = doExchange(card, orderAmount, ExchangeStrategyConstants.EXCHANGE_STRATEGY_CATEGORY_RECHARGE.getCode());
        if(newAmount < 0) {
            newAmount = orderAmount;
        }
        return newAmount;
    }

    public Long doExchange(Card card, Long orderAmount, String strategyCategory) {
        val cardRelationRepository = SpringUtils.getBean(card.getBeanName(), ICardRelationRepository.class);
        ExchangeStrategy exchangeStrategy = cardRelationRepository.getExchangeStrategy(card.getCardId(), strategyCategory);
        if(exchangeStrategy != null) {
            ExchangeStrategyTypeDict strategyType = exchangeStrategyTypeDictService.getExchangeStrategyType(exchangeStrategy.getStrategyTypeId());
            String params = exchangeStrategy.getParams();
            if(strategyType != null) {
                val strategy = SpringUtils.getBean(strategyType.getStrategyBeanName(), IExchangeStrategy.class);
                return strategy.doExchange(orderAmount, params);
            }
        }
        return -1L;
    }

}
