package com.wecloud.im.sdk;

import java.net.URL;
import java.util.List;
import java.util.Map;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;

import com.wecloud.im.sdk.internal.WecloudImContactsOperation;
import com.wecloud.im.sdk.internal.WecloudImConversationOperation;
import com.wecloud.im.sdk.internal.WecloudImGroupOperation;
import com.wecloud.im.sdk.internal.WecloudImMessageOperation;
import com.wecloud.im.sdk.internal.WecloudImRtcRecordOperation;
import com.wecloud.im.sdk.internal.WecloudImSystemNotificationOperation;
import com.wecloud.im.sdk.internal.WecloudImUserOperation;
import com.wecloud.im.sdk.model.*;

/**
 *
 * @Author luozh
 * @Date 2022年04月13日 11:23:24
 * @Version 1.0
 */
public class WecloudImClient implements WecloudIm {

    /**
     * 请求地址
     */
    private URL apiDomain;

    /**
     * 蔚可云分配后台分配的appKey
     */
    private String appKey;

    /**
     * 蔚可云分配后台分配的appSecret
     */
    private String appSecret;

    /* The miscellaneous IM operations */
    private WecloudImUserOperation imUserOperation;

    private WecloudImConversationOperation imConversationOperation;

    private WecloudImMessageOperation imMessageOperation;

    private WecloudImGroupOperation imGroupOperation;

    private WecloudImContactsOperation imContactsOperation;

    private WecloudImRtcRecordOperation imRtcRecordOperation;

    private WecloudImSystemNotificationOperation imSystemNotificationOperation;

    public WecloudImClient(URL apiDomain, String appKey, String appSecret) {
        this.apiDomain = apiDomain;
        this.appKey = appKey;
        this.appSecret = appSecret;
        initOperations();
    }

    @Override
    public ImClient registerUser(String userId, String headPortrait, String nickname) {
        RegisterClientRequest registerClientRequest =
                RegisterClientRequest.builder()
                        .userId(userId).headPortrait(headPortrait)
                        .nickname(nickname)
                        .build();
        return imUserOperation.registerClient(registerClientRequest);
    }

    @Override
    public Token getToken(String userId, Integer deviceType) {
        ClientLoginRequest clientLoginRequest = ClientLoginRequest.builder().userId(userId).deviceType(deviceType).build();

        return imUserOperation.getToken(clientLoginRequest);
    }

    @Override
    public Boolean modifyUser(String userId, String nickname, String headPortrait) {
        ModifyUserRequest modifyUserRequest =
                ModifyUserRequest.builder().userId(userId).nickname(nickname).headPortrait(headPortrait).build();

        return imUserOperation.modifyUser(modifyUserRequest);
    }

    @Override
    public Attributes getUserAttributes(String userId) {
        GetUserAttributesRequest getUserAttributesRequest = GetUserAttributesRequest.builder().userId(userId).build();
        return imUserOperation.getUserAttributes(getUserAttributesRequest);
    }

    @Override
    public Boolean modifyUserAttributes(String userId, Attributes attributes) {
        ModifyUserAttributesRequest modifyUserAttributesRequest =
                ModifyUserAttributesRequest.builder().userId(userId).attributes(attributes).build();
        ;
        return imUserOperation.modifyUserAttributes(modifyUserAttributesRequest);
    }

    @Override
    public Boolean bannedUser(String userId, Integer minute) {
        BannedUserRequest bannedUserRequest = BannedUserRequest.builder().userId(userId).minute(minute).build();
        return imUserOperation.bannedUser(bannedUserRequest);
    }

    @Override
    public List<UnsureFriend> getUnsureFriends(String userId) {
        GetUnsureFriendsRequest getUnsureFriendsRequest = GetUnsureFriendsRequest.builder().userId(userId).build();

        return imContactsOperation.getUnsureFriends(getUnsureFriendsRequest);
    }


    @Override
    public List<Friend> getFriends(String userId) {
        GetFriendsRequest getFriendsRequest = GetFriendsRequest.builder().userId(userId).build();
        return imContactsOperation.getFriends(getFriendsRequest);
    }

