package feishu

import (
	"errors"
	"fmt"
	"strings"

	cloudsso20210515 "github.com/alibabacloud-go/cloudsso-20210515/client"
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	util "github.com/alibabacloud-go/tea-utils/v2/service"
	"github.com/alibabacloud-go/tea/tea"
	credential "github.com/aliyun/credentials-go/credentials"
)

// CreateClient 使用硬编码的 AK/SK 初始化
func CreateClient() (*cloudsso20210515.Client, error) {
	// ======= 改成你自己的 AK/SK =======
	//accessKeyId := "*"
	//accessKeySecret := "*"

	// 正确写法：用 credential.Config
	cred, err := credential.NewCredential(&credential.Config{
		Type:            tea.String("access_key"),
		AccessKeyId:     tea.String(accessKeyId),
		AccessKeySecret: tea.String(accessKeySecret),
	})
	if err != nil {
		return nil, err
	}

	config := &openapi.Config{
		Credential: cred,
		Endpoint:   tea.String("cloudsso.cn-shanghai.aliyuncs.com"),
	}
	return cloudsso20210515.NewClient(config)
}

// GetAccessConfigurationId 根据权限名称查 ID
func GetAccessConfigurationId(directoryId, permissionName string) (string, error) {
	client, err := CreateClient()
	if err != nil {
		return "", err
	}

	req := &cloudsso20210515.ListAccessConfigurationsRequest{
		DirectoryId: tea.String(directoryId),
	}

	resp, err := client.ListAccessConfigurationsWithOptions(req, &util.RuntimeOptions{})
	if err != nil {
		return "", err
	}

	if resp.Body == nil || resp.Body.AccessConfigurations == nil {
		return "", fmt.Errorf("no access configurations found")
	}

	for _, cfg := range resp.Body.AccessConfigurations {
		if tea.StringValue(cfg.AccessConfigurationName) == permissionName {
			return tea.StringValue(cfg.AccessConfigurationId), nil
		}
	}

	return "", fmt.Errorf("permission name %s not found", permissionName)
}

// GetUserIdByUserName 根据邮箱（UserName）查询 UserId，支持分页
func GetUserIdByUserName(directoryId, userName string) (string, error) {
	client, err := CreateClient()
	if err != nil {
		return "", err
	}

	var nextToken *string = nil

	for {
		req := &cloudsso20210515.ListUsersRequest{
			DirectoryId: tea.String(directoryId),
			MaxResults:  tea.Int32(100),
			NextToken:   nextToken,
		}

		resp, err := client.ListUsersWithOptions(req, &util.RuntimeOptions{})
		if err != nil {
			return "", err
		}

		if resp.Body == nil || resp.Body.Users == nil {
			break
		}

		for _, u := range resp.Body.Users {
			if tea.StringValue(u.UserName) == userName {
				return tea.StringValue(u.UserId), nil
			}
		}

		// 判断是否还有下一页
		if resp.Body.NextToken == nil || tea.StringValue(resp.Body.NextToken) == "" {
			break
		}
		nextToken = resp.Body.NextToken
	}

	return "", fmt.Errorf("user %s not found", userName)
}

// CreateAccessAssignment 调用 API 授权
func CreateAccessAssignment(directoryId, accessConfigurationId, principalId, principalType, targetId, targetType string) error {
	client, err := CreateClient()
	if err != nil {
		return err
	}

	req := &cloudsso20210515.CreateAccessAssignmentRequest{
		DirectoryId:           tea.String(directoryId),
		AccessConfigurationId: tea.String(accessConfigurationId),
		PrincipalId:           tea.String(principalId),
		PrincipalType:         tea.String(principalType),
		TargetId:              tea.String(targetId),
		TargetType:            tea.String(targetType),
	}

	_, err = client.CreateAccessAssignmentWithOptions(req, &util.RuntimeOptions{})
	if err != nil {
		return err
	}
	return nil
}

