package com.tourism.webadmin.app.website.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tourism.common.additional.config.ApplicationConfig;
import com.tourism.common.additional.utils.StringUtils;
import com.tourism.common.additional.utils.UrlConvertUtils;
import com.tourism.common.core.object.MyRelationParam;
import com.tourism.common.core.object.ResponseResult;
import com.tourism.common.core.object.TokenData;
import com.tourism.common.core.util.MyModelUtil;
import com.tourism.webadmin.app.website.controller.SystemMessageController;
import com.tourism.webadmin.app.website.dto.*;
import com.tourism.webadmin.app.website.service.TourGroupService;
import com.tourism.webadmin.app.website.service.TourMemberService;
import com.tourism.webadmin.back.dao.TourImGroupMapper;
import com.tourism.webadmin.back.model.TourImGroup;
import com.tourism.webadmin.back.model.TourImGroupInvitation;
import com.tourism.webadmin.back.model.TourImMember;
import com.tourism.webadmin.back.model.TourUser;
import com.tourism.webadmin.back.model.constant.IsTrue;
import com.tourism.webadmin.back.model.constant.NoticeType;
import com.tourism.webadmin.back.service.TourImGroupInvitationService;
import com.tourism.webadmin.back.service.TourImGroupService;
import com.tourism.webadmin.back.service.TourImMemberService;
import com.tourism.webadmin.back.service.TourUserService;
import com.tourism.webadmin.back.vo.TourImGroupVo;
import com.tourism.webadmin.back.vo.TourImMemberVo;
import com.tourism.webadmin.enums.GroupRole;
import com.tourism.webadmin.enums.RedisLock;
import com.tourism.webadmin.ws.handle.SystemMessageHandler;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.socket.WebSocketSession;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Handler;
import java.util.stream.Collectors;

@Service
public class TourGroupServiceImpl extends ServiceImpl<TourImGroupMapper, TourImGroup> implements TourGroupService{

    @Autowired
    private TourUserService tourUserService;
    @Autowired
    private TourMemberService tourMemberService;
    @Autowired
    private TourImGroupService tourImGroupService;
    @Autowired
    private SystemMessageController systemMessageController;
    @Autowired
    private TourImMemberService tourImMemberService;
    @Autowired
    private TourImGroupInvitationService tourImGroupInvitationService;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private SystemMessageHandler systemMessageHandler;
    /**
     *  创建群聊
     * @param params
     */
    @Override
    @Transactional
    public Long createGroup(CreateGroupDto params) {
        TourImGroup group = new TourImGroup();
        //登录账号
        Long userId = TokenData.takeFromRequest().getUserId();

        TourUser creatUser = tourUserService.getById(userId);
        //创建人
        group.setCreateUserId(userId);
        //头像
        group.setGroupAvatar(params.getHeadImage());
        //群主
        group.setLeaderId(userId);

        ArrayList<Long> userIds = new ArrayList<>();
        userIds.add(userId);

        if("2".equals(params.getCreateType())){
            //拉人创建
            String s = params.getIds().size() > 1 ? "...(群聊)" : "";
            TourUser user = tourUserService.getById(params.getIds().get(0));
            group.setGroupName(creatUser.getShowName()+"、"+user.getShowName()+s);
            userIds.addAll(params.getIds());
            group.setNoticeType(2);
            group.setUpdateTime(new Date());
            group.setUpdateUserId(userId);
            save(group);
            Map<String, Map<String, WebSocketSession>> groupMap = systemMessageHandler.getGroupMap();
            groupMap.put(group.getId().toString(), new ConcurrentHashMap<String,WebSocketSession>());
            for (Long paramsId : userIds) {
                Map<String, WebSocketSession> sessionMap = systemMessageHandler.getSessionMap();
                if (sessionMap.containsKey(paramsId.toString())){
                    WebSocketSession webSocketSession = sessionMap.get(paramsId.toString());
                    Long groupId = group.getId();
                    if (groupMap.containsKey(groupId.toString())){
                        Map<String, WebSocketSession> webSocketSessionMap = groupMap.get(groupId.toString());
                        webSocketSessionMap.put(paramsId.toString(), webSocketSession);
                    }
                }
            }

        }else {
            //手动创建
            group.setGroupName(params.getGroupName());
            group.setDescription(params.getDescription());
            group.setBelongTypeId(params.getBelongTypeId());
            group.setIsPublic(params.getIsPublic());
            group.setNoticeType(2);
            group.setUpdateTime(new Date());
            group.setUpdateUserId(userId);
            save(group);
            Map<String, Map<String, WebSocketSession>> groupMap = systemMessageHandler.getGroupMap();
            groupMap.put(group.getId().toString(), new ConcurrentHashMap<String,WebSocketSession>());
                Map<String, WebSocketSession> sessionMap = systemMessageHandler.getSessionMap();
                if (sessionMap.containsKey(TokenData.takeFromRequest().getUserId().toString())){
                    WebSocketSession webSocketSession = sessionMap.get(TokenData.takeFromRequest().getUserId().toString());
                    Long groupId = group.getId();
                    if (groupMap.containsKey(groupId.toString())){
                        Map<String, WebSocketSession> webSocketSessionMap = groupMap.get(groupId.toString());
                        webSocketSessionMap.put(TokenData.takeFromRequest().getUserId().toString(), webSocketSession);
                    }
                }


        }
        addTourMember(userIds,group);
        return group.getId();
    }