    @Override
    public ClientRelation userRelation(String userId, String friendId) {
        UserRelationRequest userRelationRequest =
                UserRelationRequest.builder().userId(userId).friendUserId(friendId).build();
        return imUserOperation.userRelation(userRelationRequest);
    }

    @Override
    public List<ClientRelation> usersRelation(String userId, String friendIds) {
        UsersRelationRequest userRelationRequest =
                UsersRelationRequest.builder().userId(userId).friendUserIds(friendIds).build();
        return imUserOperation.usersRelation(userRelationRequest);
    }

    @Override
    public PageResult<Blacklist> pageBlacklist(Integer pageIndex, Integer pageSize, String userId) {
        PageBlacklistRequest pageBlacklistRequest =
                PageBlacklistRequest.builder().pageSize(pageSize).pageIndex(pageIndex).userId(userId).build();
        return imContactsOperation.pageBlacklist(pageBlacklistRequest);
    }

    @Override
    public Boolean friendRequest(String userId, String friendId, String friendName, String requestRemark) {
        FriendRequestRequest friendRequestRequest =
                FriendRequestRequest.builder().userId(userId).friendId(friendId).friendName(friendName).requestRemark(requestRemark).needVerify(true).build();
        return imContactsOperation.friendRequest(friendRequestRequest);
    }

    @Override
    public Boolean friendRequest(String userId, String friendId, String friendName, String requestRemark, Boolean needVerify) {
        FriendRequestRequest friendRequestRequest =
                FriendRequestRequest.builder().userId(userId).friendId(friendId).friendName(friendName).requestRemark(requestRemark).needVerify(needVerify).build();
        return imContactsOperation.friendRequest(friendRequestRequest);
    }

    @Override
    public Boolean groupMembersFriendRequest(Long conversationId, String userId, String friendId, String friendName, String requestRemark) {
        GroupMembersFriendRequestRequest groupMembersFriendRequestRequest =
                GroupMembersFriendRequestRequest.builder().conversationId(conversationId)
                        .userId(userId).friendId(friendId)
                        .friendName(friendName)
                        .requestRemark(requestRemark)
                        .needVerify(true)
                        .build();
        return imContactsOperation.groupMembersFriendRequest(groupMembersFriendRequestRequest);
    }

    @Override
    public Boolean groupMembersFriendRequest(Long conversationId, String userId, String friendId, String friendName, String requestRemark, Boolean needVerify) {
        GroupMembersFriendRequestRequest groupMembersFriendRequestRequest =
                GroupMembersFriendRequestRequest.builder().conversationId(conversationId)
                        .userId(userId).friendId(friendId)
                        .friendName(friendName)
                        .requestRemark(requestRemark)
                        .needVerify(needVerify)
                        .build();
        return imContactsOperation.groupMembersFriendRequest(groupMembersFriendRequestRequest);
    }

    @Override
    public List<ChatRoomMember> listChatRoomMember(Long chatRoomId) {
        ListChatRoomMemberRequest request = ListChatRoomMemberRequest.builder().chatRoomId(chatRoomId).build();
        return imUserOperation.listChatRoomMember(request);
    }

    @Override
    public Long createConversation(CreateConversation createConversation) {
        CreateConversationRequest request = CreateConversationRequest.builder()
                .name(createConversation.getName())
                .creatorUserId(createConversation.getCreatorUserId())
                .memberUserIds(createConversation.getMemberUserIds())
                .chatType(createConversation.getChatType())
                .attributes(createConversation.getAttributes())
                .build();
        return imConversationOperation.create(request);
    }

    @Override
    public List<Conversation> listConversation(Integer chatType, List<Long> conversationIds) {
        ListConversationRequest request = ListConversationRequest.builder().chatType(chatType)
                .conversationIds(conversationIds).build();
        return imConversationOperation.listConversation(request);
    }

