package com.lantone.security.facade;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.lantone.security.dto.GetHospitalTreeDTO;
import com.lantone.security.dto.GetHospitalUserPageDTO;
import com.lantone.security.dto.GetMyNoticeListDTO;
import com.lantone.security.dto.GetNoticeInfoByIdDTO;
import com.lantone.security.dto.ListManagePageDTO;
import com.lantone.common.dto.SendToTopicDTO;
import com.lantone.common.enums.IsDeleteEnum;
import com.lantone.common.enums.StatusEnum;
import com.lantone.common.exception.Asserts;
import com.lantone.common.util.DateUtil;
import com.lantone.common.util.ListUtil;
import com.lantone.common.util.StringUtil;
import com.lantone.common.util.SysUserUtils;
import com.lantone.security.vo.AddNoticeVO;
import com.lantone.security.vo.GetHospitalUserVO;
import com.lantone.security.vo.GetMyNoticeListVO;
import com.lantone.security.vo.ListManagePageVO;
import com.lantone.security.entity.Dept;
import com.lantone.security.entity.HospitalUser;
import com.lantone.security.entity.Notice;
import com.lantone.security.entity.NoticeUser;
import com.lantone.security.entity.User;
import com.lantone.security.facade.base.DeptFacade;
import com.lantone.security.facade.base.DeptUserFacade;
import com.lantone.security.facade.base.DictionaryInfoFacade;
import com.lantone.security.facade.base.HospitalFacade;
import com.lantone.security.facade.base.HospitalUserFacade;
import com.lantone.security.facade.base.NoticeFacade;
import com.lantone.security.facade.base.NoticeUserFacade;
import com.lantone.security.facade.base.UserFacade;
import com.lantone.security.service.impl.NoticeUserServiceImpl;
import com.lantone.security.enums.DictionaryEnum;
import com.lantone.security.enums.ReadTypeEnum;
import com.lantone.security.enums.ReceiveTypeEnum;
import com.lantone.security.enums.ReturnTypeEnum;
import com.lantone.security.client.MessageService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Description: 站内通知管理-业务处理类
 * @author: songxl
 * @time: 2021/9/10 13:39
 */
@Component
public class NoticeManagementFacade {
    @Autowired
    private NoticeUserFacade noticeUserFacade;
    @Autowired
    private UserFacade userFacade;
    @Autowired
    private NoticeFacade noticeFacade;
    @Autowired
    private HospitalFacade hospitalFacade;
    @Autowired
    private HospitalUserFacade hospitalUserFacade;
    @Autowired
    private DeptUserFacade deptUserFacade;
    @Autowired
    private DeptFacade deptFacade;
    @Autowired
    private DictionaryInfoFacade dictionaryInfoFacade;
    @Autowired
    private MessageService messageService;

    /**
     * @param getMyNoticeListVO
     * @Description我的通知列表页
     * @Return com.baomidou.mybatisplus.core.metadata.IPage<com.lantone.security.dto.GetMyNoticeListDTO>
     */
    public IPage<GetMyNoticeListDTO> listPage(GetMyNoticeListVO getMyNoticeListVO) {
        getMyNoticeListVO.setId(SysUserUtils.getCurrentPrincipleId());
        getMyNoticeListVO.setHospitalId(SysUserUtils.getCurrentHospitalId());
        return noticeUserFacade.getBaseMapper().listPage(getMyNoticeListVO);
    }

    /**
     * @param listManagePageVO
     * @Description通知管理列表页
     * @Return com.baomidou.mybatisplus.core.metadata.IPage<com.lantone.security.dto.GetMyNoticeListDTO>
     */
    public IPage<ListManagePageDTO> listManagePage(ListManagePageVO listManagePageVO) {
        listManagePageVO.setId(SysUserUtils.getCurrentPrincipleId());
        return noticeFacade.getBaseMapper().listPage(listManagePageVO);
    }

