package com.wecloud.im.friend.service;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.enums.FriendStateEnum;
import com.wecloud.im.friend.entity.ImFriend;
import com.wecloud.im.friend.entity.ImFriendRecommend;
import com.wecloud.im.friend.mapper.ImFriendMapper;
import com.wecloud.im.friend.mapper.ImFriendRecommendMapper;
import com.wecloud.im.friend.param.ImFriendApplyDto;
import com.wecloud.im.friend.param.ImFriendBaseDto;
import com.wecloud.im.friend.param.ImFriendPageParam;
import com.wecloud.im.friend.param.ImFriendRecommendDto;
import com.wecloud.im.param.ImClientSimpleDto;
import com.wecloud.im.service.ImClientService;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import io.geekidea.springbootplus.framework.core.pagination.PageInfo;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import io.geekidea.springbootplus.framework.shiro.util.SnowflakeUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Description 好友关系处理逻辑
 * @Author lixiaozhong
 * @Date 2022/1/12 11:49 上午
 */
@Service
public class ImFriendService extends BaseServiceImpl<ImFriendMapper, ImFriend> {

    @Autowired
    private ImClientService imClientService;

    @Autowired
    private ImFriendMapper imFriendMapper;

    @Autowired
    private ImFriendRecommendMapper imFriendRecommendMapper;

    /**
     * 查看朋友详情
     * @param curentClientId
     * @param friendClientId
     * @return
     */
    public ImFriendApplyDto getFriendInfo(Long curentClientId, Long friendClientId) {
        return imFriendMapper.getFriendInfo(curentClientId, friendClientId);
    }

    /**
     * 获取待验证的好友列表
     * @param currentClient
     * @return
     */
    public List<ImFriendApplyDto> getUnsureFriends(ImClient currentClient) {
        ImFriendPageParam pageParam = new ImFriendPageParam();
        pageParam.setPageSize(1000L);
        Page<ImFriendApplyDto> page = new PageInfo(pageParam, OrderItem.desc(getLambdaColumn(ImFriend::getCreateTime)));
        IPage<ImFriendApplyDto> pageList = imFriendMapper.getUnsureFriendPageList(page, currentClient.getId());
        return pageList.getRecords();
    }

    /**
     * 好友申请
     * @param currentClient
     * @param friendClient
     * @param friendName
     * @param requestRemark
     * @return
     */
    @Transactional
    public Boolean applyFriend(ImClient currentClient,ImClient friendClient, String friendName, String requestRemark) {
        //好友关系有维护两条，我和他，他和我
        ImFriend my = new ImFriend();
        my.setFkClientId(currentClient.getId());
        my.setFkClientIdFriend(friendClient.getId());
        my.setFkClientIdClaimer(currentClient.getId());
        my.setFriendName(friendName);
        my.setRequestRemark(requestRemark);
        my.setState(FriendStateEnum.UNSURE.getCode());
        if(getByKey(currentClient.getId(), friendClient.getId()) != null) {
            if(StringUtils.isNotEmpty(requestRemark)) {
                my.setRequestRemark(requestRemark);
            }
            if(StringUtils.isNotEmpty(friendName)) {
                my.setFriendName(friendName);
            }
            this.updateByKeyAndClaimer(my);
        } else {
            my.setId(SnowflakeUtil.getId());
            my.setCreateTime(new Date());
            this.save(my);
        }

        ImFriend friend = new ImFriend();
        friend.setFkClientId(friendClient.getId());
        friend.setFkClientIdFriend(currentClient.getId());
        friend.setFkClientIdClaimer(currentClient.getId());
        friend.setRequestRemark(requestRemark);
        friend.setState(FriendStateEnum.UNSURE.getCode());
        if(getByKey(friendClient.getId(), currentClient.getId()) != null) {
            if(StringUtils.isNotEmpty(requestRemark)) {
                friend.setRequestRemark(requestRemark);
            }
            if(StringUtils.isNotEmpty(friendName)) {
                friend.setFriendName(friendName);
            }
            this.updateByKeyAndClaimer(friend);
        } else {
            friend.setId(SnowflakeUtil.getId());
            friend.setCreateTime(new Date());
            this.save(friend);
        }

        //既然申请好友了，就删除好友推荐
        this.batchDeleteRecommend(currentClient, Collections.singletonList(friendClient.getClientId()));
        this.batchDeleteRecommend(friendClient, Collections.singletonList(currentClient.getClientId()));

        return true;
    }

    /**
     * 根据 自己id和好友id查询好友信息
     * @param clientId
     * @param friendClientId
     * @return
     */
    public ImFriend getByKey(Long clientId, Long friendClientId) {
        return this.getOne(new QueryWrapper<ImFriend>().lambda()
                .eq(ImFriend::getFkClientId, clientId)
                .eq(ImFriend::getFkClientIdFriend, friendClientId));
    }

    /**
     * 根据 自己id和好友id，以及申请者id，更新好友信息
     * @param imFriend
     */
    public void updateByKeyAndClaimer(ImFriend imFriend) {
        // 不更新id
        imFriend.setId(null);
        imFriend.setCreateTime(null);
        this.update(imFriend, new QueryWrapper<ImFriend>().lambda()
                .eq(ImFriend::getFkClientId, imFriend.getFkClientId())
                .eq(ImFriend::getFkClientIdFriend, imFriend.getFkClientIdFriend())
                .eq(ImFriend::getFkClientIdClaimer, imFriend.getFkClientIdClaimer()));
    }

