package com.wecloud.im.friend.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.friend.param.*;
import com.wecloud.im.friend.service.ImFriendService;
import com.wecloud.im.sdk.enums.FriendStateEnum;
import com.wecloud.im.service.ImClientService;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.controller.BaseController;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import io.geekidea.springbootplus.framework.log.annotation.OperationLog;
import io.geekidea.springbootplus.framework.log.enums.OperationLogType;
import io.geekidea.springbootplus.framework.shiro.util.SecurityUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

/**
 * @author lixiaozhong
 * 好友与好友推荐相关接口
 */
@Slf4j
@RestController
@RequestMapping("/friend")
@Api(value = "好友与好友推荐相关API", tags = {"好友关系"})
public class ImFriendController extends BaseController {

    @Autowired
    private ImFriendService imFriendService;

    @Autowired
    private ImClientService imClientService;

    /**
     * 查询好友信息，只有自己的好友才查得到
     */
    @PostMapping("/info")
    @ApiOperation(value = "查询好友信息，只有自己的好友才查得到")
    public ApiResult<ImFriendApplyDto> getFriendInfo(@RequestBody ImFriendBaseParam param) {
        log.info("查询好友信息入参 {}", JSON.toJSONString(param));
        if(param == null) {
            return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, null);
        }
        ImClient currentClient = imClientService.getCurrentClient();
        if(currentClient == null) {
            return ApiResult.fail(ApiCode.CLIENT_NOT_FOUNT, null);
        }
        ImClient friendClient = imClientService.getCacheImClient(currentClient.getFkAppid(), param.getFriendClientId());
        if(friendClient == null) {
            return ApiResult.fail(ApiCode.CLIENT_NOT_FOUNT, null);
        }
        ImFriendApplyDto friendInfo = imFriendService.getFriendInfo(currentClient.getClientId(), friendClient.getClientId());
        return ApiResult.ok(friendInfo);
    }

    /**
     * 申请添加好友
     */
    @PostMapping("/apply")
    @ApiOperation(value = "申请添加好友")
    public ApiResult<Boolean> applyFriend(@RequestBody ImFriendApplyParam param) {
        log.info("申请添加好友入参 {}", JSON.toJSONString(param));
        if(param == null) {
            return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, null);
        }
        ImClient currentClient = imClientService.getCurrentClient();
        // 判断是否为vip
        Boolean isVip = getIsVip(currentClient);
        if(currentClient == null) {
            return ApiResult.fail(ApiCode.CLIENT_NOT_FOUNT, null);
        }
        ImClient friendClient = imClientService.getCacheImClient(currentClient.getFkAppid(), param.getFriendClientId());
        if (friendClient == null) {
            return ApiResult.fail(ApiCode.CLIENT_NOT_FOUNT, null);
        }
        if (currentClient.getId().equals(friendClient.getId())) {
            return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, null);
        }
        if (param.getAddFriendScene().equals("STRANGER")){
            List<ImFriendBaseDto> friends = imFriendService.getFriends(currentClient);
            if (isVip){
                // 是vip
                if (friends.size()>=10){
                    throw new BusinessException("vip最多只能加10个好友");
                }
            }else {
                // 不是vip
                if (friends.size()>=500){
                    throw new BusinessException("非vip最多只能加500个好友");
                }
            }
        }
        imFriendService.applyFriend(currentClient, friendClient, param.getFriendName(), param.getRequestRemark());
        log.info("申请添加好友逻辑完成");
        return ApiResult.ok();
    }


    /**
     * 申请添加好友
     */
    @PostMapping("/sdk/apply")
    @ApiOperation(value = "申请添加好友 sdk用")
    public ApiResult<Boolean> applyFriendSdk(@RequestBody ImFriendApplyParam param) {
        log.info("申请添加好友入参 {}", JSON.toJSONString(param));
        if (param == null) {
            return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, null);
        }
        ImClient currentClient = imClientService.getCacheImClient(SecurityUtils.getCurrentAppId(), param.getClientId());
        if (currentClient == null) {
            return ApiResult.fail(ApiCode.CLIENT_NOT_FOUNT, null);
        }
        ImClient friendClient = imClientService.getCacheImClient(SecurityUtils.getCurrentAppId(), param.getFriendClientId());
        if (friendClient == null) {
            return ApiResult.fail(ApiCode.CLIENT_NOT_FOUNT, null);
        }
        if (currentClient.getId().equals(friendClient.getId())) {
            return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, null);
        }
        Boolean isVip = getIsVip(currentClient);
        if (param.getAddFriendScene().equals("STRANGER")){
            List<ImFriendBaseDto> friends = imFriendService.getFriends(currentClient);
            if (isVip){
                // 是vip
                if (friends.size()>=10){
                    throw new BusinessException("vip最多只能加10个好友");
                }
            }else {
                // 不是vip
                if (friends.size()>=500){
                    throw new BusinessException("非vip最多只能加500个好友");
                }
            }
        }
        imFriendService.applyFriend(currentClient, friendClient, param.getFriendName(), param.getRequestRemark());
        if (!param.getNeedVerify()) {
            imFriendService.approveFriend(friendClient, currentClient, true, "");
        }
        log.info("申请添加好友逻辑完成");
        return ApiResult.ok();
    }

    private Boolean getIsVip(ImClient currentClient) {
        String senderAttributesStr = currentClient.getAttributes();
        JSONObject senderAttributes = new JSONObject();
        if (StringUtils.isNotBlank(senderAttributesStr)) {
            try {
                senderAttributes = JSONObject.parseObject(senderAttributesStr);
            } catch (Exception e) {
                // do nothing is ok
            }
        }
        boolean isVip = Optional.ofNullable(senderAttributes.getBoolean("isVip")).orElse(Boolean.FALSE);
        return isVip;
    }

    /**
     * 待接受的好友请求列表，最多只返回1000个
     */
    @PostMapping("/unsureFriends")
    @ApiOperation(value = "待接受的好友请求列表，最多只返回1000个")
    public ApiResult<List<ImFriendApplyDto>> getUnsureFriends() {
        ImClient currentClient = imClientService.getCurrentClient();
        if (currentClient == null) {
            return ApiResult.fail(ApiCode.CLIENT_NOT_FOUNT, null);
        }
        List<ImFriendApplyDto> friendInfo = imFriendService.getApplyFriends(currentClient);
        return ApiResult.ok(friendInfo);
    }

    /**
     * 好友请求列表，最多只返回1000个 sdk使用
     */
    @GetMapping("/sdk/unsureFriends")
    @ApiOperation(value = "获取好友请求列表，最多只返回1000个")
    public ApiResult<List<ImFriendApplyDto>> getUnsureFriendsSdk(@RequestParam("userId") String clientId) {
        log.info("获取好友请求列表入参 {}", clientId);
        Long appId = SecurityUtils.getCurrentAppId();
        ImClient imClient = imClientService.getCacheImClient(appId, clientId);
        List<ImFriendApplyDto> applyFriends = imFriendService.getApplyFriends(imClient);
        return ApiResult.ok(applyFriends);
    }

    /**
     * 查询好友信息，只有自己的好友才查得到 sdk
     */
    @GetMapping("/sdk/info")
    @ApiOperation(value = "查询好友信息，只有自己的好友才查得到")
    public ApiResult<ImFriendApplyDto> getFriendInfoSdk(@RequestBody ImFriendBaseParam param) {
        if (param == null) {
            return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, null);
        }
        Long appId = SecurityUtils.getCurrentAppId();
        ImClient imClient = imClientService.getCacheImClient(appId, param.getClientId());
        return ApiResult.ok(imFriendService.getFriendInfo(imClient.getClientId(), param.getFriendClientId()));
    }

    /**
     * 全量获取好友列表 sdk使用
     * @Author luozh
     * @Date 2022年04月22日 11:28:44
     * @param
     * @Return
     */
    @GetMapping("/sdk/getFriends")
    @ApiOperation(value = "全量获取好友列表")
    public ApiResult<List<ImFriendBaseDto>> getFriendsSdk(@RequestParam("userId") String clientId) {
        Long appId = SecurityUtils.getCurrentAppId();
        ImClient imClient = imClientService.getCacheImClient(appId, clientId);
        return ApiResult.ok(imFriendService.getFriends(imClient));
    }


    /**
     * 接受/拒绝好友申请
     */
    @PostMapping("/approve")
    @ApiOperation(value = "接受/拒绝好友申请")
    public ApiResult<Boolean> approveFriend(@RequestBody ImFriendApproveParam param) {
        log.info("接受/拒绝好友申请入参 {}", JSON.toJSONString(param));
        if (param == null || param.getAgree() == null) {
            return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, null);
        }
        ImClient currentClient = imClientService.getCurrentClient();
        if(currentClient == null) {
            return ApiResult.fail(ApiCode.CLIENT_NOT_FOUNT, null);
        }
        ImClient friendClient = imClientService.getCacheImClient(currentClient.getFkAppid(), param.getFriendClientId());
        if(friendClient == null) {
            return ApiResult.fail(ApiCode.CLIENT_NOT_FOUNT, null);
        }

        boolean ok = imFriendService.approveFriend(currentClient, friendClient, param.getAgree(), param.getRejectRemark());
        return ApiResult.ok(ok);
    }


    /**
     * 批量删除好友
     */
    @PostMapping("/batchDelete")
    @ApiOperation(value = "删除好友")
    public ApiResult<Boolean> batchDeleteFriend(@RequestBody ImDeleteFriendParam param) {
        log.info("删除好友入参 {}", JSON.toJSONString(param));
        ImClient currentClient = imClientService.getCurrentClient();
        if (currentClient == null) {
            return ApiResult.fail(ApiCode.CLIENT_NOT_FOUNT, null);
        }

        imFriendService.batchDeleteFriend(currentClient, param.getFriendClientIds());
        return ApiResult.ok();
    }

    /**
     * 批量删除好友 sdk用
     */
    @PostMapping("/sdk/unfriends")
    @ApiOperation(value = "删除好友")
    public ApiResult<Boolean> unfriends(@RequestBody UnfriendParam param) {
        log.info("删除好友入参 {}", JSON.toJSONString(param));
        if (StringUtils.isBlank(param.getUserId())) {
            throw new BusinessException("参数userId不能为空");
        }
        if (StringUtils.isBlank(param.getFriendUserIds())) {
            throw new BusinessException("参数friendUserIds不能为空");
        }
        imFriendService.unfriends(param);
        return ApiResult.ok();
    }

    /**
     * 好友备注
     * @Author luozh
     * @Date 2022年05月16日 11:07:53
     * @param param
     * @Return
     */
    @PostMapping("/sdk/remark")
    @ApiOperation(value = "备注")
    public ApiResult<Boolean> remark(@RequestBody FriendRemarkParam param) {
        log.info("备注好友入参 {}", JSON.toJSONString(param));
        if (StringUtils.isBlank(param.getUserId())) {
            throw new BusinessException("参数userId不能为空");
        }
        if (StringUtils.isBlank(param.getFriendUserId())) {
            throw new BusinessException("参数friendUserId不能为空");
        }
        imFriendService.remark(param);
        return ApiResult.ok();
    }

    /**
     * 好友分页列表
     */
    @PostMapping("/getPageList")
    @OperationLog(name = "好友分页列表", type = OperationLogType.PAGE)
    @ApiOperation(value = "好友分页列表")
    public ApiResult<Paging<ImFriendBaseDto>> getImFriendPageList(@RequestBody ImFriendPageParam pageParam) {
        log.info("好友分页列表入参 {}", JSON.toJSONString(pageParam));
        ImClient currentClient = imClientService.getCurrentClient();
        if(currentClient == null) {
            return ApiResult.fail(ApiCode.CLIENT_NOT_FOUNT, null);
        }

        Paging<ImFriendBaseDto> friends = imFriendService.getImFriendPageList(currentClient.getClientId(), pageParam);
        return ApiResult.ok(friends);
    }

    /**
     * 批量创建好友推荐
     */
    @PostMapping("/recommend/batchCreate")
    @OperationLog(name = "批量创建好友推荐", type = OperationLogType.PAGE)
    @ApiOperation(value = "批量创建好友推荐")
    public ApiResult<Boolean> batchCreateRecommend(@RequestBody ImCreateRecommendParam param) {
        log.info("批量创建好友推荐入参 {}", JSON.toJSONString(param));
        ImClient currentClient = imClientService.getCurrentClient();
        if(currentClient == null) {
            return ApiResult.fail(ApiCode.CLIENT_NOT_FOUNT, null);
        }
        if(CollectionUtils.isEmpty(param.getRecommendFriends())) {
            return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, null);
        }
        for (ImFriendRecommendDto p : param.getRecommendFriends()) {
            if (BaseEnum.valueOf(FriendStateEnum.class, p.getSource()) == null) {
                return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, null);
            }
        }
        imFriendService.batchCreateRecommend(currentClient, param.getRecommendFriends());
        return ApiResult.ok();
    }

    /**
     * 好友推荐分页列表
     */
    @PostMapping("/recommend/getPageList")
    @OperationLog(name = "好友推荐分页列表", type = OperationLogType.PAGE)
    @ApiOperation(value = "好友推荐分页列表")
    public ApiResult<Paging<ImFriendRecommendDto>> getImFriendRecommendPageList(@RequestBody ImFriendPageParam pageParam) {
        log.info("好友推荐分页列表入参 {}", JSON.toJSONString(pageParam));
        ImClient currentClient = imClientService.getCurrentClient();
        if(currentClient == null) {
            return ApiResult.fail(ApiCode.CLIENT_NOT_FOUNT, null);
        }
        Paging<ImFriendRecommendDto> res = imFriendService.getImFriendRecommendPageList(currentClient.getId(), pageParam);
        return ApiResult.ok(res);

    }

    /**
     * 批量删除好友推荐
     */
    @PostMapping("/recommend/batchDelete")
    @ApiOperation(value = "删除好友推荐")
    public ApiResult<Boolean> batchDeleteRecommend(@RequestBody ImDeleteRecommendParam param) {
        log.info("删除好友推荐入参 {}", JSON.toJSONString(param));
        ImClient currentClient = imClientService.getCurrentClient();
        if(currentClient == null) {
            return ApiResult.fail(ApiCode.CLIENT_NOT_FOUNT, null);
        }
        imFriendService.batchDeleteRecommend(currentClient, param.getFriendClientIds());
        return ApiResult.ok();
    }
}

