// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

package org.apache.doris.stack.component;

import org.apache.doris.stack.dao.ClusterUserMembershipRepository;
import org.apache.doris.stack.entity.ClusterUserMembershipEntity;
import org.apache.doris.stack.exception.UserNoSelectClusterException;
import org.apache.doris.stack.model.request.user.UserGroupRole;
import org.apache.doris.stack.dao.ClusterInfoRepository;
import org.apache.doris.stack.dao.CoreUserRepository;
import org.apache.doris.stack.dao.PermissionsGroupMembershipRepository;
import org.apache.doris.stack.dao.PermissionsGroupRoleRepository;
import org.apache.doris.stack.entity.ClusterInfoEntity;
import org.apache.doris.stack.entity.CoreUserEntity;
import org.apache.doris.stack.entity.PermissionsGroupMembershipEntity;
import org.apache.doris.stack.entity.PermissionsGroupRoleEntity;
import org.apache.doris.stack.exception.NoPermissionException;
import org.apache.doris.stack.model.response.user.GroupMember;
import org.apache.doris.stack.service.BaseService;
import lombok.extern.slf4j.Slf4j;

import org.apache.doris.stack.util.CredsUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

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

/**
 * @Description：The engine cluster management tool class is mainly responsible for
 * verifying whether the user has the permission of cluster space
 */
@Component
@Slf4j
public class ClusterUserComponent extends BaseService {

    @Autowired
    private ClusterInfoRepository clusterInfoRepository;

    @Autowired
    private PermissionsGroupRoleRepository groupRoleRepository;

    @Autowired
    private PermissionsGroupMembershipRepository membershipRepository;

    @Autowired
    private CoreUserRepository userRepository;

    @Autowired
    private ClusterUserMembershipRepository clusterUserMembershipRepository;

    /**
     * Obtain the user's current space information.
     * All API accesses in the space need to obtain the current space ID
     * @param user
     * @return
     * @throws Exception
     */
    public ClusterInfoEntity getUserCurrentCluster(CoreUserEntity user) throws Exception {
        long clusterId = user.getClusterId();
        if (clusterId < 1) {
            log.error("The user do not have current cluster");
            throw new UserNoSelectClusterException();
        }

        Optional<ClusterInfoEntity> clusterInfoEntityOp = clusterInfoRepository.findById((long) clusterId);
        if (clusterInfoEntityOp.equals(Optional.empty())) {
            log.error("The user current cluster {} has been deleted", clusterId);
            throw new UserNoSelectClusterException();
        }
        ClusterInfoEntity clusterInfoEntity = clusterInfoEntityOp.get();
        try {
            clusterInfoEntity.setPasswd(CredsUtil.aesDecrypt(clusterInfoEntity.getPasswd()));
        } catch (Exception e) {
            log.warn("execute more than once select in one thread, the password was cached. msg {}", e.getMessage());
        }

        return clusterInfoEntity;
    }

    // add a user for all space which doesn't have default user
//    public void addDefaultUserForSpace() throws Exception {
//        log.debug("add default user");
//        List<ClusterInfoEntity> clusterInfoEntities = clusterInfoRepository.findAll();
//        for (ClusterInfoEntity clusterInfo : clusterInfoEntities) {
//            int adminGroupUserId = clusterInfo.getAdminGroupId();
//            int allUserGroupId = clusterInfo.getAllUserGroupId();
//            long clusterId = clusterInfo.getId();
//            if (membershipRepository.getByUserId(-1L * clusterId).size() < 2) {
//
//                addDefaultUserForSpace(clusterId, adminGroupUserId, allUserGroupId);
//            }
//        }
//    }

//    public void addDefaultUserForSpace(long clusterId, int adminGroupUserId, int allUserGroupId) throws Exception {
//        log.debug("add default user for space");
//        // add into admin group
//        PermissionsGroupMembershipEntity adminMembershipEntity = new PermissionsGroupMembershipEntity();
//        adminMembershipEntity.setUserId(-clusterId);
//        adminMembershipEntity.setGroupId(adminGroupUserId);
//        membershipRepository.save(adminMembershipEntity);
//        // add into all user group
//        PermissionsGroupMembershipEntity allUserMembershipEntity = new PermissionsGroupMembershipEntity();
//        allUserMembershipEntity.setUserId(-clusterId);
//        allUserMembershipEntity.setGroupId(allUserGroupId);
//        membershipRepository.save(allUserMembershipEntity);
//    }