    /**
     *  查询群聊全部管理员
     * @param groupId
     * @return {@link List }<{@link TourUser }>
     */
    @Override
    public List<TourUser> getAdmin(Long groupId) {
        TourImGroup byId = getById(groupId);
        if(byId==null)return null;
        ArrayList<TourUser> tourUsers = new ArrayList<>();
        //单聊
        if(byId.getNoticeType().equals(0)) return tourUsers;
        ArrayList<Integer> role = new ArrayList<>();
        //群主
        role.add(GroupRole.GROUP_LEADER.getCode());
        //管理员
        role.add(GroupRole.ADMINISTRATORS.getCode());
        List<TourImMember> list = tourMemberService.lambdaQuery().eq(TourImMember::getGroupId, groupId)
                .in(TourImMember::getGroupRole, role).eq(TourImMember::getDataState,1).list();
        List<Long> userIds = list.stream().map(TourImMember::getUserId).collect(Collectors.toList());
        return tourUserService.getBaseMapper().selectBatchIds(userIds);
    }

    /**
     *
     * 退出群聊
     * @param group
     */

    @Override
    @Transactional
    public void exitGroup(TourImGroup group) {
        Long userId = TokenData.takeFromRequest().getUserId();
        //群主解散群聊
        if(group.getLeaderId().equals(userId)){
            //用户=群主ID = 解散群聊
            group.setDataState(-1);
            updateById(group);
            //推送消息
            ArrayList<String> ids = new ArrayList<>();
            ids.add(group.getId().toString());
            Map<String, Set<TourUser>> userByGroupId = tourMemberService.getUserByGroupId(ids);

            Set<TourUser> tourUsers = userByGroupId.get(group.getId().toString());
            if(tourUsers.size()<=1)return;
            for (TourUser user : tourUsers) {
                if(user.getUserId().equals(userId)){
                    continue;
                }
                SystemMessageDTO systemMessageDTO = new SystemMessageDTO();
                //移除群成员
                systemMessageDTO.setNoticeType(3);
                systemMessageDTO.setMessageType(0);
                systemMessageDTO.setContent(group.getGroupName()+"群聊已经被解散");
                systemMessageDTO.setTitle("群通知");
                systemMessageDTO.setGetUserId(user.getUserId().toString());//接收人
                systemMessageDTO.setSendUserId(userId.toString());//处理人
                systemMessageDTO.setGroupId(userId.toString());//群ID
                systemMessageController.sendMessage(systemMessageDTO);
            }
            LambdaQueryWrapper<TourImMember> query = Wrappers.<TourImMember>lambdaQuery().eq(TourImMember::getGroupId, group.getId()).eq(TourImMember::getDataState, 1);
            TourImMember tourImMember = new TourImMember();
            tourImMember.setDataState(-1);
            tourImMemberService.update(tourImMember, query);
        }else {
            TourImMember one = tourMemberService.getOne(Wrappers.<TourImMember>lambdaQuery().eq(TourImMember::getGroupId, group.getId())
                    .eq(TourImMember::getUserId, userId).eq(TourImMember::getDataState,1));
            one.setDataState(-1);
            tourMemberService.updateById(one);
        }

    }

