package com.yeejoin.amos.boot.module.jcs.biz.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPObject;
import com.yeejoin.amos.boot.module.jcs.api.dto.AuthDataDto;
import com.yeejoin.amos.boot.module.jcs.api.service.ICcsToStationUserInfo;
import com.yeejoin.amos.boot.module.jcs.biz.config.StartLoader;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.component.cache.Redis;
import org.typroject.tyboot.component.cache.enumeration.CacheType;
import org.typroject.tyboot.component.emq.EmqKeeper;
import org.typroject.tyboot.component.emq.EmqxListener;
import org.typroject.tyboot.core.auth.face.model.SsoSessionsModel;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;

import javax.xml.crypto.Data;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 中心级用户登录信息同步实现类
 * @author xxz
 */
@Service
public class CcsToStationUserInfoImpl implements ICcsToStationUserInfo {
    private final Logger logger = LoggerFactory.getLogger(StartLoader.class);


    private static final String SESSION = "SESSION";

    private static final String SESSION_TOKEN = "SESSION_TOKEN";

    private static final String SESSION_LOGINID = "SESSION_LOGINID";

    private static final String SESSION_USERID = "SESSION_USERID";

    private static  Long DEFAULT_SESSION_EXPIRATION = 2592000L;

    @Autowired
    private EmqKeeper emqKeeper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${mqtt.topic.ccs.user.login}")
    private String ccsUserLogin;

    @Value("${mqtt.topic.station.user.login}")
    private String stationUserLogin;