    /**
     * 好友通过/拒绝
     * @param currentClientId
     * @param friendClientId
     * @param agree
     * @param rejectRemark
     */
    @Transactional
    public void approveFriend(Long currentClientId, Long friendClientId, Boolean agree, String rejectRemark) {
        if(BooleanUtils.isTrue(agree)) {
            rejectRemark = null;
        }
        //好友关系有维护两条，我和他，他和我
        //好友的先更新
        ImFriend friend = new ImFriend();
        friend.setFkClientId(friendClientId);
        friend.setFkClientIdFriend(currentClientId);
        friend.setFkClientIdClaimer(friendClientId);
        friend.setState(BooleanUtils.isTrue(agree) ? FriendStateEnum.CONFORM.getCode() : FriendStateEnum.REJECT.getCode());
        if(StringUtils.isNotEmpty(rejectRemark)) {
            friend.setRejectRemark(rejectRemark);
        }
        this.updateByKeyAndClaimer(friend);
        // 同时更新我的
        ImFriend my = new ImFriend();
        my.setFkClientId(currentClientId);
        my.setFkClientIdFriend(friendClientId);
        my.setFkClientIdClaimer(friendClientId);
        my.setState(BooleanUtils.isTrue(agree) ? FriendStateEnum.CONFORM.getCode() : FriendStateEnum.REJECT.getCode());
        if(StringUtils.isNotEmpty(rejectRemark)) {
            my.setRejectRemark(rejectRemark);
        }
        this.updateByKeyAndClaimer(my);
    }

    public void batchDeleteFriend(ImClient currentClient, List<String> friendClientIds) {
        if(CollectionUtils.isEmpty(friendClientIds)) {
            return;
        }
        imFriendMapper.batchDeleteFriend(currentClient.getId(), currentClient.getFkAppid(), friendClientIds);
    }

    public Paging<ImFriendBaseDto> getImFriendPageList(Long currentClientId, ImFriendPageParam pageParam) {
        Page<ImFriendBaseDto> page = new PageInfo(pageParam, OrderItem.desc(getLambdaColumn(ImFriend::getFriendName)));
        IPage<ImFriendBaseDto> pageList = imFriendMapper.getImFriendPageList(page, currentClientId);
        return new Paging<>(pageList);
    }

    public Paging<ImFriendRecommendDto> getImFriendRecommendPageList(Long currentClientId, ImFriendPageParam pageParam) {
        Page<ImFriendRecommendDto> page = new PageInfo(pageParam, OrderItem.desc(getLambdaColumn(ImFriend::getCreateTime)));
        IPage<ImFriendRecommendDto> pageList = imFriendRecommendMapper.getImFriendRecommendPageList(page, currentClientId);
        return new Paging<>(pageList);
    }

    public void batchDeleteRecommend(ImClient currentClient, List<String> friendClientIds) {
        if(CollectionUtils.isEmpty(friendClientIds)) {
            return;
        }
        imFriendRecommendMapper.batchDeleteRecommend(currentClient.getId(), currentClient.getFkAppid(), friendClientIds);
    }

    /**
     * 批量创建好友推荐
     * @param currentClient
     * @param recommendFriends
     */
    public void batchCreateRecommend(ImClient currentClient, List<ImFriendRecommendDto> recommendFriends) {
        // 自己不推荐给自己
        List<ImFriendRecommendDto> friends = recommendFriends.stream().filter(p -> !currentClient.getClientId().equals(p.getFriendClientId())).collect(Collectors.toList());
        List<String> friendClientIds = friends.stream().map(ImFriendRecommendDto::getFriendClientId).collect(Collectors.toList());
        // 批量获取clientId 对应的内表 id主键
        List<ImClientSimpleDto> simpleFriendClients = imClientService.getSimpleClients(currentClient.getFkAppid(), friendClientIds);
        if(CollectionUtils.isEmpty(simpleFriendClients)) {
            return;
        }
        //对已经存在的好友过滤掉
        List<Long> maybeFriendIds = simpleFriendClients.stream().map(ImClientSimpleDto::getId).collect(Collectors.toList());
        List<Long> alreadyFriendIds = imFriendMapper.filterNegativeFriends(currentClient.getId(), maybeFriendIds);

        Map<String, Long> friendIdMap = simpleFriendClients.stream().collect(Collectors.toMap(ImClientSimpleDto::getClientId,
                ImClientSimpleDto::getId, (a, b) -> a));

        List<ImFriendRecommend> list = new ArrayList<>();
        for (ImFriendRecommendDto p : friends) {
            Long fkFriendCliendId = friendIdMap.get(p.getFriendClientId());
            // 只有client存在的数据才是真数据
            if(fkFriendCliendId == null) {
                continue;
            }
            // 如果推荐的人已经是好友，则忽略。
            if (alreadyFriendIds.contains(fkFriendCliendId)) {
                continue;
            }
            ImFriendRecommend recommend = new ImFriendRecommend();
            recommend.setId(SnowflakeUtil.getId());
            recommend.setFkClientId(currentClient.getId());

            recommend.setFkClientIdFriend(fkFriendCliendId);
            recommend.setSource(p.getSource());
            recommend.setDelFlag(false);
            list.add(recommend);
        }
        if(CollectionUtils.isEmpty(list)) {
            return;
        }
        // 如果数据重复，只会更新updateTime
        imFriendRecommendMapper.batchCreateRecommend(list);
    }
}