    /**
     * 修改群信息
     * @param groupDto
     */

    @Override
    public void updateGroup(UpdateGroupDto groupDto,TourImGroup group) {
        if (groupDto.getBelongTypeId()!=null) {
            //修改群类型
            group.setBelongTypeId(groupDto.getBelongTypeId());
        }
        if (groupDto.getGroupName()!=null) {
            //修改群名称
            group.setGroupName(groupDto.getGroupName());
        }
        if (groupDto.getGroupAvatar()!=null) {
            //修改群头像
            group.setGroupAvatar(groupDto.getGroupAvatar());
        }
        if (groupDto.getIsNeedConfirm()!=null) {
            //是否开启群验证
            group.setIsNeedConfirm(Integer.valueOf(groupDto.getIsNeedConfirm()));
        }
        if (groupDto.getIsPublic()!=null) {
            //是否开启群验证
            group.setIsPublic(groupDto.getIsPublic());
        }
        if(groupDto.getDescription()!=null){
            //群描述
            group.setDescription(groupDto.getDescription());
        }
        updateById(group);
    }

    /**新增会话*/
    @Transactional
    public void addTourMember(List<Long> userId, TourImGroup group) {
        ArrayList<TourImMember> tourImMembers = new ArrayList<>();
        //全部用户
        List<TourUser> tourUsers = tourUserService.getBaseMapper().selectBatchIds(userId);
        //遍历创建member对象
        for (Long l : userId) {
            TourImMember member = new TourImMember();
            member.setGroupId(group.getId());
            if(l.equals(group.getCreateUserId())){
                member.setGroupRole(GroupRole.GROUP_LEADER.getCode());
            }else {
                member.setGroupRole(GroupRole.ORDINARY_MEMBERS.getCode());
            }
            member.setUserId(l);
            member.setDataState(1);
            member.setUpdateTime(new Date());
            member.setUpdateUserId(group.getCreateUserId());
            member.setCreateUserId(group.getCreateUserId());
            tourImMembers.add(member);
        }
        tourMemberService.saveBatch(tourImMembers);
    }




    @Override
    public boolean applyIsPass(List<TourImGroupInvitation> list,String isPass,String groupId) {

        List<Long> ids = list.stream().map(TourImGroupInvitation::getId).collect(Collectors.toList());

        Long userId = TokenData.takeFromRequest().getUserId();

        LambdaQueryWrapper<TourImGroupInvitation> query = Wrappers.<TourImGroupInvitation>lambdaQuery().in(TourImGroupInvitation::getId, ids);

        if("2".equals(isPass)){
            //同意 生成tour_im_member
            pass(userId,groupId,list);
        }
        //修改状态
        TourImGroupInvitation update = new TourImGroupInvitation();
        update.setStatus(Integer.valueOf(isPass));
        update.setUpdateTime(new Date());
        update.setUpdateUserId(userId);
        tourImGroupInvitationService.update(update, query);
        return true;

    }

    /**
     * 是否是管理员
     * @param groupId
     * @param userId
     * @return boolean
     */

    @Override
    public boolean isAdmin(Long groupId, Long userId) {
        List<TourUser> admin = this.getAdmin(groupId);
        List<TourUser> collect = admin.stream().filter(tourUser -> tourUser.getUserId().equals(userId)).collect(Collectors.toList());
        //是否是管理员
        return !collect.isEmpty();
    }