    /**
     * Judge whether the user is in the space
     * @param userId
     * @return
     * @throws Exception
     */
    public boolean checkUserBelongToCluster(int userId, long clusterId) throws Exception {
        // built in user
        if (userId == BuiltInUserComponent.BUILT_USER_ID) {
            return true;
        }
        List<ClusterUserMembershipEntity> clusterUserMembershipEntities =
                clusterUserMembershipRepository.getByUserIdAndClusterId(userId, clusterId);
        if (clusterUserMembershipEntities.isEmpty()) {
            log.error("The user {} is not a space {} user.", userId, clusterId);
            throw new NoPermissionException();
        }
        return true;
    }

    /**
     * Judge whether the user is in the space
     * @param userId
     * @return
     * @throws Exception
     */
    public boolean userBelongToCluster(int userId, long clusterId) {
        List<ClusterUserMembershipEntity> clusterUserMembershipEntities =
                clusterUserMembershipRepository.getByUserIdAndClusterId(userId, clusterId);
        if (clusterUserMembershipEntities.isEmpty()) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * Determine whether the user is the administrator role of a space
     * @param userId
     * @param clusterInfo
     * @return
     */
    public boolean userIsClusterAdminRole(int userId, ClusterInfoEntity clusterInfo) {
        int adminGroupRoleId = clusterInfo.getAdminGroupId();
        List<PermissionsGroupMembershipEntity> membershipEntities =
                membershipRepository.getByUserIdAndGroupId(userId, adminGroupRoleId);
        if (membershipEntities == null || membershipEntities.isEmpty()) {
            return false;
        }
        return true;
    }

    /**
     * Add a normal user to the space
     * @param userId
     * @param clusterInfo
     */
    public void addUserToCluster(int userId, ClusterInfoEntity clusterInfo) {
        ClusterUserMembershipEntity membershipEntity =
                new ClusterUserMembershipEntity(userId, clusterInfo.getId());
        clusterUserMembershipRepository.save(membershipEntity);

        addGroupUserMembership(userId, clusterInfo.getAllUserGroupId());
    }

    /**
     * Add an administrator user to the space
     * @param userId
     * @param clusterInfo
     */
    public void addAdminUserToCluster(int userId, ClusterInfoEntity clusterInfo) {
        addUserToCluster(userId, clusterInfo);
        addGroupUserMembership(userId, clusterInfo.getAdminGroupId());
    }

    /**
     * Check whether the user is the administrator role user of the space
     * Available to space level APIs
     * @param user
     * @return
     * @throws Exception
     */
    public long getUserCurrentClusterIdAndCheckAdmin(CoreUserEntity user) throws Exception {
        ClusterInfoEntity cluster = getUserCurrentCluster(user);
        long clusterId = cluster.getId();
        if (!user.isSuperuser() && !user.getIsClusterAdmin()) {
            log.error("The user {} not cluster {} space admin", user.getId(), clusterId);
            throw new NoPermissionException();
        }
        return clusterId;
    }

    /**
     * Check whether the user is the administrator role user of the space
     * Available to space level APIs
     * @param user
     * @return
     * @throws Exception
     */
    public ClusterInfoEntity getUserCurrentClusterAndCheckAdmin(CoreUserEntity user) throws Exception {
        ClusterInfoEntity cluster = getUserCurrentCluster(user);
        if (!user.isSuperuser() && !user.getIsClusterAdmin()) {
            log.error("The user {} not cluster {} space admin", user.getId(), cluster.getId());
            throw new NoPermissionException();
        }
        return cluster;
    }

    /**
     * Check whether the user has the operation permission of the administrator role of the space
     * Space level API usage
     * @param user
     * @param clusterId
     * @return
     * @throws Exception
     */
    public ClusterInfoEntity checkUserClusterAdminPermission(CoreUserEntity user, long clusterId) throws Exception {
        // The super admin user has all space administrator permissions by default and can operate directly
        if (user.isSuperuser()) {
            return clusterInfoRepository.findById((long) clusterId).get();
        } else {
            int userId = user.getId();
            ClusterInfoEntity clusterInfoEntity = clusterInfoRepository.findById((long) clusterId).get();

            boolean isAdmin = userIsClusterAdminRole(userId, clusterInfoEntity);

            if (!isAdmin) {
                log.error("The user {} is not a space {} user.", userId, clusterId);
                throw new NoPermissionException();
            }
            return clusterInfoEntity;
        }
    }

    /**
     * Check whether the user has the operation permission of the administrator role of the space
     * APIs that can be accessed at both platform and space levels are used
     * @param user
     * @param clusterId
     * @return
     * @throws Exception
     */
    public void checkUserSpuerAdminOrClusterAdmin(CoreUserEntity user, long clusterId) throws Exception {
        // The super admin user has all space administrator permissions by default and can operate directly
        if (user.isSuperuser()) {
            return;
        } else {
            int userId = user.getId();
            ClusterInfoEntity clusterInfoEntity = clusterInfoRepository.findById((long) clusterId).get();

            boolean isAdmin = userIsClusterAdminRole(userId, clusterInfoEntity);

            if (!isAdmin) {
                log.error("The user {} is not a space {} user.", userId, clusterId);
                throw new NoPermissionException();
            }
            return;
        }
    }

    /**
     * Initialize the correspondence between permission groups and users
     *
     * @param userId
     * @param groupId
     * @return
     */
    public int addGroupUserMembership(int userId, int groupId) {
        PermissionsGroupMembershipEntity amdinMembershipEntity =
                new PermissionsGroupMembershipEntity(userId, groupId);
        return membershipRepository.save(amdinMembershipEntity).getId();
    }

    /**
     * Create a user group and return the user group ID
     *
     * @return
     */
    public int addPermissionsGroup(String name, long clusterId, UserGroupRole role) {
        // Create a user group and bind the relationship with the Doris cluster and user information.
        PermissionsGroupRoleEntity groupRoleEntity =
                new PermissionsGroupRoleEntity(name, role.name(), clusterId);
        int groupId = groupRoleRepository.save(groupRoleEntity).getGroupId();
        log.debug("create group {}.", groupId);

        return groupId;
    }

    /**
     * Create a user group and return the user group ID
     *
     * @return
     */
    public int addPermissionsGroup(String name, long clusterId, UserGroupRole role, String dorisUserName,
                                   String passwd) {
        // Create a user group and bind the relationship with the Doris cluster and user information.
        PermissionsGroupRoleEntity groupRoleEntity =
                new PermissionsGroupRoleEntity(name, role.name(), clusterId, dorisUserName, passwd);
        int groupId = groupRoleRepository.save(groupRoleEntity).getGroupId();
        log.debug("create group {}.", groupId);

        return groupId;
    }

    /**
     * Save user group password information
     * @Param
     * @return
     */
    public PermissionsGroupRoleEntity addPermissionsGroupWithPaloUser(String name, long clusterId,
                                                                      UserGroupRole role, String password,
                                                                      String userName) throws Exception {
        // Create a user group and bind the relationship with the Doris cluster and user information.
        password = CredsUtil.aesEncrypt(password);
        PermissionsGroupRoleEntity groupRoleEntity =
                new PermissionsGroupRoleEntity(name, role.name(), clusterId, userName, password);
        int groupId = groupRoleRepository.save(groupRoleEntity).getGroupId();
        log.debug("create group {}.", groupId);

        return groupRoleEntity;
    }

    /**
     * Get all members of a permission group
     *
     * @param groupId
     * @return
     */
    public List<GroupMember> getGroupMembers(int groupId) {
        log.debug("get group {} all members.", groupId);
        List<Integer> stopLdapUsers = userRepository.getByEmptyEntryUUID();
        List<PermissionsGroupMembershipEntity> users = membershipRepository.getByGroupId(groupId);

        List<GroupMember> members = new ArrayList<>();
        for (PermissionsGroupMembershipEntity membershipEntity : users) {
            // get user
            if (membershipEntity.getUserId() < 0 || stopLdapUsers.contains(membershipEntity.getUserId())) {
                continue;
            }
            CoreUserEntity userEntity = userRepository.findById(membershipEntity.getUserId()).get();

            // construct Member
            GroupMember member = new GroupMember();
            member.setMembershipId(membershipEntity.getId());
            member.setUserId(membershipEntity.getUserId());
            member.setName(userEntity.getFirstName());
            member.setEmail(userEntity.getEmail());

            // add list
            members.add(member);
        }
        return members;
    }

    // Encrypt the cluster unencrypted password
    public void encryptClusterPassword() throws Exception {
        log.debug("encrypt password for cluster");
        List<ClusterInfoEntity> clusterInfoEntities = clusterInfoRepository.findAll();
        log.debug("encrypt password for cluster, size is {}", clusterInfoEntities.size());
        for (ClusterInfoEntity clusterInfo : clusterInfoEntities) {
            if (clusterInfo.getPasswd() == null) {
                log.debug("cluster password is null");
                continue;
            }
            if (!clusterInfo.getPasswd().trim().equals("")) {
                try {
                    CredsUtil.aesDecrypt(clusterInfo.getPasswd());
                    log.debug("password has been encrypted");
                    continue;
                } catch (Exception e) {
                    log.debug("password has not been encrypted");
                }
            }
            // Empty string is still empty after encryption
            clusterInfo.setPasswd(CredsUtil.aesEncrypt(clusterInfo.getPasswd()));
            clusterInfoRepository.save(clusterInfo);
        }
    }
}