// 移除指定账号的权限
func DeleteAccessAssignment(directoryId, principalId, principalType, targetId, targetType, accessConfigurationId string) error {
	client, err := CreateClient()
	if err != nil {
		return err
	}

	request := &cloudsso20210515.DeleteAccessAssignmentRequest{
		DirectoryId:           tea.String(directoryId),
		PrincipalId:           tea.String(principalId),
		PrincipalType:         tea.String(principalType),
		TargetId:              tea.String(targetId),
		TargetType:            tea.String(targetType),
		AccessConfigurationId: tea.String(accessConfigurationId),
	}

	runtime := &util.RuntimeOptions{}

	tryErr := func() (e error) {
		defer func() {
			if r := tea.Recover(recover()); r != nil {
				e = r
			}
		}()
		_, err = client.DeleteAccessAssignmentWithOptions(request, runtime)
		if err != nil {
			return err
		}
		return nil
	}()
	return tryErr
}

/*
AccountID 阿里巴巴云的账号
UserName 为邮箱名 xx@pingcap.com
PerName 为自定义权限名称
*/
func Alibaba_Delete_Permissions(AccountID string, UserName string, PerName string) error {
	directoryId := "d-00ts1z0rjv32"
	targetType := "RD-Account"
	principalType := "User"

	if AccountID == "" || UserName == "" || PerName == "" {
		fmt.Println("Alibabacloud: AccountID or UserName or PerName is empty")
		return errors.New("Alibabacloud: AccountID or UserName or PerName is empty")
	}

	UserID, err := Alibaba_obtain_UserID(UserName)
	if err != nil {
		return err
	}

	PerID, err := Alibaba_Obtain_PerID(PerName)
	if err != nil {
		return err
	}

	AccountID = strings.TrimSpace(AccountID)
	UserID = strings.TrimSpace(UserID)
	PerID = strings.TrimSpace(PerID)
	// 示例调用
	err = DeleteAccessAssignment(
		directoryId,   // DirectoryId
		UserID,        // PrincipalId
		principalType, // PrincipalType
		AccountID,     // TargetId
		targetType,    // TargetType
		PerID,         // AccessConfigurationId
	)
	if err != nil {
		return err
	}
	return nil
}

// 授予权限
func Alibaba_Assign_permissions(AccountID string, UserName string, PerName string) error {
	directoryId := "d-00ts1z0rjv32"
	targetType := "RD-Account"
	principalType := "User"

	if AccountID == "" || UserName == "" || PerName == "" {
		fmt.Println("Alibabacloud: AccountID or UserName or PerName is empty")
		return errors.New("Alibabacloud: AccountID or UserName or PerName is empty")
	}

	UserID, err := Alibaba_obtain_UserID(UserName)
	if err != nil {
		return err
	}

	PerID, err := Alibaba_Obtain_PerID(PerName)
	if err != nil {
		return err
	}

	targetId := strings.TrimSpace(AccountID)
	accessConfigurationId := strings.TrimSpace(PerID)
	principalId := strings.TrimSpace(UserID)

	err = CreateAccessAssignment(directoryId, accessConfigurationId, principalId, principalType, targetId, targetType)
	if err != nil {
		return err
	}
	return nil
}

// 1、Obtain the permission ID
func Alibaba_obtain_UserID(userName string) (string, error) {
	directoryId := "d-00ts1z0rjv32"
	//userName := "tangpeng@pingcap.com"

	userId, err := GetUserIdByUserName(directoryId, userName)
	if err != nil {
		return "", err
	}
	//fmt.Printf("UserName=%s, UserId=%s\n", userName, userId)
	return userId, nil
}

// 2、Obtain the user ID
func Alibaba_Obtain_PerID(permissionName string) (string, error) {
	directoryId := "d-00ts1z0rjv32"
	//permissionName := "DBaaS-Prod-Admin-Role"

	PerID, err := GetAccessConfigurationId(directoryId, permissionName)
	if err != nil {
		return "", err
	}
	//fmt.Printf("PermissionName=%s, AccessConfigurationId=%s\n", permissionName, id)
	return PerID, nil
}