    /**
     * @param addNoticeVO
     * @Description添加通知
     * @Return java.lang.Boolean
     */
    public Boolean add(AddNoticeVO addNoticeVO) {
        addNoticeVO.setCreator(SysUserUtils.getCurrentPrincipleId());
        User user = userFacade.getById(SysUserUtils.getCurrentPrincipleId());
        if (user != null) {
            addNoticeVO.setCreatorName(user.getName());
        }
        Notice notice = new Notice();
        BeanUtils.copyProperties(addNoticeVO, notice);
        notice.setCreator(SysUserUtils.getCurrentPrincipleId() + "");
        notice.setGmtCreate(DateUtil.now());
        //根据通知类型查询通知用户
        Set<HospitalUser> hospitalUsers = new HashSet<>();
        if (ReceiveTypeEnum.ALL.getKey().equals(addNoticeVO.getReceiveType())) {
            //获取当前登录用户管理的医院
            List<Long> hospitals = hospitalFacade.getBaseMapper()
                    .getHospitalTreeInfo(SysUserUtils.getCurrentHospitalId(), StatusEnum.Enable.getKey()).stream()
                    .map(GetHospitalTreeDTO::getHospitalId).collect(Collectors.toList());
            //获取这些组织的用户
            getUserByHospitals(hospitals, hospitalUsers);
        } else if (ReceiveTypeEnum.CUSTOM.getKey().equals(addNoticeVO.getReceiveType())) {
            if (ListUtil.isEmpty(addNoticeVO.getSendHospitals()) &&
                    ListUtil.isEmpty(addNoticeVO.getSendDepts()) &&
                    ListUtil.isEmpty(addNoticeVO.getSendUsers())) {
                Asserts.fail("选择发送的用户为空~");
            }
            //获取通知的医院-转成用户
            if (ListUtil.isNotEmpty(addNoticeVO.getSendHospitals())) {
                getUserByHospitals(addNoticeVO.getSendHospitals(), hospitalUsers);
            }
            //获取通知的科室-转成用户
            if (ListUtil.isNotEmpty(addNoticeVO.getSendDepts())) {
                getUserByDepts(addNoticeVO.getSendDepts(), hospitalUsers);
            }
            if (ListUtil.isNotEmpty(addNoticeVO.getSendUsers())) {
                try {
                    addNoticeVO.getSendUsers().stream().forEach(temp -> {
                        if (StringUtil.isNotBlank(temp) && temp.contains("-")) {
                            HospitalUser hospitaluser = new HospitalUser();
                            hospitaluser.setHospitalId(Long.parseLong(temp.split("-")[0]));
                            hospitaluser.setUserId(Long.parseLong(temp.split("-")[1]));
                            hospitalUsers.add(hospitaluser);
                        }
                    });
                } catch (Exception e) {

                }
            }
        } else {
            Asserts.fail("接收类型不存在，请检查重新输入~");
        }
        if (hospitalUsers.isEmpty()) {
            Asserts.fail("通知用户为空，请联系管理员~");
        }
        if (noticeFacade.save(notice)) {
            //发送通知
            return sendNotice(hospitalUsers, notice.getId());
        }
        return false;
    }

    /**
     * @param hospitalUsers
     * @param id
     * @Description发送通知
     * @Return java.lang.Boolean
     */
    private Boolean sendNotice(Set<HospitalUser> hospitalUsers, Long id) {
        List<NoticeUser> noticeUsers = new ArrayList<>();
        List<SendToTopicDTO> sendToTopics = new ArrayList<>();
        hospitalUsers.stream().forEach(hospitalUser -> {
            NoticeUser noticeUser = new NoticeUser();
            noticeUser.setHospitalId(hospitalUser.getHospitalId());
            noticeUser.setUserId(hospitalUser.getUserId());
            noticeUser.setNoticeId(id);
            noticeUsers.add(noticeUser);
            SendToTopicDTO sendToTopicDTO = new SendToTopicDTO();
            sendToTopicDTO.setMessage("+1");
            sendToTopicDTO.setType("count");
            sendToTopicDTO.setTopic(hospitalUser.getHospitalId() + "-" + hospitalUser.getUserId() + "");
            sendToTopics.add(sendToTopicDTO);
        });
        messageService.sendToTopic(sendToTopics);
        return new NoticeUserServiceImpl().saveBatch(noticeUsers);
    }

    /**
     * @param hospitals
     * @param hospitalUsers
     * @Description获取医院的用户
     * @Return void
     */
    private void getUserByHospitals(List<Long> hospitals, Set<HospitalUser> hospitalUsers) {

        if (ListUtil.isEmpty(hospitals)) {
            Asserts.fail("当前管理员发送通知的组织集合为空，请联系管理员~");
        }
        //获取该医院的用户
        Set<HospitalUser> tempUsers = hospitalUserFacade.list(new QueryWrapper<HospitalUser>()
                .eq("is_deleted", IsDeleteEnum.N.getKey())
                .in("hospital_id", hospitals)).stream().collect(Collectors.toSet());
        if (tempUsers != null && tempUsers.size()>0) {
            hospitalUsers.addAll(tempUsers);
        }
        //获取医院的科室
        List<Long> tempDepts = deptFacade.list(new QueryWrapper<Dept>()
                .eq("is_deleted", IsDeleteEnum.N.getKey())
                .in("hospital_id", hospitals)).stream().map(Dept::getId).collect(Collectors.toList());
        if (ListUtil.isNotEmpty(tempDepts)) {
            getUserByDepts(tempDepts, hospitalUsers);
        }
    }

