package alicloud

import (
	"context"
	"fmt"
	"github.com/spf13/viper"

	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	sts20150401 "github.com/alibabacloud-go/sts-20150401/v2/client"
	util "github.com/alibabacloud-go/tea-utils/v2/service"
	"github.com/alibabacloud-go/tea/tea"
	"github.com/pingcap-inc/pchub/pkg/log"
)

type STSTokenResponse struct {
	Credentials struct {
		AccessKeyId     string `json:"AccessKeyId"`
		AccessKeySecret string `json:"AccessKeySecret"`
		SecurityToken   string `json:"SecurityToken"`
		Expiration      string `json:"Expiration"`
	} `json:"Credentials"`
	AssumedRoleUser struct {
		AssumedRoleId string `json:"AssumedRoleId"`
		Arn           string `json:"Arn"`
	} `json:"AssumedRoleUser"`
	RequestId string `json:"RequestId"`
}

// CreateSTSClient 创建STS客户端
func CreateSTSClient(accessKeyId, accessKeySecret string) (*sts20150401.Client, error) {
	config := &openapi.Config{
		AccessKeyId:     tea.String(accessKeyId),
		AccessKeySecret: tea.String(accessKeySecret),
		Endpoint:        tea.String("sts.cn-hangzhou.aliyuncs.com"), // 默认使用杭州区域
	}

	client, err := sts20150401.NewClient(config)
	if err != nil {
		return nil, fmt.Errorf("failed to create STS client: %v", err)
	}

	return client, nil
}

// AssumeRole 获取STS临时凭证
func AssumeRole(client *sts20150401.Client, roleArn, roleSessionName, policy string, durationSeconds int64) (*STSTokenResponse, error) {
	request := &sts20150401.AssumeRoleRequest{
		RoleArn:         tea.String(roleArn),
		RoleSessionName: tea.String(roleSessionName),
		DurationSeconds: tea.Int64(durationSeconds),
	}

	// 如果提供了策略，则设置
	if policy != "" {
		request.Policy = tea.String(policy)
	}

	runtime := &util.RuntimeOptions{}
	response, err := client.AssumeRoleWithOptions(request, runtime)
	if err != nil {
		return nil, fmt.Errorf("failed to assume role: %v", err)
	}

	// 构建响应结构
	result := &STSTokenResponse{
		RequestId: tea.StringValue(response.Body.RequestId),
	}

	if response.Body.Credentials != nil {
		result.Credentials.AccessKeyId = tea.StringValue(response.Body.Credentials.AccessKeyId)
		result.Credentials.AccessKeySecret = tea.StringValue(response.Body.Credentials.AccessKeySecret)
		result.Credentials.SecurityToken = tea.StringValue(response.Body.Credentials.SecurityToken)
		result.Credentials.Expiration = tea.StringValue(response.Body.Credentials.Expiration)
	}

	if response.Body.AssumedRoleUser != nil {
		result.AssumedRoleUser.AssumedRoleId = tea.StringValue(response.Body.AssumedRoleUser.AssumedRoleId)
		result.AssumedRoleUser.Arn = tea.StringValue(response.Body.AssumedRoleUser.Arn)
	}

	return result, nil
}

// GetCallerIdentity 获取当前调用者身份信息
func GetCallerIdentity(client *sts20150401.Client) (map[string]interface{}, error) {
	runtime := &util.RuntimeOptions{}

	response, err := client.GetCallerIdentityWithOptions(runtime)
	if err != nil {
		return nil, fmt.Errorf("failed to get caller identity: %v", err)
	}

	result := map[string]interface{}{
		"RequestId": tea.StringValue(response.Body.RequestId),
		"AccountId": tea.StringValue(response.Body.AccountId),
		"UserId":    tea.StringValue(response.Body.UserId),
		"Arn":       tea.StringValue(response.Body.Arn),
	}

	return result, nil
}

// GetSessionToken 获取会话令牌
func GetSessionToken(client *sts20150401.Client, durationSeconds int64) (*STSTokenResponse, error) {
	// 注意：阿里云STS SDK v2中可能没有GetSessionToken方法
	// 这里提供一个示例，实际使用时需要根据SDK版本调整
	fmt.Println("注意：GetSessionToken方法在当前STS SDK版本中可能不可用")

	// 返回一个示例响应结构
	result := &STSTokenResponse{
		RequestId: "example-request-id",
	}

	return result, nil
}

// GenerateStsToken 生成STS临时凭证
func GenerateStsToken(ctx context.Context, ak, sk string) (*string, error) {

	// 创建STS客户端
	client, err := CreateSTSClient(ak, sk)
	if err != nil {
		log.L(ctx).Errorf("创建STS客户端失败: %v", err)

		return nil, err
	}

	fmt.Println("=== 获取调用者身份信息 ===")
	identity, err := GetCallerIdentity(client)
	if err != nil {
		log.L(ctx).Errorf("获取调用者身份信息失败: %v", err)

		return nil, err
	} else {
		fmt.Printf("账户ID: %s\n", identity["AccountId"])
		fmt.Printf("用户ID: %s\n", identity["UserId"])
		fmt.Printf("ARN: %s\n", identity["Arn"])
		fmt.Printf("请求ID: %s\n", identity["RequestId"])
	}

	roleArn := viper.Get("alicloud.role_arn").(string)
	tk := ""
	if roleArn != "" {
		log.L(ctx).Infof("假设角色ARN: %s", roleArn)
		roleSessionName := "test-session"
		//policy := `{
		//	"Version": "1",
		//	"Statement": [
		//		{
		//			"Effect": "Allow",
		//			"Action": "oss:GetObject",
		//			"Resource": "*"
		//		}
		//	]
		//}`

		token, err := AssumeRole(client, roleArn, roleSessionName, "", 3600)
		if err != nil {
			log.L(ctx).Errorf("假设角色失败: %v", err)

			return nil, err
		} else {
			fmt.Printf("临时访问密钥ID: %s\n", token.Credentials.AccessKeyId)
			fmt.Printf("临时访问密钥Secret: %s\n", token.Credentials.AccessKeySecret)
			fmt.Printf("安全令牌: %s\n", token.Credentials.SecurityToken)
			fmt.Printf("过期时间: %s\n", token.Credentials.Expiration)
			fmt.Printf("假设角色ID: %s\n", token.AssumedRoleUser.AssumedRoleId)
			fmt.Printf("假设角色ARN: %s\n", token.AssumedRoleUser.Arn)
		}

		tk = token.Credentials.SecurityToken
	} else {
		log.L(ctx).Error("未提供角色ARN，无法假设角色")

		return nil, fmt.Errorf("未提供角色ARN，无法假设角色")
	}

	return &tk, nil
}
