package com.liquidnet.client.admin.zhengzai.admin.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.liquidnet.client.admin.common.enums.UpushTargetType;
import com.liquidnet.client.admin.common.utils.ShiroUtils;
import com.liquidnet.client.admin.zhengzai.kylin.utils.upush.AndroidNotification;
import com.liquidnet.client.admin.zhengzai.kylin.utils.upush.PushClient;
import com.liquidnet.client.admin.zhengzai.kylin.utils.upush.android.AndroidBroadcast;
import com.liquidnet.client.admin.zhengzai.kylin.utils.upush.ios.IOSBroadcast;
import com.liquidnet.common.cache.redis.util.RedisDataSourceUtil;
import com.liquidnet.commons.lang.constant.LnsEnum;
import com.liquidnet.commons.lang.util.*;
import com.liquidnet.service.adam.dto.vo.admin.AdminUpushVo;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.dao.UpushDetailsListDao;
import com.liquidnet.service.kylin.dto.param.admin.UpushParam;
import com.liquidnet.service.kylin.dto.param.admin.UpushSearchParam;
import com.liquidnet.service.kylin.entity.AdminUpush;
import com.liquidnet.service.kylin.mapper.AdminUpushMapper;
import com.liquidnet.service.kylin.service.admin.IAdminUpushService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 友盟消息推送 服务实现类
 * </p>
 *
 * @author jiangxiulong
 * @since 2021-07-13
 */
@Service
public class AdminUpushServiceImpl extends ServiceImpl<AdminUpushMapper, AdminUpush> implements IAdminUpushService {

    @Value("${liquidnet.aliyun.oss.imgUrl}")
    private String imgUrl;

    @Value("${liquidnet.umeng.ios.appkey}")
    private String iosAppkey;
    @Value("${liquidnet.umeng.ios.appMasterSecret}")
    private String iosAppMasterSecret;
    @Value("${liquidnet.umeng.android.appkey}")
    private String androidAppkey;
    @Value("${liquidnet.umeng.android.appMasterSecret}")
    private String androidAppMasterSecret;

    private PushClient client = new PushClient();

    @Autowired
    Environment environment;

    @Autowired
    private AdminUpushMapper adminUpushMapper;

    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    RedisDataSourceUtil redisDataSourceUtil;