    @Override
    public Boolean addOrModifyConversationAttribute(Long conversationId, Map<String, Object> attribute) {
        AddOrModifyConversationAttributeRequest request =
                AddOrModifyConversationAttributeRequest.builder()
                        .conversationId(conversationId)
                        .attribute(attribute)
                        .build();
        return imConversationOperation.addOrModifyConversationAttribute(request);
    }

    @Override
    public Boolean setConversationTop(String userId, Long conversationId, Boolean top) {
        SetConversationTopRequest setConversationTopRequest =
                SetConversationTopRequest.builder().userId(userId).conversationId(conversationId).top(top).build();
        return imConversationOperation.setConversationTop(setConversationTopRequest);
    }

    @Override
    public Boolean setConversationDoNotDisturb(String userId, Long conversationId, Boolean doNotDisturb) {
        SetConversationDoNotDisturbRequest setConversationDoNotDisturbRequest =
                SetConversationDoNotDisturbRequest.builder().userId(userId).conversationId(conversationId).doNotDisturb(doNotDisturb).build();
        return imConversationOperation.setConversationDoNotDisturb(setConversationDoNotDisturbRequest);
    }

    @Override
    public Boolean publishGroupChatMessage(GroupChatMessage groupChatMessage) {
        Assert.notNull(groupChatMessage);
        PublishGroupChatMessageRequest request = BeanUtil.toBean(groupChatMessage,
                PublishGroupChatMessageRequest.class);
        return imMessageOperation.publishGroupChatMessage(request);
    }

    @Override
    public Boolean publishGroupChatStatusMessage(GroupChatStatusMessage groupChatstatusMessage) {
        Assert.notNull(groupChatstatusMessage);
        PublishGroupChatStatusMessageRequest request = BeanUtil.toBean(groupChatstatusMessage,
                PublishGroupChatStatusMessageRequest.class);
        return imMessageOperation.publishGroupChatStatusMessage(request);
    }

    @Override
    public Boolean publishPrivateMessage(PrivateChatMessage privateChatMessage) {
        Assert.notNull(privateChatMessage);
        PublishPrivateChatMessageRequest request = BeanUtil.toBean(privateChatMessage,
                PublishPrivateChatMessageRequest.class);
        return imMessageOperation.publishPrivateMessage(request);
    }

    @Override
    public Boolean publishPrivateStatusMessage(PrivateChatStatusMessage privateChatStatusMessage) {
        Assert.notNull(privateChatStatusMessage);
        PublishPrivateChatStatusMessageRequest request = BeanUtil.toBean(privateChatStatusMessage,
                PublishPrivateChatStatusMessageRequest.class);
        return imMessageOperation.publishPrivateStatusMessage(request);
    }

    @Override
    public Long createGroup(String groupOwnerUserId, String groupName, String memberIds) {
        CreateGroupRequest createGroupRequest =
                CreateGroupRequest.builder().userId(groupOwnerUserId).groupName(groupName).memberIds(memberIds).build();

        return imGroupOperation.createGroup(createGroupRequest);
    }

    @Override
    public Boolean dismissGroup(String userId, String groupId) {
        DismissGroupRequest dismissGroupRequest =
                DismissGroupRequest.builder().userId(userId).groupId(groupId).build();
        return imGroupOperation.dismissGroup(dismissGroupRequest);
    }

    @Override
    public Integer joinGroup(String inviterUserId, String groupId, String userIds) {
        JoinGroupRequest joinGroupRequest =
                JoinGroupRequest.builder().inviterUserId(inviterUserId).userIds(userIds).groupId(groupId).build();
        return imGroupOperation.joinGroup(joinGroupRequest);
    }

    @Override
    public Integer leaveGroup(String operatorUserId, String groupId, String userIds) {
        LeaveGroupRequest leaveGroupRequest =
                LeaveGroupRequest.builder().operatorUserId(operatorUserId).userIds(userIds).groupId(groupId).build();
        return imGroupOperation.leaveGroup(leaveGroupRequest);
    }

    @Override
    public List<String> listGroupMembers(String groupId) {
        ListGroupMembersRequest listGroupMembersRequest =
                ListGroupMembersRequest.builder().groupId(groupId).build();
        return imGroupOperation.listGroupMembers(listGroupMembersRequest);
    }

