package com.yida.data.school.letter.service.impl;

import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.tokenizer.Result;
import cn.hutool.extra.tokenizer.TokenizerEngine;
import cn.hutool.extra.tokenizer.TokenizerUtil;
import cn.hutool.extra.tokenizer.Word;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vdurmont.emoji.EmojiManager;
import com.vdurmont.emoji.EmojiParser;
import com.yida.data.common.core.common.ResultBean;
import com.yida.data.common.core.entity.CurrentUser;
import com.yida.data.common.core.entity.constant.AppConstant;
import com.yida.data.common.core.entity.customform.CoreCustomFormRelationAdmin;
import com.yida.data.common.core.entity.letter.EduLetterBox;
import com.yida.data.common.core.entity.letter.EduLetterBoxReplyPerson;
import com.yida.data.common.core.entity.notice.qywx.BaseStaffNotice;
import com.yida.data.common.core.entity.letter.EduLetterBoxReplyPerson;
import com.yida.data.common.core.entity.notice.qywx.TextSchoolNotice;
import com.yida.data.common.core.entity.notice.qywx.inside.Text;
import com.yida.data.common.core.entity.system.Dept;
import com.yida.data.common.core.entity.system.EduApp;
import com.yida.data.common.core.utils.Asserts;
import com.yida.data.common.core.utils.FebsUtil;
import com.yida.data.common.core.utils.FebsUtil;
import com.yida.data.common.core.entity.user.EduStaff;
import com.yida.data.common.core.utils.Asserts;
import com.yida.data.common.core.utils.FebsUtil;
import com.yida.data.common.core.utils.WxUtil;
import com.yida.data.common.core.vo.NameValueVO;
import com.yida.data.common.service.CommonService;
import com.yida.data.school.dto.letterbox.LetterBoxDTO;
import com.yida.data.school.letter.mapper.EduLetterBoxMapper;
import com.yida.data.school.letter.service.EduLetterBoxReplyPersonService;
import com.yida.data.school.letter.service.EduLetterBoxConfigService;
import com.yida.data.school.letter.service.EduLetterBoxReplyPersonService;
import com.yida.data.school.letter.service.EduLetterBoxService;
import com.yida.data.user.feign.RemoteStaffService;
import com.yida.data.school.vo.letterbox.StaLetterVO;
import com.yida.data.system.feign.RemoteDeptService;
import com.yida.data.user.feign.RemoteStudentService;

import java.time.LocalDate;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;

import javax.annotation.Resource;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;

import static com.yida.data.common.core.entity.constant.CachePrefixConstant.STAFF_DATA;

/**
 * 信箱表（仅查看） Service实现
 *
 * @author zhanghaijun
 * @date 2021-07-20 10:55:41
 */