    /**
     * @param depts
     * @param hospitalUsers
     * @Description获取科室的用户
     * @Return void
     */
    private void getUserByDepts(List<Long> depts, Set<HospitalUser> hospitalUsers) {
        if (ListUtil.isEmpty(depts)) {
            Asserts.fail("当前管理员发送通知的组织集合为空，请联系管理员~");
        }
        //获取该医院的用户
        hospitalUsers.addAll(deptUserFacade.getBaseMapper().getDeptUser(depts).stream().collect(Collectors.toSet()));
    }

    /**
     * @param id
     * @param type
     * @Description获取通知详情
     * @Return com.lantone.security.dto.GetNoticeInfoByIdDTO
     */
    public GetNoticeInfoByIdDTO getNoticeInfoById(Long id, String type) {

        GetNoticeInfoByIdDTO getNoticeInfoByIdDTO = new GetNoticeInfoByIdDTO();
        //获取字典类型
        Map<String, String> noticeType = dictionaryInfoFacade.getOneDicMap(ReturnTypeEnum.INTERFACE.getKey(),
                DictionaryEnum.NOTICE_TYPE.getKey() + "");
        Notice notice = noticeFacade.getById(id);
        if (notice == null) {
            Asserts.fail("通知不存在，请联系管理员~");
        }
        BeanUtils.copyProperties(notice, getNoticeInfoByIdDTO);
        getNoticeInfoByIdDTO.setTypeName(noticeType.get(getNoticeInfoByIdDTO.getType()));
        //我的通知点击查看要更新通知状态为已读
        if ("1".equals(type)) {
            if (!noticeUserFacade.update(new UpdateWrapper<NoticeUser>()
                    .set("status", ReadTypeEnum.READ.getKey())
                    .eq("user_id", SysUserUtils.getCurrentPrincipleId())
                    .eq("is_deleted", IsDeleteEnum.N.getKey())
                    .eq("notice_id", notice.getId()))) {
                Asserts.fail("通知已读状态更新失败，请联系管理员~");
            }
        }
        return getNoticeInfoByIdDTO;
    }

    /**
     * @param id
     * @Description删除通知
     * @Return boolean
     */
    public boolean deleteNoticeInfo(Long id) {
        if (noticeFacade.update(new UpdateWrapper<Notice>()
                .set("is_deleted", IsDeleteEnum.Y.getKey())
                .eq("id", id)
                .eq("is_deleted", IsDeleteEnum.N.getKey()))) {
            return noticeUserFacade.update(new UpdateWrapper<NoticeUser>()
                    .set("is_deleted", IsDeleteEnum.Y.getKey())
                    .in("notice_id", id)
                    .eq("is_deleted", IsDeleteEnum.N.getKey()));

        }
        return false;
    }

    /**
     * @param
     * @Description获取未读信息数量
     * @Return java.lang.Integer
     */
    public Map<String, Integer> getNotNoticeCount() {
        Map<String, Integer> out = new HashMap<>();
        out.put("count", noticeUserFacade.count(new QueryWrapper<NoticeUser>()
                .eq("hospital_id", SysUserUtils.getCurrentHospitalId())
                .eq("user_id", SysUserUtils.getCurrentPrincipleId())
                .eq("status", ReadTypeEnum.NOT_READ.getKey())
                .eq("is_deleted", IsDeleteEnum.N.getKey())));
        return out;
    }

    /**
     * @param getHospitalUserVO
     * @Description获取用户列表
     * @Return com.baomidou.mybatisplus.core.metadata.IPage<com.lantone.security.dto.GetHospitalUserPageDTO>
     */
    public IPage<GetHospitalUserPageDTO> getHospitalUser(GetHospitalUserVO getHospitalUserVO) {
        return hospitalUserFacade.getBaseMapper().getHospitalUser(getHospitalUserVO);
    }
}