package com.liquidnet.service.adam.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.common.third.easemob.util.EasemobUtil;
import com.liquidnet.commons.lang.core.JwtValidator;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.adam.constant.AdamConst;
import com.liquidnet.service.adam.dto.AdamUserInfoParam;
import com.liquidnet.service.adam.dto.vo.AdamTagParentVo;
import com.liquidnet.service.adam.dto.vo.AdamTagVo;
import com.liquidnet.service.adam.dto.vo.AdamUserInfoVo;
import com.liquidnet.service.adam.service.AdamRdmService;
import com.liquidnet.service.adam.service.IAdamUserInfoService;
import com.liquidnet.service.adam.util.QueueUtils;
import com.liquidnet.service.base.ErrorMapping;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 用户信息 服务实现类
 * </p>
 *
 * @author liquidnet
 * @since 2021-05-10
 */
@Slf4j
@Service
public class AdamUserInfoServiceImpl implements IAdamUserInfoService {
    @Autowired
    AdamRdmService adamRdmService;
    @Autowired
    QueueUtils queueUtils;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    JwtValidator jwtValidator;
    @Autowired
    private EasemobUtil easemobUtil;

    @Value("${liquidnet.reviewer.user-info}")
    private Boolean reviewUserInfo;
    // 用户注册IM的密码
    private static final String ppwd = "138CEF91A62088BD3EF329FA3A6176CB18A";

    @Override
//    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ResponseDto<AdamUserInfoVo> edit(AdamUserInfoParam parameter) {
        String currentUid = CurrentUtil.getCurrentUid();
        AdamUserInfoVo userInfoVo = adamRdmService.getUserInfoVoByUid(currentUid);

        List<AdamTagParentVo> tagMe = parameter.getTagMe();
        String uuid = null, type = null, created = null, modified = null;

        boolean syncChimeFlg = false;// 标识是否需要同步`service-chime`
        if (!CollectionUtil.isEmpty(tagMe)) {// 标签不为空则注册或更新IM
            String nickname = parameter.getNickname();
            boolean syncIMNicknameFlg = null != nickname && !nickname.equals(userInfoVo.getNickname());
            Integer voIsComplete = userInfoVo.getIsComplete();

            int isComplete = voIsComplete == 0 ? 1 : voIsComplete;
            if (isComplete == 1) {// 注册IM
                JSONObject jsonObject = null;
                try {
                    // 138cef91a62088bd3ef329fa3a6176cb18a > 138CEF91A62088BD3EF329FA3A6176CB18A > IM@zhengzai
                    String result = easemobUtil.createUser(userInfoVo.getUid(), ppwd, userInfoVo.getNickname());

                    jsonObject = JSONObject.parseObject(result);
                } catch (Exception e) {
                    log.error("###编辑资料:注册IM异常[uid:{},mobile:{}]", userInfoVo.getUid(), userInfoVo.getMobile());
                }
                if (null == jsonObject) {
                    return ResponseDto.failure(ErrorMapping.get("10014"));
                }
                if (StringUtil.isNotNull(jsonObject.get("error"))) {
                    return ResponseDto.failure(ErrorMapping.get("10014"));
                }
                if (jsonObject.getBooleanValue("activated")) {
                    isComplete = 11;

                    type = jsonObject.getString("type");
                    uuid = jsonObject.getString("uuid");
                    created = jsonObject.getString(created);
                    modified = jsonObject.getString("modified");
                }
            } else if (syncIMNicknameFlg && isComplete == 11) {// 同步IM信息
                // TODO: 2021/9/17 暂未接入
            }

            userInfoVo.setIsComplete(isComplete);

            syncChimeFlg = true;
        } else {
            tagMe = userInfoVo.getTagMe();
        }

        AdamTagVo sex = parameter.getSex();
        syncChimeFlg = syncChimeFlg || !userInfoVo.getSex().getVal().equals(sex.getVal());

