package com.flossom.miniProgram.service.impl;

import com.flossom.common.core.domain.entity.*;
import com.flossom.common.core.enums.SiteOpenTypeEnum;
import com.flossom.common.core.enums.SitePushTypeEnum;
import com.flossom.common.core.enums.SiteTypeEnum;
import com.flossom.common.core.enums.TagTypeStatusEnum;
import com.flossom.common.core.exception.ServiceException;
import com.flossom.common.core.mapper.*;
import com.flossom.common.core.utils.DateUtils;
import com.flossom.common.core.utils.StringUtils;
import com.flossom.common.security.utils.SecurityUtils;
import com.flossom.miniProgram.service.ISiteInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class SiteInfoServiceImpl implements ISiteInfoService {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private SiteInfoMapper siteInfoMapper;

    @Autowired
    private SiteLogMapper siteLogMapper;

    @Autowired
    private WxUserTagMapper wxUserTagMapper;

    @Autowired
    private SiteInfoTagMapper siteInfoTagMapper;

    @Autowired
    private SysTagMapper sysTagMapper;


    @Override
    public List<SiteInfo> popupList(Integer openType) {
        SiteOpenTypeEnum openTypeEnum = SiteOpenTypeEnum.getOpenType(openType);
        if (openTypeEnum == null) {
            logger.error("获取弹窗失败：openType值为 {}", openType);
            throw new ServiceException("获取弹窗失败");
        }

        SiteInfo siteInfo = new SiteInfo();
        // 站点类型
        siteInfo.setSiteType(SiteTypeEnum.POPUP_LIST.getCode());
        // 弹窗类型
        siteInfo.setOpenType(openTypeEnum.getCode());
        // 开启的数据
        siteInfo.setOperate(1);
        List<SiteInfo> siteInfos = siteInfoMapper.selectSiteInfoList(siteInfo);
        if (siteInfos != null && siteInfos.size() > 0) {
            return filterSite(siteInfos);
        }
        return null;
    }

    @Override
    public List<SiteInfo> carousel() {
        SiteInfo siteInfo = new SiteInfo();
        // 站点类型
        siteInfo.setSiteType(SiteTypeEnum.CAROUSEL_LIST.getCode());
        // 开启的数据
        siteInfo.setOperate(1);
        List<SiteInfo> siteInfos = siteInfoMapper.selectSiteInfoList(siteInfo);
        if (siteInfos != null && siteInfos.size() > 0) {
            return filterSite(siteInfos);
        }
        return null;
    }

    @Override
    public void addTag(Long siteInfoId) {
        SiteInfoTag siteInfoTag = new SiteInfoTag();
        siteInfoTag.setSiteId(siteInfoId);
        // 小程序标签
        siteInfoTag.setTagType(TagTypeStatusEnum.MINI_PROGRAM.getCode());
        siteInfoTag.setStatus(2L);
        List<SiteInfoTag> addMiniTagList = siteInfoTagMapper.selectSiteInfoTagList(siteInfoTag);
        if (addMiniTagList != null && addMiniTagList.size() > 0) {
            List<Integer> tagIdList = addMiniTagList.stream().map(SiteInfoTag::getTagId).map(Long::intValue).collect(Collectors.toList());
            List<Integer> userIdList = Arrays.asList(SecurityUtils.getLoginUser().getWxUserMember().getId()).stream().map(Long::intValue).collect(Collectors.toList());
            batchAddTag(tagIdList, userIdList, TagTypeStatusEnum.MINI_PROGRAM.getCode());
        }
        // 外部标签
        siteInfoTag.setTagType(TagTypeStatusEnum.ENTERPRISE_WECHAT.getCode());
        siteInfoTag.setStatus(2L);
        List<SiteInfoTag> addWecomTagList = siteInfoTagMapper.selectSiteInfoTagList(siteInfoTag);
        if (addWecomTagList != null && addWecomTagList.size() > 0) {
            List<Integer> tagIdList = addWecomTagList.stream().map(SiteInfoTag::getTagId).map(Long::intValue).collect(Collectors.toList());
            List<Integer> userIdList = Arrays.asList(SecurityUtils.getLoginUser().getWxUserMember().getId()).stream().map(Long::intValue).collect(Collectors.toList());
            batchAddTag(tagIdList, userIdList, TagTypeStatusEnum.ENTERPRISE_WECHAT.getCode());
        }

    }

    /**
     * 批量添加标签
     * code 标签类型 {@link TagTypeStatusEnum}
     *
     * @param tagIdList
     * @param userIdList
     */
    public void batchAddTag(List<Integer> tagIdList, List<Integer> userIdList, Integer code) {
        // 对单个标签操作
        for (Integer tagId : tagIdList) {
            SysTag sysTag = sysTagMapper.selectDeptById(tagId.longValue());
            if (sysTag != null) {
                List<Integer> needAddIdList = new ArrayList<>();
                // 1、查询该标签下，有那些用户关联
                List<Integer> existedUserList = wxUserTagMapper.selectWxUserTagByTagId(tagId, code);
                Iterator<Integer> iterator = userIdList.iterator();
                while (iterator.hasNext()) {
                    Integer element = iterator.next();
                    if (!existedUserList.contains(element)) {
                        needAddIdList.add(element);
                    }
                }

                // 2、添加用户与标签的关联
                List<WxUserTag> list = new ArrayList<>();
                WxUserTag wxUserTag;
                if (needAddIdList != null && needAddIdList.size() > 0) {
                    for (Integer userId : needAddIdList) {
                        wxUserTag = new WxUserTag(null, userId.longValue(), sysTag.getTagName(), tagId.longValue(), code, null);
                        wxUserTag.setCreateTime(DateUtils.getNowDate());
                        list.add(wxUserTag);
                    }
                    wxUserTagMapper.insertBatch(list);
                }
            }
        }
        // TODO: 对接数赢：批量添加小程序标签
    }

    /**
     * 根据 条件做过滤
     *
     * @param siteInfos
     * @return
     */
    private List<SiteInfo> filterSite(List<SiteInfo> siteInfos) {
        /* 获取用户拥有的小程序标签和外部标签 */
        List<Long> userMiniTageIdList = new ArrayList<>();
        List<Long> userWecomTageIdList = new ArrayList<>();
        WxUserMember wxUserMember = SecurityUtils.getLoginUser().getWxUserMember();
        WxUserTag wxUserTag = new WxUserTag();
        wxUserTag.setUserId(wxUserMember.getId());
        wxUserTag.setType(TagTypeStatusEnum.MINI_PROGRAM.getCode());
        // 用户拥有的小程序标签
        List<WxUserTag> userMiniProgramTags = wxUserTagMapper.selectWxUserTagList(wxUserTag);
        if (userMiniProgramTags != null && userMiniProgramTags.size() > 0) {
            userMiniTageIdList = userMiniProgramTags.stream().map(WxUserTag::getTagId).collect(Collectors.toList());
        }
        wxUserTag.setType(TagTypeStatusEnum.ENTERPRISE_WECHAT.getCode());
        // 用户拥有的外部标签
        List<WxUserTag> userWecomTags = wxUserTagMapper.selectWxUserTagList(wxUserTag);
        if (userWecomTags != null && userWecomTags.size() > 0) {
            userWecomTageIdList = userWecomTags.stream().map(WxUserTag::getTagId).collect(Collectors.toList());
        }

        /* 开始判断 */
        List<SiteInfo> resultList = new ArrayList<>();
        for (SiteInfo info : siteInfos) {
            /* 1、开启结束时间判定 */
            Date siteStartTime = info.getSiteStartTime();
            Date siteEndTime = info.getSiteEndTime();
            if (siteStartTime != null && siteEndTime != null) {
                LocalDateTime startTime = LocalDateTime.ofInstant(siteStartTime.toInstant(), ZoneId.systemDefault());
                LocalDateTime endTime = LocalDateTime.ofInstant(siteEndTime.toInstant(), ZoneId.systemDefault());
                LocalDateTime now = LocalDateTime.now();
                // 不在时间范围内
                if (!(now.isAfter(startTime) && now.isBefore(endTime))) {
                    continue;
                }
            }

            /* 2、投放用户注册时间 */
            Date registerStartTime = info.getUserRegisterStartTime();
            Date registerEndTime = info.getUserRegisterEndTime();
            if (registerStartTime != null && registerEndTime != null) {
                LocalDateTime startTime = LocalDateTime.ofInstant(registerStartTime.toInstant(), ZoneId.systemDefault());
                LocalDateTime endTime = LocalDateTime.ofInstant(registerEndTime.toInstant(), ZoneId.systemDefault());
                LocalDateTime now = LocalDateTime.now();
                // 不在时间范围内
                if (!(now.isAfter(startTime) && now.isBefore(endTime))) {
                    continue;
                }
            }

            /* 3、可见用户类型 */
            Integer userType = info.getUserType();
            // 可见用户类型 0-全部 1-游客 2-会员
            if (userType != 0) {
                Integer loginUserType = SecurityUtils.getLoginUser().getWxUserMember().getUserType();
                // 当用户类型为游客
                if (loginUserType== null || loginUserType == 0) {
                    if (userType != 1) {
                        continue;
                    }
                }
                // 当用户类型为会员
                if (loginUserType == 1) {
                    if (userType != 2) {
                        continue;
                    }
                }
            }

            /* 4、弹窗标签判断 */
            // 4.2、禁止标签
            SiteInfoTag siteInfoTag = new SiteInfoTag();
            siteInfoTag.setSiteId(info.getId());
            siteInfoTag.setStatus(1L);
            List<SiteInfoTag> forbidSiteInfoTags = siteInfoTagMapper.selectSiteInfoTagList(siteInfoTag);
            if (forbidSiteInfoTags != null && forbidSiteInfoTags.size() > 0) {
                List<Long> forbidTagIdList = forbidSiteInfoTags.stream().map(SiteInfoTag::getTagId).collect(Collectors.toList());
                if (userMiniTageIdList.size() > 0) {
                    boolean isContinue = false;
                    for (Long tagid : userMiniTageIdList) {
                        if (forbidTagIdList.contains(tagid)) {
                            isContinue = true;
                            break;
                        }
                    }
                    if(isContinue){
                        continue;
                    }
                }
                if (userWecomTageIdList.size() > 0) {
                    boolean isContinue = false;
                    for (Long tagid : userWecomTageIdList) {
                        if (forbidTagIdList.contains(tagid)) {
                            isContinue = true;
                            break;
                        }
                    }
                    if(isContinue){
                        continue;
                    }
                }
            }

            // 4.4、可见小程序标签
            siteInfoTag.setSiteId(info.getId());
            siteInfoTag.setTagType(TagTypeStatusEnum.MINI_PROGRAM.getCode());
            siteInfoTag.setStatus(0L);
            List<SiteInfoTag> showWechatSiteInfoTags = siteInfoTagMapper.selectSiteInfoTagList(siteInfoTag);
            if (showWechatSiteInfoTags != null && showWechatSiteInfoTags.size() > 0) {
                List<Long> showWechatTagIdList = showWechatSiteInfoTags.stream().map(SiteInfoTag::getTagId).collect(Collectors.toList());
                if (userMiniTageIdList == null || !userMiniTageIdList.containsAll(showWechatTagIdList)) {
                    continue;
                }
            }
            // 4.5、可见外部标签
            siteInfoTag.setSiteId(info.getId());
            siteInfoTag.setTagType(TagTypeStatusEnum.ENTERPRISE_WECHAT.getCode());
            siteInfoTag.setStatus(0L);
            List<SiteInfoTag> showCompanySiteInfoTags = siteInfoTagMapper.selectSiteInfoTagList(siteInfoTag);
            if (showCompanySiteInfoTags != null && showCompanySiteInfoTags.size() > 0) {
                List<Long> showCompanyTagIdList = showCompanySiteInfoTags.stream().map(SiteInfoTag::getTagId).collect(Collectors.toList());
                if (userWecomTageIdList == null || !userWecomTageIdList.containsAll(showCompanyTagIdList)) {
                    continue;
                }
            }

            /* 5、推送频次 */
            Integer pushType = info.getPushType();
            if (info.getPushType() != null) {
                // 5.1、每次进入：每次页面刷新则展示，不用做判断
                // 5.2、一次
                if (SitePushTypeEnum.ONE.getCode() == pushType) {
                    SiteLog siteLog = new SiteLog();
                    siteLog.setUserId(SecurityUtils.getLoginUser().getWxUserMember().getId());
                    siteLog.setSiteId(info.getId());
                    List<SiteLog> siteLogs = siteLogMapper.selectSiteLogList(siteLog);
                    if (siteLogs != null && siteLogs.size() > 0) {
                        continue;
                    }
                }
                // 自定义
                if (SitePushTypeEnum.CUSTOM.getCode() == pushType) {
                    // 判断当前日期的星期是否在规定范围内
                    String pushTimer = info.getPushTimer();
                    if (StringUtils.isNotBlank(pushTimer)) {
                        List<Integer> weekList = Arrays.asList(pushTimer.split(",")).stream().map(Integer::valueOf).collect(Collectors.toList());
                        Calendar calendar = Calendar.getInstance();
                        // 获取当前星期几（1表示周日，2表示周一，依此类推）
                        int week = calendar.get(Calendar.DAY_OF_WEEK);
                        if (!weekList.contains(week)) {
                            // 不包含
                            continue;
                        }
                        // 在规定的星期内，判断观看次数是否达标了
                        SiteLog siteLog = new SiteLog();
                        siteLog.setUserId(SecurityUtils.getLoginUser().getWxUserMember().getId());
                        siteLog.setSiteId(info.getId());
                        LocalDateTime now = LocalDateTime.now();
                        siteLog.getParams().put("beginTime", LocalDateTime.of(now.toLocalDate(), LocalTime.MIN));
                        siteLog.getParams().put("endTime", LocalDateTime.of(now.toLocalDate(), LocalTime.MAX));
                        List<SiteLog> siteLogs = siteLogMapper.selectSiteLogList(siteLog);
                        if (siteLogs != null && siteLogs.size() >= info.getPushNumber()) {
                            continue;
                        }
                    }
                }
            }

            /**
             * TODO: 打卡多少次可见
             */

            /**
             * TODO: 关联仪器
             */

            // 最终符合条件
            resultList.add(info);

            // 添加观看日志
            if (resultList != null && resultList.size() > 0) {
                for (SiteInfo siteInfo : resultList) {
                    SiteLog siteLog = new SiteLog();
                    siteLog.setUserId(SecurityUtils.getLoginUser().getWxUserMember().getId());
                    siteLog.setSiteId(siteInfo.getId());
                    siteLog.setCreateTime(DateUtils.getNowDate());
                    siteLogMapper.insertSiteLog(siteLog);
                }
            }
        }
        return resultList;
    }

}