    public Boolean create(UpushParam upushParam) {
        try {
            // 入数据库
            String upushId = IDGenerator.nextSnowId();
            upushParam.setUpushId(upushId);
            String authId = ShiroUtils.getUserId().toString();
            String authName = ShiroUtils.getLoginName();
            AdminUpush adminUpush = new AdminUpush();
            BeanUtils.copyProperties(upushParam, adminUpush);
            adminUpush.setCreatedAt(DateUtil.getNowTime());
            adminUpush.setPushedBy(authId);
            adminUpush.setPushedName(authName);
            if (adminUpush.getPushTime().isEmpty()) {
                adminUpush.setPushTime(DateUtil.getNowTime());
            }
            adminUpushMapper.insert(adminUpush);

            // 处理缓存数据
            List<AdminUpush> pushListIos = adminUpushMapper.selectList(
                    Wrappers.lambdaQuery(AdminUpush.class)
                            .in(AdminUpush::getPushRange, 1, 2)
                            .orderByDesc(AdminUpush::getPushTime)
                            .last("LIMIT 20")
            );
            LinkedList<AdminUpushVo> pushLinkedIos = new LinkedList<>();
            for (AdminUpush upush : pushListIos) {
                AdminUpushVo adminUpushVo = AdminUpushVo.getNew();
                BeanUtils.copyProperties(upush, adminUpushVo);
                pushLinkedIos.add(adminUpushVo);
            }
            List<AdminUpush> pushListAndroid = adminUpushMapper.selectList(
                    Wrappers.lambdaQuery(AdminUpush.class)
                            .in(AdminUpush::getPushRange, 1, 3)
                            .orderByDesc(AdminUpush::getPushTime)
                            .last("LIMIT 20")
            );
            LinkedList<AdminUpushVo> pushLinkedAndroid = new LinkedList<>();
            for (AdminUpush upush : pushListAndroid) {
                AdminUpushVo adminUpushVo = AdminUpushVo.getNew();
                BeanUtils.copyProperties(upush, adminUpushVo);
                pushLinkedAndroid.add(adminUpushVo);
            }

            String redisKeyIos = KylinRedisConst.ADMIN_UPUSH_LIST_IOS;
            String redisKeyAndroid = KylinRedisConst.ADMIN_UPUSH_LIST_ANDROID;
            if (upushParam.getPushRange() == 1) { // all
                redisDataSourceUtil.getRedisKylinUtil().set(redisKeyIos, pushLinkedIos);
                redisDataSourceUtil.getRedisKylinUtil().set(redisKeyAndroid, pushLinkedAndroid);
            } else if (upushParam.getPushRange() == 2) { // ios
                redisDataSourceUtil.getRedisKylinUtil().set(redisKeyIos, pushLinkedIos);
            } else if (upushParam.getPushRange() == 3) { // android
                redisDataSourceUtil.getRedisKylinUtil().set(redisKeyAndroid, pushLinkedAndroid);
            }
            /*AdminUpushVo adminUpushVo = new AdminUpushVo();
            BeanUtils.copyProperties(adminUpush, adminUpushVo);
            adminUpushVo.setMessageType(2);
            adminUpushVo.setSpecifyType(2); // 这里暂时写死就行 如果以后改需求再处理
            String redisKeyIos = KylinRedisConst.ADMIN_UPUSH_LIST_IOS;
            String redisKeyAndroid = KylinRedisConst.ADMIN_UPUSH_LIST_ANDROID;
            LinkedList<AdminUpushVo> pushList = new LinkedList<>();
            LinkedList<AdminUpushVo> pushList2 = new LinkedList<>();
            if (upushParam.getPushRange() == 1) { // all
                pushList = (LinkedList<AdminUpushVo>) redisDataSourceUtil.getRedisKylinUtil().get(redisKeyIos);
                pushList2 = (LinkedList<AdminUpushVo>) redisDataSourceUtil.getRedisKylinUtil().get(redisKeyAndroid);
            } else if (upushParam.getPushRange() == 2) { // ios
                pushList = (LinkedList<AdminUpushVo>) redisDataSourceUtil.getRedisKylinUtil().get(redisKeyIos);
            } else if(upushParam.getPushRange() == 3) { // android
                pushList = (LinkedList<AdminUpushVo>) redisDataSourceUtil.getRedisKylinUtil().get(redisKeyAndroid);
            }

            if (null == pushList) {
                pushList = new LinkedList<>();
            }
            if (null == pushList2) {
                pushList2 = new LinkedList<>();
            }
            if (upushParam.getPushRange() == 1) {
                if (!CollectionUtil.isEmpty(pushList)) {
                    if (pushList.size() >= 20) {
                        pushList.remove(pushList.size()-1);
                    }
                }
                pushList.addFirst(adminUpushVo);
                if (!CollectionUtil.isEmpty(pushList2)) {
                    if (pushList2.size() >= 20) {
                        pushList2.remove(pushList.size()-1);
                    }
                }
                pushList2.addFirst(adminUpushVo);
            } else {
                if (!CollectionUtil.isEmpty(pushList)) {
                    if (pushList.size() >= 20) {
                        pushList.remove(pushList.size()-1);
                    }
                }
                pushList.addFirst(adminUpushVo);
            }
            if (upushParam.getPushRange() == 1) { // all
                redisDataSourceUtil.getRedisKylinUtil().set(redisKeyIos, pushList);
                redisDataSourceUtil.getRedisKylinUtil().set(redisKeyAndroid, pushList2);
            } else if (upushParam.getPushRange() == 2) { // ios
                redisDataSourceUtil.getRedisKylinUtil().set(redisKeyIos, pushList);
            } else if(upushParam.getPushRange() == 3) { // android
                redisDataSourceUtil.getRedisKylinUtil().set(redisKeyAndroid, pushList);
            }*/

            // 推送
            if (adminUpush.getIsPush() == 1) {
                if (adminUpush.getPushRange() == 1) {
                    sendAndroidBroadcast(adminUpush);
                    sendIOSBroadcast(adminUpush);
                } else if (adminUpush.getPushRange() == 2) {
                    sendIOSBroadcast(adminUpush);
                } else if (adminUpush.getPushRange() == 3) {
                    sendAndroidBroadcast(adminUpush);
                }
            }
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public PageInfo<UpushDetailsListDao> lists(UpushSearchParam upushSearchParam) {
        try {
            PageHelper.startPage(upushSearchParam.getPageNum(), upushSearchParam.getPageSize());
            List<UpushDetailsListDao> voList = adminUpushMapper.searchList(BeanUtil.convertBeanToMap(upushSearchParam));
            for (UpushDetailsListDao item : voList) {
                String typeName = UpushTargetType.getTypeName(item.getJumpType());
                item.setJumpName(typeName);
            }

            return new PageInfo(voList);
        } catch (Exception e) {
            return new PageInfo(new ArrayList());
        }
    }

    public UpushDetailsListDao detail(String upushId) {
        AdminUpush data = adminUpushMapper.selectOne(Wrappers.lambdaQuery(AdminUpush.class).eq(AdminUpush::getUpushId, upushId));
        UpushDetailsListDao upushDetailsListDao = new UpushDetailsListDao();
        if (null != data) {
            String typeName = UpushTargetType.getTypeName(data.getJumpType());
            BeanUtils.copyProperties(data, upushDetailsListDao);
            upushDetailsListDao.setImg(imgUrl + upushDetailsListDao.getImg());
            upushDetailsListDao.setJumpName(typeName);
        } else {
            return null;
        }

        return upushDetailsListDao;
    }

    public void sendAndroidBroadcast(AdminUpush adminUpush) {
        AdminUpush updatePush = new AdminUpush();
        try {
            AndroidBroadcast broadcast = new AndroidBroadcast(androidAppkey, androidAppMasterSecret);
            broadcast.setBadge(1);
            broadcast.setTicker(adminUpush.getPushTitle());
            broadcast.setTitle(adminUpush.getPushTitle());
            broadcast.setText(adminUpush.getPushContent());
            String custom = UpushTargetType.getTypeAction(adminUpush.getJumpType());
            broadcast.goCustomAfterOpen(custom);
            broadcast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
            if (!LnsEnum.ENV.prod.name().equals(environment.getProperty(CurrentUtil.CK_ENV_ACTIVE))) {
                broadcast.setTestMode();
            } else {
                broadcast.setProductionMode();
            }
            // Set customized fields
            broadcast.setExtraField("type", adminUpush.getJumpType().toString());
            broadcast.setExtraField("id", adminUpush.getJumpValue());
            broadcast.setExtraField("url", adminUpush.getJumpValue());

            if (adminUpush.getSendType() == 1) {
                String pushTime = adminUpush.getPushTime();
                broadcast.setPredefinedKeyValue("start_time", pushTime);
            }
            String sendRes = client.send(broadcast);
            HashMap hashMap = JsonUtils.fromJson(sendRes, HashMap.class);
            String ret = (String) hashMap.get("ret");
            if (ret.equals("SUCCESS")) {
                HashMap data = (HashMap) hashMap.get("data");
                String msg_id = (String) data.get("msg_id");
                String task_id = (String) data.get("task_id");
                if (null != msg_id && !msg_id.isEmpty()) {
                    updatePush.setMsgId(msg_id);
                }
                if (null != task_id && !task_id.isEmpty()) {
                    updatePush.setTaskId(task_id);
                }
            } else {
                HashMap data = (HashMap) hashMap.get("data");
                String msg_id = (String) data.get("msg_id");
                String task_id = (String) data.get("task_id");
                String error_code = (String) data.get("error_code");
                String error_msg = (String) data.get("error_msg");
                if (null != msg_id && !msg_id.isEmpty()) {
                    updatePush.setMsgId(msg_id);
                }
                if (null != task_id && !task_id.isEmpty()) {
                    updatePush.setTaskId(task_id);
                }
                if (null != error_code && !error_code.isEmpty()) {
                    updatePush.setErrorCode(error_code);
                }
                if (null != error_msg && !error_msg.isEmpty()) {
                    updatePush.setErrorMsg(error_msg);
                }
            }
            updatePush.setUpdatedAt(DateUtil.getNowTime());
            adminUpushMapper.update(updatePush, Wrappers.lambdaUpdate(AdminUpush.class).eq(AdminUpush::getUpushId, adminUpush.getUpushId()));
        } catch (Exception e) {
            updatePush.setErrorMsg(e.getMessage());
            updatePush.setUpdatedAt(DateUtil.getNowTime());
            adminUpushMapper.update(updatePush, Wrappers.lambdaUpdate(AdminUpush.class).eq(AdminUpush::getUpushId, adminUpush.getUpushId()));
            e.printStackTrace();
        }
    }

    public void sendIOSBroadcast(AdminUpush adminUpush) {
        AdminUpush updatePush = new AdminUpush();
        try {
            IOSBroadcast broadcast = new IOSBroadcast(iosAppkey, iosAppMasterSecret);
            //alert的值设置为字典
            broadcast.setAlert(adminUpush.getPushTitle(), "", adminUpush.getPushContent());
            broadcast.setBadge(1);
            broadcast.setSound("default");
            if (!LnsEnum.ENV.prod.name().equals(environment.getProperty(CurrentUtil.CK_ENV_ACTIVE))) {
                broadcast.setTestMode();
            } else {
                broadcast.setProductionMode();
            }
            // Set customized fields
            broadcast.setCustomizedField("type", adminUpush.getJumpType().toString());
            broadcast.setCustomizedField("id", adminUpush.getJumpValue());
            broadcast.setCustomizedField("url", adminUpush.getJumpValue());

            if (adminUpush.getSendType() == 1) {
                String pushTime = adminUpush.getPushTime();
                broadcast.setPredefinedKeyValue("start_time", pushTime);
            }
            String sendRes = client.send(broadcast);
            HashMap hashMap = JsonUtils.fromJson(sendRes, HashMap.class);
            String ret = (String) hashMap.get("ret");
            if (ret.equals("SUCCESS")) {
                HashMap data = (HashMap) hashMap.get("data");
                String msg_id = (String) data.get("msg_id");
                String task_id = (String) data.get("task_id");
                if (null != msg_id && !msg_id.isEmpty()) {
                    updatePush.setMsgId(msg_id);
                }
                if (null != task_id && !task_id.isEmpty()) {
                    updatePush.setTaskId(task_id);
                }
            } else {
                HashMap data = (HashMap) hashMap.get("data");
                String msg_id = (String) data.get("msg_id");
                String task_id = (String) data.get("task_id");
                String error_code = (String) data.get("error_code");
                String error_msg = (String) data.get("error_msg");
                if (null != msg_id && !msg_id.isEmpty()) {
                    updatePush.setMsgId(msg_id);
                }
                if (null != task_id && !task_id.isEmpty()) {
                    updatePush.setTaskId(task_id);
                }
                if (null != error_code && !error_code.isEmpty()) {
                    updatePush.setErrorCode(error_code);
                }
                if (null != error_msg && !error_msg.isEmpty()) {
                    updatePush.setErrorMsg(error_msg);
                }
            }
            updatePush.setUpdatedAt(DateUtil.getNowTime());
            adminUpushMapper.update(updatePush, Wrappers.lambdaUpdate(AdminUpush.class).eq(AdminUpush::getUpushId, adminUpush.getUpushId()));
        } catch (Exception e) {
            updatePush.setErrorMsg(e.getMessage());
            updatePush.setUpdatedAt(DateUtil.getNowTime());
            adminUpushMapper.update(updatePush, Wrappers.lambdaUpdate(AdminUpush.class).eq(AdminUpush::getUpushId, adminUpush.getUpushId()));
            e.printStackTrace();
        }

    }
}