@RefreshScope
@Service
@RequiredArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class EduLetterBoxServiceImpl extends ServiceImpl<EduLetterBoxMapper, EduLetterBox> implements EduLetterBoxService {

    private final EduLetterBoxMapper eduLetterBoxMapper;
    private final RemoteDeptService remoteDeptService;

    @Value("${febs.parentLetterUrl}")
    private String parentLetterUrl;

    @Value("${febs.teacherLetterUrl}")
    private String teacherLetterUrl;

    @Resource
    private RemoteStudentService remoteStudentService;

    @Resource
    private CommonService commonService;

    @Resource
    private WxUtil wxUtil;

    @Resource
    private RedisService redisService;


    @Resource
    private RemoteStaffService staffService;


    @Resource
    private EduLetterBoxReplyPersonService personService;


    @Override
    public List<EduLetterBox> findListViewLetter(EduLetterBox letterBox) {
        return eduLetterBoxMapper.findListViewLetter(letterBox);
    }

    @Override
    public IPage<EduLetterBox> findList(Page page, String title, Long schoolId, String contentType, String appPhone,
                                        Integer reply) {

        IPage<EduLetterBox> list = baseMapper.findListPage(page, title, schoolId, contentType, appPhone, reply);
        if (CollUtil.isNotEmpty(list.getRecords())) {
            for (EduLetterBox record : list.getRecords()) {
                record.setContent(EmojiParser.parseToUnicode(record.getContent()));
            }
        }
        return list;
    }

    @Override
    public IPage<EduLetterBox> findViewList(Page page, String title, Long schoolId, Long identityId, Integer viewsNum) {
        IPage<EduLetterBox> list = eduLetterBoxMapper.findViewList(page, title, schoolId, identityId, viewsNum);
        if (CollUtil.isNotEmpty(list.getRecords())) {
            for (EduLetterBox record : list.getRecords()) {
                record.setContent(EmojiParser.parseToUnicode(record.getContent()));
            }
        }
        return list;
    }

    @Override
    public void listReplyLetter(LetterBoxDTO letterBoxDTO, Collection<EduLetterBox> eduLetterBoxes, CurrentUser currentUser) {
        ArrayList<String> phoneList = new ArrayList<>();
        for (EduLetterBox eduLetterBox : eduLetterBoxes) {
            eduLetterBox.setReply(1);
            eduLetterBox.setReplyDate(LocalDateTime.now());
            eduLetterBox.setReplyContent(letterBoxDTO.getReplyContent());
            eduLetterBox.setReplyId(String.valueOf(currentUser.getUserId()));
            eduLetterBox.setReplyName(currentUser.getUsername());
            if (StrUtil.isNotBlank(eduLetterBox.getContent())) {
                eduLetterBox.setContent(EmojiParser.parseToAliases(eduLetterBox.getContent()));
            }
            phoneList.add(eduLetterBox.getAppPhone());
        }
        saveOrUpdateBatch(eduLetterBoxes);

        Dept school = commonService.getDept(letterBoxDTO.getSchoolId());
        //微信的学校则发送消息
        if (school.getSchoolType().contains(Dept.TYPE_QYWX)) {

            EduApp appByCodeAndSchool = commonService
                    .getAppByCodeAndSchool(AppConstant.INDEX_PARENT, null, letterBoxDTO.getSchoolId());
            TextSchoolNotice textSchoolNotice = new TextSchoolNotice();
            Text text = new Text();
            textSchoolNotice.setText(text);
            textSchoolNotice.setAgentid(appByCodeAndSchool.getWxAgentId());
            List<String> wxId = remoteStudentService.getParentByPhoneAndSchoolId(phoneList, letterBoxDTO.getSchoolId()).getData();

            for (String s : wxId) {
                for (EduLetterBox eduLetterBox : eduLetterBoxes) {
                    ArrayList<String> list = new ArrayList<>();
                    list.add(s);
                    String url =
                            parentLetterUrl + appByCodeAndSchool.getWxCorpId() + "#/view?id=" + eduLetterBox.getId();
                    text.setContent(
                            "【校长信箱】回信通知：亲爱的家长，您在" + eduLetterBox.getCreateDate().toLocalDate() + "投递的信件已被回复，请<a href='" + url
                                    + "'>点击此处</a>前往查看。");
                    textSchoolNotice.setTo_parent_userid(list);
                    String accessToken = wxUtil
                            .getAccessToken(appByCodeAndSchool.getWxCorpId(), appByCodeAndSchool.getWxSecret());
                    wxUtil.pushSchoolNotice(accessToken, textSchoolNotice);
                }
            }
        }
    }

    @Override
    public void submitReplyLetter(EduLetterBox eduLetterBox) {
        ArrayList<String> phoneList = new ArrayList<>();
        phoneList.add(eduLetterBox.getAppPhone());
        eduLetterBox.setReply(1);
        eduLetterBox.setReplyDate(LocalDateTime.now());
        if (StrUtil.isNotBlank(eduLetterBox.getContent())) {
            eduLetterBox.setContent(EmojiParser.parseToAliases(eduLetterBox.getContent()));
        }
        baseMapper.updateById(eduLetterBox);
        Dept school = commonService.getDept(eduLetterBox.getSchoolId());
        if (school.getSchoolType().contains(Dept.TYPE_QYWX)) {
            EduApp appByCodeAndSchool = commonService
                    .getAppByCodeAndSchool(AppConstant.INDEX_PARENT, null, eduLetterBox.getSchoolId());
            TextSchoolNotice textSchoolNotice = new TextSchoolNotice();
            Text text = new Text();
            textSchoolNotice.setText(text);
            textSchoolNotice.setAgentid(appByCodeAndSchool.getWxAgentId());
            List<String> wxId = remoteStudentService.getParentByPhoneAndSchoolId(phoneList, eduLetterBox.getSchoolId()).getData();

            String url =
                    parentLetterUrl + appByCodeAndSchool.getWxCorpId() + "#/view?id=" + eduLetterBox.getId();
            for (String s : wxId) {
                ArrayList<String> list = new ArrayList<>();
                list.add(s);
                text.setContent("【校长信箱】回信通知：亲爱的家长，您在" + eduLetterBox.getCreateDate().toLocalDate() + "投递的信件已被回复，请<a href='" + url
                        + "'>点击此处</a>前往查看。");
                textSchoolNotice.setTo_parent_userid(list);
                String accessToken = wxUtil.getAccessToken(appByCodeAndSchool.getWxCorpId(), appByCodeAndSchool.getWxSecret());
                wxUtil.pushSchoolNotice(accessToken, textSchoolNotice);
            }
        }
    }

    /**
     * 点赞
     *
     * @param letterId 信箱id
     * @param status   0为有用，1为没用
     * @param userId   用户id
     */
    @Override
    public void upOrDownLetter(Integer letterId, Integer status, Long userId, Integer type) {
        //点赞
        if (type == 0) {
            //有用
            if (status == 0) {
                if (redisService.hasKey(AppConstant.INDEX_PARENT + letterId.toString())) {
                    List<Long> list = new ArrayList<>();
                    List<Object> userList = redisService.lGet(AppConstant.INDEX_PARENT + letterId, 0L, -1L);
                    for (Object o : userList) {
                        String id = String.valueOf(o);
                        list.add(Long.valueOf(id));
                    }
                    list.add(userId);
                    redisService.llSet(AppConstant.INDEX_PARENT + letterId, list);
                } else {
                    List<Long> userList = new ArrayList<>();
                    userList.add(userId);
                    redisService.llSet(AppConstant.INDEX_PARENT + letterId, userList);
                }
            }
            //没用
            else if (status == 1) {
                if (redisService.hasKey(AppConstant.INDEX_PARENT + "d" + letterId.toString())) {
                    List<Long> list = new ArrayList<>();
                    List<Object> userList = redisService.lGet(AppConstant.INDEX_PARENT + "d" + letterId, 0L, -1L);
                    for (Object o : userList) {
                        String id = String.valueOf(o);
                        list.add(Long.valueOf(id));
                    }
                    list.add(userId);
                    redisService.llSet(AppConstant.INDEX_PARENT + "d" + letterId, list);
                } else {
                    List<Long> userList = new ArrayList<>();
                    userList.add(userId);
                    redisService.llSet(AppConstant.INDEX_PARENT + "d" + letterId, userList);
                }
            }
        }
        //取消点赞
        else {
            if (redisService.hasKey(AppConstant.INDEX_PARENT + "d" + letterId)) {
                List<Long> list = new ArrayList<>();
                List<Object> userList = redisService.lGet(AppConstant.INDEX_PARENT + "d" + letterId, 0L, -1L);
                for (Object o : userList) {
                    String id = String.valueOf(o);
                    list.add(Long.valueOf(id));
                }
                if (CollectionUtil.isNotEmpty(list)) {
                    list.remove(userId);
                }
                redisService.llSet(AppConstant.INDEX_PARENT + "d" + letterId, list);
            }

            if (redisService.hasKey(AppConstant.INDEX_PARENT + letterId.toString())) {
                List<Long> list = new ArrayList<>();
                List<Object> userList = redisService.lGet(AppConstant.INDEX_PARENT + letterId, 0L, -1L);
                if (CollectionUtil.isNotEmpty(userList)) {
                    for (Object o : userList) {
                        String id = String.valueOf(o);
                        list.add(Long.valueOf(id));
                    }
                    list.remove(userId);
                }
                redisService.llSet(AppConstant.INDEX_PARENT + letterId.toString(), list);
            }

        }


    }

    @Override
    public EduLetterBox getLetter(Integer id, Long userId) {
        EduLetterBox eduLetterBox = getById(id);
        // 处理浏览数
        eduLetterBox.setViews(Optional.ofNullable(eduLetterBox).map(obj -> obj.getViews()).orElse(0L) + 1);
        updateById(eduLetterBox);
        EduLetterBox eduLetterBox1 = getById(id);
        eduLetterBox.setResolutions(Optional.ofNullable(eduLetterBox1).map(obj -> obj.getResolutions()).orElse(0L) + 1);
        updateById(eduLetterBox1);
        eduLetterBox.setContent(EmojiParser.parseToUnicode(eduLetterBox.getContent()));
        return statisticsLetter(eduLetterBox, userId);
    }

    @Override
    public void addLetter(EduLetterBox eduLetterBox, CurrentUser currentUser) {

        eduLetterBox.setTitle(EmojiParser.removeAllEmojis(eduLetterBox.getTitle()));
        Asserts.isTrue(StrUtil.isNotBlank(eduLetterBox.getTitle()), "标题不能为空");
        eduLetterBox.setDelFlag(0);
        eduLetterBox.setSortDate(LocalDateTime.now());
        eduLetterBox.setContent(EmojiParser.parseToAliases(eduLetterBox.getContent()));
        if (ObjectUtil.isNotEmpty(currentUser)) {
            eduLetterBox.setAppHeader(currentUser.getAvatar());
            eduLetterBox.setAppName(currentUser.getNickname());
            eduLetterBox.setAppPhone(currentUser.getMobile());
        save(eduLetterBox);
            //具有回复权限的员工接收对应通知
            List<EduLetterBoxReplyPerson> replyPersonList = personService.list(Wrappers.query(new EduLetterBoxReplyPerson())
                    .lambda().eq(EduLetterBoxReplyPerson::getSchoolId, eduLetterBox.getSchoolId()));

            List<Long> staffIds = new ArrayList<>();
            for (EduLetterBoxReplyPerson replyPerson : replyPersonList) {
                staffIds.add(replyPerson.getUserId());
            }

            List<EduStaff> staffList = new ArrayList<>();

            for (Long staffId : staffIds) {
                if (redisService.hHasKey(staffId.toString(), STAFF_DATA)) {
                    EduStaff staff = (EduStaff) redisService.hget(staffId.toString(), STAFF_DATA);
                    staffList.add(staff);
                } else {
                    EduStaff staff = staffService.getStaff(staffId).getData();
                    staffList.add(staff);
                }

            }


            EduApp appByCodeAndSchool = commonService.getAppByCodeAndSchool(AppConstant.CONTACT_SELECT, null, eduLetterBox.getSchoolId());

            for (EduStaff staff : staffList) {
                if (ObjectUtil.isNotEmpty(staff)) {
                    BaseStaffNotice textSchoolNotice = new BaseStaffNotice();

                    Text text = new Text();
                    textSchoolNotice.setText(text);
                    textSchoolNotice.setAgentid(appByCodeAndSchool.getWxAgentId());

                    String url = teacherLetterUrl + appByCodeAndSchool.getWxCorpId() + "#/teacherView?id=" + eduLetterBox.getId();
                    text.setContent("<a href='" + url + "'> 有一个新的信件需要您回复，点击查看详情</a>");
                    textSchoolNotice.setTouser(staff.getWxId());
                    String accessToken = wxUtil.getAccessToken(appByCodeAndSchool.getWxCorpId(), appByCodeAndSchool.getWxSecret());
                    wxUtil.pushStaffNotice(accessToken, textSchoolNotice);
                }

            }
        }
    }

    /**
     * 统计点赞数据
     *
     * @param eduLetterBox 信件
     * @param userId       用户id
     * @return
     */
    public EduLetterBox statisticsLetter(EduLetterBox eduLetterBox, Long userId) {
        //没用数量
        if (redisService.hasKey(AppConstant.INDEX_PARENT + "d" + eduLetterBox.getId())) {
            List<Long> list = new ArrayList<>();
            List<Object> userList = redisService.lGet(AppConstant.INDEX_PARENT + "d" + eduLetterBox.getId(), 0L, -1L);
            for (Object o : userList) {
                String id = String.valueOf(o);
                list.add(Long.valueOf(id));
            }
            eduLetterBox.setDisLikeNum(list.size());
            //如果有则为没用了
            if (list.contains(userId)) {
                eduLetterBox.setLikeStatus(2);
            }
        } else {
            eduLetterBox.setDisLikeNum(0);
        }
        //有用数量
        if (redisService.hHasKey(eduLetterBox.getId().toString(), AppConstant.INDEX_PARENT)) {

            List<Long> list = new ArrayList<>();
            List<Object> userList = redisService.lGet(AppConstant.INDEX_PARENT + eduLetterBox.getId().toString(), 0L, -1L);
            for (Object o : userList) {
                String id = String.valueOf(o);
                list.add(Long.valueOf(id));
            }
            eduLetterBox.setLikeNum(list.size());
            //如果有则为点赞了
            if (list.contains(userId)) {
                eduLetterBox.setLikeStatus(1);
            }
        } else {
            eduLetterBox.setLikeNum(0);
        }
        //空就还没有点赞
        if (ObjectUtil.isEmpty(eduLetterBox.getLikeStatus())) {
            eduLetterBox.setLikeStatus(0);
        }
        return eduLetterBox;
    }

    @Override
    public StaLetterVO getStaData(LocalDate startDate, LocalDate endDate, List<Long> schoolIds) {
        if (CollUtil.isEmpty(schoolIds)) {
            schoolIds = Collections.singletonList(-1L);
        }
        return baseMapper.getStaData(schoolIds, startDate, endDate);
    }

    @Override
    public List titleCloud(String startDate, String endDate, List<Long> schoolIds) {
        Map<String, Integer> wordNumMap = new HashMap<>();
        if (CollUtil.isNotEmpty(schoolIds)) {
            List<String> titles = baseMapper.listTitle(schoolIds, startDate, endDate);
            for (String title : titles) {
                TokenizerEngine engine = TokenizerUtil.createEngine();
                Result result = engine.parse(title);
                for (Word word : result) {
                    if (!FebsUtil.containChinese(word.getText())) {
                        continue;
                    }
                    if (wordNumMap.containsKey(word.getText())) {
                        wordNumMap.put(word.getText(), wordNumMap.get(word.getText()) + 1);
                    } else {
                        wordNumMap.put(word.getText(), 1);
                    }
                }
            }
        }
        return wordNumMap.entrySet().stream().map(x -> {
            NameValueVO<String, Integer> vo = new NameValueVO();
            vo.setName(x.getKey());
            vo.setValue(x.getValue());
            return vo;
        }).sorted((x, y) -> y.getValue() - x.getValue()).limit(20).collect(Collectors.toList());
    }
}
