package feishu

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2"

	"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
	"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
	"github.com/google/uuid"
)

// 从环境变量读取认证信息
var (
// clientID     = "*"
// clientSecret = "*"
// tenantID     = "*"
)

// 获取 Azure 认证凭证
func getCred() (*azidentity.ClientSecretCredential, error) {
	return azidentity.NewClientSecretCredential(
		tenantID,
		clientID,
		clientSecret,
		nil,
	)
}

// 获取角色定义 ID（通过角色名）
func getRoleDefinitionID(ctx context.Context, cred *azidentity.ClientSecretCredential, subscriptionID, roleName string) (string, error) {
	roleClient, err := armauthorization.NewRoleDefinitionsClient(cred, nil)
	if err != nil {
		return "", err
	}

	scope := fmt.Sprintf("/subscriptions/%s", subscriptionID)
	pager := roleClient.NewListPager(scope, nil)
	for pager.More() {
		page, err := pager.NextPage(ctx)
		if err != nil {
			return "", err
		}
		for _, role := range page.Value {
			if role.Properties != nil && *role.Properties.RoleName == roleName {
				return *role.ID, nil
			}
		}
	}
	return "", fmt.Errorf("role '%s' not found", roleName)
}

// 获取用户的 Object ID
func getUserObjectID(ctx context.Context, cred *azidentity.ClientSecretCredential, userEmail string) (string, error) {
	token, err := cred.GetToken(ctx, policy.TokenRequestOptions{
		Scopes: []string{"https://graph.microsoft.com/.default"},
	})
	if err != nil {
		return "", fmt.Errorf("failed to get token: %v", err)
	}

	url := fmt.Sprintf("https://graph.microsoft.com/v1.0/users/%s", userEmail)
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return "", err
	}
	req.Header.Set("Authorization", "Bearer "+token.Token)

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("failed to get user: %s", resp.Status)
	}

	var result struct {
		ID string `json:"id"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return "", err
	}
	return result.ID, nil
}

// 为指定用户分配角色
func Azure_AssignRole(userEmail, roleName, subscriptionID string) error {
	ctx := context.Background()
	cred, err := getCred()
	if err != nil {
		return err
	}

	// 获取用户的 Object ID
	userObjectID, err := getUserObjectID(ctx, cred, userEmail)
	if err != nil {
		return fmt.Errorf("failed to get user object ID: %v", err)
	}

	roleDefID, err := getRoleDefinitionID(ctx, cred, subscriptionID, roleName)
	if err != nil {
		return err
	}

	scope := fmt.Sprintf("/subscriptions/%s", subscriptionID)
	roleAssignmentsClient, err := armauthorization.NewRoleAssignmentsClient(subscriptionID, cred, nil)
	if err != nil {
		return err
	}

	assignmentName := uuid.New().String()
	_, err = roleAssignmentsClient.Create(ctx, scope, assignmentName, armauthorization.RoleAssignmentCreateParameters{
		Properties: &armauthorization.RoleAssignmentProperties{
			PrincipalID:      &userObjectID,
			RoleDefinitionID: &roleDefID,
		},
	}, nil)

	return err
}

// 移除指定用户的角色
func Azure_RemoveRole(userEmail, roleName, subscriptionID string) error {
	ctx := context.Background()
	cred, err := getCred()
	if err != nil {
		return err
	}

	// 获取用户的 Object ID
	userObjectID, err := getUserObjectID(ctx, cred, userEmail)
	if err != nil {
		return fmt.Errorf("failed to get user object ID: %v", err)
	}

	roleDefID, err := getRoleDefinitionID(ctx, cred, subscriptionID, roleName)
	if err != nil {
		return err
	}

	scope := fmt.Sprintf("/subscriptions/%s", subscriptionID)
	roleAssignmentsClient, err := armauthorization.NewRoleAssignmentsClient(subscriptionID, cred, nil)
	if err != nil {
		return err
	}

	// 查找并删除对应的角色分配
	pager := roleAssignmentsClient.NewListForScopePager(scope, nil)
	for pager.More() {
		page, err := pager.NextPage(ctx)
		if err != nil {
			return err
		}
		for _, assignment := range page.Value {
			if assignment.Properties != nil &&
				assignment.Properties.PrincipalID != nil &&
				assignment.Properties.RoleDefinitionID != nil &&
				*assignment.Properties.PrincipalID == userObjectID &&
				*assignment.Properties.RoleDefinitionID == roleDefID {
				// 使用正确的 API 版本删除角色分配
				_, err = roleAssignmentsClient.Delete(ctx, scope, *assignment.Name, nil)
				return err
			}
		}
	}
	return fmt.Errorf("no matching role assignment found for user %s with role %s", userEmail, roleName)
}

// Azure convert subscription to subscription_id, covnert role to real name
func Azure_Convert_subid(subscription string) string {
	subscription_id := ""
	subscription = strings.TrimSpace(subscription)
	switch subscription {
	case "tidb-dedicated-prod-controlplane":
		subscription_id = "ad881159-0593-4502-96e4-e2698b790a3d"
		break
	case "tidb-dedicated-prod-dataplane-000":
		subscription_id = "efe59dff-e62f-4356-b93d-de124c967a1f"
		break
	case "tidb-o11y":
		subscription_id = "01f5d24b-a99c-45e1-a3e2-5ddc1e5bb71d"
		break
	}
	return subscription_id
}

func Azure_Add_Permissions(subscription string, user_email string, roles []string) {
	//1、 subscription 转换为订阅 ID
	subscription_id := ""
	subscription = strings.TrimSpace(subscription)
	subscription_id = Azure_Convert_subid(subscription)

	// 开始添加权限，roles 需要转换为订阅真实环境中的 role name
	for _, role := range roles {
		// role 需要转换你为实际场景中的 role name
		if subscription == "tidb-dedicated-prod-dataplane-000" {
			role = role + "-0"
		} else if subscription == "tidb-o11y" {
			role = role + "-o11y"
		}

		// 开始添加权限
		err := Azure_AssignRole(user_email, role, subscription_id)
		if err == nil {
			ntime := time.Now().Format("2006-01-02 15:04:05")
			Writelog_To_File("./log/add_permission_log", ntime+" "+subscription+" "+user_email+" "+role+" add permissions success")
			fmt.Println(ntime + " --> " + subscription + " " + user_email + " " + role + " add permissions success")
			//发送飞书提醒消息
			send_feishu_message := strings.ReplaceAll(Azure_Add_Permission_notice, "permission_name", role)
			fserr := Send_User_Notice(user_email, "Azure SSO 权限申请反馈通知", send_feishu_message)
			if fserr == nil {
				fmt.Println("send feishu notice message success")
			} else {
				fmt.Println("send feishu notice message failed")
			}

			fmt.Println("")
		} else {
			fmt.Println(err.Error())
			continue
		}
	}
}

func Alibaba_Add_Permissions(Account string, user_email string, roles []string) {
	Account = strings.TrimSpace(Account)
	user_email = strings.TrimSpace(user_email)

	// 开始添加权限，roles 需要转换为订阅真实环境中的 role name
	for _, role := range roles {
		// 开始添加权限
		err := Alibaba_Assign_permissions(Account, user_email, role)

		if err == nil {
			ntime := time.Now().Format("2006-01-02 15:04:05")
			Writelog_To_File("./log/add_permission_log", ntime+" "+Account+" "+user_email+" "+role+" add permissions success")
			fmt.Println(ntime + " --> " + Account + " " + user_email + " " + role + " add permissions success")
			//发送飞书提醒消息
			send_feishu_message := strings.ReplaceAll(Alibaba_Add_Permission_notice, "permission_name", role)
			fserr := Send_User_Notice(user_email, "Alibaba SSO 权限申请反馈通知", send_feishu_message)
			if fserr == nil {
				fmt.Println("send feishu notice message success")
			} else {
				fmt.Println("send feishu notice message failed")
			}

			fmt.Println("")
		} else {
			fmt.Println(err.Error())
			continue
		}
	}
}

// 示例调用入口

func Azure_test() {
	user := "dong.zhang@pingcap.com"
	role := "DBaaS-Prod-DevUser-Role-0"
	sub := "efe59dff-e62f-4356-b93d-de124c967a1f"

	// 添加角色
	/*
		err := Azure_AssignRole(user, role, sub)
		if err != nil {
			log.Fatalf("Add Role Failed: %v", err)
		}
		fmt.Println("Role assigned successfully.")
	*/

	// 移除角色（如需测试删除，请注释掉上面 assign 调用）

	derr := Azure_RemoveRole(user, role, sub)
	if derr != nil {
		log.Fatalf("Remove Role Failed: %v", derr)
	}
	fmt.Println("Role removed successfully.")

}