        if (syncChimeFlg) {// 同步`service-chime`

        }


//        userInfoVo.setAvatar(parameter.getAvatar());
//        userInfoVo.setBackground(parameter.getBackground());
//        userInfoVo.setNickname(parameter.getNickname());
        userInfoVo.setAvatar(StringUtils.isEmpty(userInfoVo.getAvatar()) ? AdamConst.DEF_URL_AVATAR : userInfoVo.getAvatar());
        userInfoVo.setBackground(StringUtils.isEmpty(userInfoVo.getBackground()) ? AdamConst.DEF_URL_BACKGROUND : userInfoVo.getBackground());
        userInfoVo.setNickname(userInfoVo.getNickname());
        userInfoVo.setSex(sex);
        userInfoVo.setBirthday(parameter.getBirthday());
        userInfoVo.setArea(parameter.getArea());
//        userInfoVo.setSignature(parameter.getSignature());
        userInfoVo.setSignature(userInfoVo.getSignature());
        userInfoVo.setTagMe(tagMe);
        userInfoVo.setUpdatedAt(LocalDateTime.now());
//        userInfoVo.setIsComplete(1);


        long s = System.currentTimeMillis();
        adamRdmService.setUserInfoVoByUid(userInfoVo.getUid(), userInfoVo);
        log.debug("#RDS耗时:{}ms", System.currentTimeMillis() - s);


        LinkedList<String> toMqSqls = CollectionUtil.linkedListString();
        LinkedList<Object[]> updateUserObjs = CollectionUtil.linkedListObjectArr(),
                updateUserInfoObjs = CollectionUtil.linkedListObjectArr();

        s = System.currentTimeMillis();
        toMqSqls.add(SqlMapping.get("adam_user.complete"));
        updateUserObjs.add(new Object[]{1, userInfoVo.getUpdatedAt(), userInfoVo.getUid()});
        toMqSqls.add(SqlMapping.get("adam_user_info.edit"));
        updateUserInfoObjs.add(new Object[]{
                userInfoVo.getNickname(),
                JsonUtils.toJson(sex),
                userInfoVo.getBirthday(),
                userInfoVo.getArea(),
                userInfoVo.getSignature(),
                userInfoVo.getAvatar(),
                userInfoVo.getBackground(),
                JsonUtils.toJson(tagMe),
                userInfoVo.getUid()}
        );
        log.debug("#SQL.GET耗时:{}ms", System.currentTimeMillis() - s);

        s = System.currentTimeMillis();
        queueUtils.sendMsgByRedis(MQConst.AdamQueue.SQL_UCENTER.getKey(),
                SqlMapping.gets(toMqSqls, updateUserObjs, updateUserInfoObjs)
        );
        log.debug("#MQ耗时:{}ms", System.currentTimeMillis() - s);

        return ResponseDto.success(userInfoVo.desensitize(reviewUserInfo));
    }

    @Override
//    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public String editMobile(String uid, String mobile) {
        LocalDateTime now = LocalDateTime.now();
        AdamUserInfoVo beforeUserInfoVo = adamRdmService.getUserInfoVoByUid(uid);

        long s = System.currentTimeMillis();
        adamRdmService.delUidByMobile(beforeUserInfoVo.getMobile());
        adamRdmService.setUidByMobile(mobile, uid);
        beforeUserInfoVo.setMobile(mobile);
        beforeUserInfoVo.setUpdatedAt(now);
        adamRdmService.setUserInfoVoByUid(uid, beforeUserInfoVo);
        log.debug("#RDS耗时:{}ms", System.currentTimeMillis() - s);

        s = System.currentTimeMillis();
        queueUtils.sendMsgByRedis(MQConst.AdamQueue.SQL_UCENTER.getKey(),
                SqlMapping.get("adam_user.edit.mobile", mobile, now, uid)
        );
        log.debug("#MQ耗时:{}ms", System.currentTimeMillis() - s);

        return this.flushSsoProcess(beforeUserInfoVo);
    }

    private String flushSsoProcess(AdamUserInfoVo userInfoVo) {
        Map<String, Object> claimsMap = CollectionUtil.mapStringObject();
        claimsMap.put("sub", userInfoVo.getUid());
        claimsMap.put("mobile", userInfoVo.getMobile());
        claimsMap.put("nickname", userInfoVo.getNickname());
        claimsMap.put("type", "user");

        String token = jwtValidator.create(claimsMap);

        redisUtil.set(
                jwtValidator.getSsoRedisKey().concat(userInfoVo.getUid()),
                DigestUtils.md5DigestAsHex(token.getBytes(StandardCharsets.UTF_8)),
                jwtValidator.getExpireTtl() * 60
        );
        return token;
    }
}