    @Override
    public void sendUserInfoToStation(String userInfo) {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("topic", stationUserLogin);
            jsonObject.put("data", userInfo);
            emqKeeper.getMqttClient().publish(ccsUserLogin, jsonObject.toJSONString().getBytes(StandardCharsets.UTF_8), 0, false);
            logger.info("发送用户登录信息至站端>>>>{}", userInfo);
        } catch (Exception e) {
            logger.error("发送登录用户信息至站端失败{}", e.getMessage());
        }
    }

    @Override
    public void saveUserInfoToRedis() {
        try {
            emqKeeper.subscript(stationUserLogin, 1, new EmqxListener() {
                @Override
                public void processMessage(String s, MqttMessage mqttMessage) {
                    byte[] payload = mqttMessage.getPayload();

                    String obj = new String(payload);
                    if (!ValidationUtil.isEmpty(obj)) {
                        JSONObject json = JSON.parseObject(obj);
                        JSONObject body = JSON.parseObject(JSON.toJSONString(json.get("body")));
                        SsoSessionsModel ssoSessionsModel = new SsoSessionsModel();
                        AuthDataDto authData = JSON.parseObject(JSON.toJSONString(body.get("authData")), AuthDataDto.class);
                        try {
                            BeanUtils.copyProperties(authData, ssoSessionsModel);
                            createSession(ssoSessionsModel);
                        } catch (Exception e) {
                            logger.error("同步用户登录信息失败：{}", e.getMessage());
                        }
                    }
                }
            });
        } catch (Exception e) {
            logger.info("订阅中心级用户登录信息异常>>{}", e.getMessage());
        }
    }

    @Override
    public void test() {
        try {
            emqKeeper.subscript("zxjlc/cs", 0, new EmqxListener() {
                @Override
                public void processMessage(String s, MqttMessage mqttMessage) throws MqttException {
                    byte[] payload = mqttMessage.getPayload();

                    String obj = new String(payload);
                    if (!ValidationUtil.isEmpty(obj)) {
                        JSONObject json = JSON.parseObject(obj);
                        String isOk = JSON.toJSONString(json.get("is_ok"));
                        if (!"1".equals(isOk)) {
                            JSONObject jsonObject = new JSONObject();
                            jsonObject.put("indexKey", "TEST20230508WB");
                            jsonObject.put("indexValue", json.get("is_ok"));
                            jsonObject.put("traceId", json.get("id"));
                            JSONObject jsonObject1 = new JSONObject();
                            JSONObject jsonObject2 = new JSONObject();
                            JSONArray jsonArray = new JSONArray();
                            jsonObject1.put("warningObjectName", "巡检点");
                            jsonObject1.put("warningObjectCode", json.get("input_id"));

                            jsonObject1.put("sourceAttribution", "LSHLZ1yOrS3WfXqzjn");
                            jsonObject1.put("sourceAttributionDesc", "鄱阳湖");
                            jsonObject2.put("tabName", "页签");
                            jsonObject2.put("tabContent", new ArrayList<>());
                            jsonArray.add(jsonObject2);
                            jsonObject1.put("dynamicDetails", jsonArray);
                            jsonObject.put("bizInfo", jsonObject1);
                            emqKeeper.getMqttClient().publish("patrol/data/analysis", jsonObject.toJSONString().getBytes(StandardCharsets.UTF_8), 1, false);
//                            mqttSendGateway.sendToMqtt("patrol/data/analysis", JSON.toJSONString(jsonObject));
                        }
                    }
                }
            });
        } catch (Exception e) {
            logger.info("订阅中心级用户登录信息异常>>{}", e.getMessage());
        }
    }

    private void createSession(SsoSessionsModel authData) {

        this.removeSession(authData.getActionByProduct(),authData.getLoginId());

        this.redisTemplate.opsForValue().set(sessionCacheKeyWithToken(authData.getToken(),authData.getActionByProduct()),authData);

        this.redisTemplate.opsForValue().set(sessionCacheKeyWithLoginId(authData.getLoginId(),authData.getActionByProduct()),authData);

        this.redisTemplate.opsForValue().set(loginIdCacheWithToken(authData.getToken()),authData.getLoginId());

        this.redisTemplate.opsForValue().set(sessionCacheKeyWithUserId(authData.getUserId()),authData);

        redisTemplate.expire(sessionCacheKeyWithToken(authData.getToken(),authData.getActionByProduct()),DEFAULT_SESSION_EXPIRATION, TimeUnit.SECONDS);

        redisTemplate.expire(sessionCacheKeyWithLoginId(authData.getLoginId(),authData.getActionByProduct()),DEFAULT_SESSION_EXPIRATION, TimeUnit.SECONDS);

        redisTemplate.expire(loginIdCacheWithToken(authData.getToken()),DEFAULT_SESSION_EXPIRATION, TimeUnit.SECONDS);

        redisTemplate.expire(sessionCacheKeyWithUserId(authData.getUserId()),DEFAULT_SESSION_EXPIRATION, TimeUnit.SECONDS);

    }

    private void removeSession(String  actionByProduct ,String loginId) {

        SsoSessionsModel sessionsModel = (SsoSessionsModel)this.redisTemplate.opsForValue().get(sessionCacheKeyWithLoginId(loginId,actionByProduct));

        if(!ObjectUtils.isEmpty(sessionsModel)) {
            this.redisTemplate.delete(sessionCacheKeyWithLoginId(loginId,actionByProduct));

            this.redisTemplate.delete(sessionCacheKeyWithToken(sessionsModel.getToken(),actionByProduct));

            SsoSessionsModel model = queryByUserId(sessionsModel.getUserId());

            if(!ObjectUtils.isEmpty(model) && model.getToken().equals(sessionsModel.getToken())) {
                this.redisTemplate.delete(sessionCacheKeyWithUserId(sessionsModel.getUserId()));
            }
        }

    }

    private static String sessionCacheKeyWithToken(String token,String actionByProduct) {
        return Redis.genKey(CacheType.ERASABLE.name(),SESSION_TOKEN,actionByProduct,token);
    }

    private static String sessionCacheKeyWithLoginId(String loginId,String actionByProduct) {
        return Redis.genKey(CacheType.ERASABLE.name(),SESSION,actionByProduct,loginId);
    }

    private static String loginIdCacheWithToken(String token) {
        return Redis.genKey(CacheType.ERASABLE.name(),SESSION_LOGINID,token);
    }

    private static String sessionCacheKeyWithUserId(String userId) {
        return Redis.genKey(CacheType.ERASABLE.name(),SESSION_USERID,userId);
    }

    private SsoSessionsModel queryByUserId(String userId) {
        return (SsoSessionsModel) this.redisTemplate.opsForValue().get(sessionCacheKeyWithUserId(userId));
    }


}
