package com.sonic.pigeon.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.sonic.lion.lib.client.PayClient;
import com.sonic.lion.lib.output.AccountBuffOutput;
import com.sonic.pigeon.domain.bo.ImUserBo;
import com.sonic.pigeon.domain.input.ReceiveImMsgInput;
import com.sonic.pigeon.lib.bo.AttachBo;
import com.sonic.pigeon.lib.client.UserDeductionClient;
import com.sonic.pigeon.lib.enums.ImUserTypeEnum;
import com.sonic.pigeon.lib.enums.MessageTypeEnum;
import com.sonic.pigeon.service.CommonSendMqService;
import com.sonic.pigeon.service.ReceiveImMsgService;
import com.sonic.pigeon.utils.ImGenerator;
import com.sonic.pigeon.utils.RedisKeyUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @Author zzhan
 * @Date 2020/10/28 11:19
 * @Version 1.0
 */
@Slf4j
@Service
public class ReceiveImMsgServiceImpl implements ReceiveImMsgService {

    @Autowired
    private ImGenerator imGenerator;
    @Autowired
    private PayClient payClient;
    @Autowired
    private UserDeductionClient userDeductionClient;


    private List<String> DEFAULT_CHECK_MSG_TYPE = new ArrayList<>();

    /**
     * 一条文本预扣金额
     */
    private final static Long TEXT_DEDUCTION_AMOUNT = 100L;
    @Autowired
    private CommonSendMqService commonSendMqService;
    @Autowired
    private RedisKeyUtils redisKeyUtils;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    @PostConstruct
    public void init() {
        DEFAULT_CHECK_MSG_TYPE.add("TEXT");
        DEFAULT_CHECK_MSG_TYPE.add("PICTURE");
        DEFAULT_CHECK_MSG_TYPE.add("IMAGE");
    }

    @Override
    public Object receiveImMsgCheck(ReceiveImMsgInput input) {
        //处理逻辑，判断发送人。接收人
        ImUserBo fromUserBo = imGenerator.getImUserBo(input.getFromAccount());
        ImUserBo toUserBo = imGenerator.getImUserBo(input.getTo());
        Long fromUserId = fromUserBo.getUserId();
        //判断图片消息的发送
        if(ImUserTypeEnum.u == fromUserBo.getImUserType() && ImUserTypeEnum.r == toUserBo.getImUserType()) {
            //解析出自定义消息内容体
            AttachBo attachBo = StringUtils.isEmpty(input.getAttach()) ? null : JSONObject.parseObject(input.getAttach(), AttachBo.class);
            if(MessageTypeEnum.CUSTOM.name().equalsIgnoreCase(input.getMsgType()) && attachBo != null && "IMAGE".equalsIgnoreCase(attachBo.getType())) {
                String level = stringRedisTemplate.opsForValue().get(redisKeyUtils.aiUserHeartbeatLevelCacheKey(fromUserId, toUserBo.getUserId()));
                if(StringUtils.isEmpty(level) || "LEVEL_1".equals(level)) {
                    return buildFailResult("20001", "不允许发送图片消息！");
                }
            }
        }

        //余额不足，返回20000错误码
        if (!isBalanceNotCheck(input) && checkBalanceIsInsufficient(fromUserId)) {
            //发送MQ,计算费用结算
            commonSendMqService.userBalanceInsufficientCheckoutMq(fromUserId);
            return buildFailResult("20000", "你的余额不足！");
        }
        return buildSuccessResult();
    }

    /**
     * 是否不要余额检测
     *
     * @param input
     * @return
     */
    private boolean isBalanceNotCheck(ReceiveImMsgInput input) {
        String msgType = input.getMsgType();
        String attach = input.getAttach();
        JSONObject attachJson = JSONObject.parseObject(attach);
        //自定义消息且是语音通话
        if ("CUSTOM".equals(msgType) && "CALL".equals(attachJson.getString("type"))) {
            return true;
        }
        return false;
    }

    /**
     * 检测余额是否不足
     *
     * @param userId
     * @return
     */
    private boolean checkBalanceIsInsufficient(Long userId) {
        try {
            AccountBuffOutput accountBuff = payClient.getAccountBuff(userId);
            Long balance = accountBuff != null && accountBuff.getBalance() > 0 ? accountBuff.getBalance() : 0;
            log.info("checkBalanceIsInsufficient balance:{},totalDeductionAmount:{}", balance, TEXT_DEDUCTION_AMOUNT);
            if (balance < TEXT_DEDUCTION_AMOUNT) {
                return true;
            }
        } catch (Exception e) {
            log.error("checkBalanceIsInsufficient error:", e);
        }
        return false;
    }

    public Map<String, String> buildSuccessResult() {
        return buildResult("0", "", "");
    }

    private Map<String, String> buildFailResult(String responseCode, String callbackExt) {
        return buildResult("1", responseCode, callbackExt);
    }

    private Map<String, String> buildResult(String errorCode, String responseCode, String callbackExt) {
        Map<String, String> result = new HashMap<>(4);
        //0：表示回调通过，允许执行。
        //1：表示回调不通过，取消执行。如果设置了合法的自定义错误码（responseCode），则发送端会收到自定义错误码，否则发送端会收到403错误码。
        result.put("errCode", errorCode);
        //1、当errCode=1时有效
        //2、范围是20000-20099，其他值无效，会被忽略
        //3、特别的，对于消息类型的第三方回调（eventType=1、2、6、22），支持设置为200的错误码，客户端表现为消息发送成功，其实消息发送失败
        result.put("responseCode", responseCode);
        result.put("modifyResponse", "");
        result.put("callbackExt", callbackExt);
        return result;
    }

}