    /**
     * 创建单项member
     * @param params
     */
    @Override
    @Transactional
    public String createMember(CreateMemberDto params) {
        //登录用户
        Long userId = TokenData.takeFromRequest().getUserId();
        //群聊ID
        String groupId = params.getGroupId();
        //接收人
        TourUser toUser = tourUserService.getById(params.getGetUserId());
        if (Objects.isNull(toUser)){
            return "接收人不存在";
        }
        //发送人
        TourUser fromUser = tourUserService.getById(userId);
        if (Objects.isNull(fromUser)){
            return "发送人不存在";
        }
        ArrayList<String> lockString = new ArrayList<>();
        lockString.add(toUser.getUserId().toString());
        lockString.add(fromUser.getUserId().toString());
        Collections.sort(lockString);//排序
        RLock[] locks=new RLock[lockString.size()];
        for (int i = 0; i < locks.length; i++) {
            String s = lockString.get(i);
            locks[i] = redissonClient.getFairLock(RedisLock.MEMBER_KEY+s);
        }
        RLock multiLock = redissonClient.getMultiLock(locks);
        try {
            if(multiLock.tryLock()){
                List<TourImMember> list = tourImMemberService.lambdaQuery().eq(TourImMember::getUserId, userId)
                        .eq(TourImMember::getPartnerId, params.getGetUserId())
                        .eq(TourImMember::getDataState, 1).list();

                if(!ObjectUtil.isEmpty(list)){
                    //之前已经有会话了
                    TourImGroup byId = getById(list.get(0).getGroupId());
                    //修改会话为显示
                    List<TourImMember> collect = list.stream().filter(item -> item.getGroupId().equals(byId.getId())&&item.getIsShow().equals(0)).collect(Collectors.toList());
                    collect.forEach(o->o.setIsShow(1));
                    tourMemberService.updateBatchById(collect);
                    //是否单聊
                    if(byId.getNoticeType()==1){
                        return list.get(0).getGroupId().toString();
                    }else {
                        return null;
                    }
                }
                TourImGroup byId = getById(groupId);
                if(ObjectUtil.isEmpty(byId)){
                    //创建group
                    TourImGroup group = new TourImGroup();
                    group.setId(Long.valueOf(groupId));
                    group.setLeaderId(userId);
                    group.setIsPublic(IsTrue.FALSE);
                    group.setGroupName(fromUser.getShowName() + "和" + toUser.getShowName()+"的单聊");
                    group.setCreateUserId(userId);
                    group.setCreateTime(new Date());
                    group.setUpdateUserId(userId);
                    group.setUpdateTime(new Date());
                    group.setNoticeType(params.getNoticeType());
                    save(group);
                    //之前没有创建会话 创建群聊和发送人的member
                    TourImMember tourImMember = new TourImMember();
                    tourImMember.setGroupId(group.getId());
                    tourImMember.setUserId(fromUser.getUserId());
                    tourImMember.setPartnerId(toUser.getUserId());

                    tourImMember.setCreateUserId(userId);
                    tourImMember.setCreateTime(new Date());
                    tourImMember.setUpdateUserId(userId);
                    tourImMember.setUpdateTime(new Date());
                    tourImMember.setGroupRole(GroupRole.GROUP_LEADER.getCode());
                    //保存Member
                    tourImMemberService.save(tourImMember);
                    groupId=group.getId().toString();
                    return groupId;
                }
            }
        }finally {
            multiLock.unlock();
        }
        return groupId;
    }

    /**
     *  通过
     */
    @Transactional
    public void pass(Long userId,String groupId,List<TourImGroupInvitation> list){
        TourImGroup group = tourImGroupService.getById(groupId);

        Set<Long> userIds = list.stream().map(TourImGroupInvitation::getInvitee).collect(Collectors.toSet());

        //查询用户信息
        List<TourUser> tourUsers = tourUserService.getBaseMapper().selectBatchIds(userIds);
        HashMap<Long, TourUser> map = new HashMap<>();
        for (TourUser tourUser : tourUsers) {
            map.put(tourUser.getUserId(),tourUser);
        }

        ArrayList<TourImMember> tourImMembers = new ArrayList<>();

        for (TourImGroupInvitation main : list) {
            //被要求人信息
            TourUser user = map.get(main.getInvitee());
            if(user!=null){
                //生成会话 tour_im_member
                TourImMember tourImMember = new TourImMember();
                //群聊ID
                tourImMember.setGroupId(group.getId());
                //用户ID
                tourImMember.setUserId(main.getInvitee());
                //群聊角色
                tourImMember.setGroupRole(GroupRole.ORDINARY_MEMBERS.getCode());

                Date now = new Date();
                tourImMember.setCreateUserId(userId);
                tourImMember.setCreateTime(now);
                tourImMember.setUpdateTime(now);
                tourImMember.setUpdateUserId(userId);
                tourImMembers.add(tourImMember);
            }

        }
        tourMemberService.saveBatch(tourImMembers);
    }

}