    @Override
    public Boolean groupSetting(GroupSettingParam param) {
        GroupSettingRequest groupSettingRequest =
                GroupSettingRequest.builder()
                        .operatorUserId(param.getOperatorUserId())
                        .groupId(param.getGroupId())
                        .type(param.getType())
                        .on(param.getOn())
                        .name(param.getName())
                        .headPortrait(param.getHeadPortrait())
                        .build();
        return imGroupOperation.groupSetting(groupSettingRequest);
    }

    @Override
    public Boolean mutedGroupMember(String groupId, Boolean muted, String userIds) {
        MutedGroupMemberRequest mutedGroupMemberRequest =
                MutedGroupMemberRequest.builder().groupId(groupId).muted(muted).userIds(userIds).build();
        return imGroupOperation.mutedGroupMember(mutedGroupMemberRequest);
    }

    @Override
    public Boolean groupOwnerTransfer(String groupId, String newGroupOwnerUserId) {
        GroupOwnerTransferRequest groupOwnerTransferRequest =
                GroupOwnerTransferRequest.builder().groupId(groupId).newGroupOwnerUserId(newGroupOwnerUserId).build();

        return imGroupOperation.groupOwnerTransfer(groupOwnerTransferRequest);
    }

    @Override
    public Boolean addGroupAdmin(String groupId, String adminUserIds) {
        AddGroupAdminRequest addGroupAdminRequest =
                AddGroupAdminRequest.builder().groupId(groupId).adminUserIds(adminUserIds).build();
        return imGroupOperation.addGroupAdmin(addGroupAdminRequest);
    }

    @Override
    public Boolean removeGroupAdmin(String groupId, String adminUserIds) {
        RemoveGroupAdminRequest removeGroupAdminRequest =
                RemoveGroupAdminRequest.builder().groupId(groupId).adminUserIds(adminUserIds).build();
        return imGroupOperation.removeGroupAdmin(removeGroupAdminRequest);
    }

    @Override
    public Boolean unfriend(String userId, String friendUserIds) {
        UnfriendRequest unfriendRequest = UnfriendRequest.builder().userId(userId).friendUserIds(friendUserIds).build();
        return imContactsOperation.unfriend(unfriendRequest);
    }

    @Override
    public Boolean remarkFriend(String userId, String friendUserId, String remark) {
        RemarkFriendRequest remarkFriendRequest =
                RemarkFriendRequest.builder().userId(userId).friendUserId(friendUserId).remark(remark).build();
        return imContactsOperation.remarkFriend(remarkFriendRequest);
    }

    @Override
    public PageResult<ImRtcRecord> getPageImRtcRecords(RtcRecord record) {
        RtcRecordRequest rtcRecordRequest = BeanUtil.toBean(record, RtcRecordRequest.class);
        return imRtcRecordOperation.listRtcRecords(rtcRecordRequest);
    }

    @Override
    public Boolean singleUserNotification(SingleUserNotification singleUserNotification) {
        SingleUserNotificationRequest singleUserNotificationRequest = BeanUtil.toBean(singleUserNotification,
                SingleUserNotificationRequest.class);
        return imSystemNotificationOperation.singleUserNotification(singleUserNotificationRequest);
    }

    private void initOperations() {
        this.imUserOperation = new WecloudImUserOperation(apiDomain, appKey, appSecret);
        this.imConversationOperation = new WecloudImConversationOperation(apiDomain, appKey, appSecret);
        this.imMessageOperation = new WecloudImMessageOperation(apiDomain, appKey, appSecret);
        this.imGroupOperation = new WecloudImGroupOperation(apiDomain, appKey, appSecret);
        this.imContactsOperation = new WecloudImContactsOperation(apiDomain, appKey, appSecret);
        this.imRtcRecordOperation = new WecloudImRtcRecordOperation(apiDomain, appKey, appSecret);
        this.imSystemNotificationOperation = new WecloudImSystemNotificationOperation(apiDomain, appKey, appSecret);
    }
}
