// Copyright 2019 Yunion
//
// Licensed 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 adapters

import (
	"context"

	"yunion.io/x/log"

	api "yunion.io/x/onecloud/pkg/apis/identity"
	"yunion.io/x/onecloud/pkg/cloudcommon/policy"
	"yunion.io/x/onecloud/pkg/mcclient"
	"yunion.io/x/onecloud/pkg/mcclient/auth"
	"yunion.io/x/onecloud/pkg/mcp-server/options"
)

// Context key 类型，用于从 HTTP Header 传入的 AK/SK 存入 context（供 Cursor/Claude 等客户端使用）
type headerCredKey string

const (
	ContextKeyAK headerCredKey = "mcp_header_ak"
	ContextKeySK headerCredKey = "mcp_header_sk"
)

// GetAKSKFromContext 从 context 中读取连接时通过 Header 传入的 AK/SK（未设置时返回空字符串）
func GetAKSKFromContext(ctx context.Context) (ak, sk string) {
	if v := ctx.Value(ContextKeyAK); v != nil {
		if s, ok := v.(string); ok {
			ak = s
		}
	}
	if v := ctx.Value(ContextKeySK); v != nil {
		if s, ok := v.(string); ok {
			sk = s
		}
	}
	return ak, sk
}

// CloudpodsAdapter 是与 Cloudpods API 交互的适配器，负责认证和资源管理
type CloudpodsAdapter struct {
	client  *mcclient.Client
	session *mcclient.ClientSession
}

type CloudRegion struct {
	RegionId string `json:"region_id"`
}

// NewCloudpodsAdapter 创建一个新的 Cloudpods 适配器实例
func NewCloudpodsAdapter() *CloudpodsAdapter {

	client := mcclient.NewClient(
		options.Options.AuthURL,
		options.Options.Timeout,
		false,
		true,
		"",
		"",
	)

	return &CloudpodsAdapter{
		client: client,
	}
}

// authenticate 实现 Cloudpods 的认证逻辑，例如获取访问令牌
func (a *CloudpodsAdapter) authenticate(ak string, sk string) (mcclient.TokenCredential, error) {
	if a.session != nil {
		return a.session.GetToken(), nil
	}

	token, err := a.client.AuthenticateByAccessKey(ak, sk, "")
	if err != nil {
		return nil, err
	}

	return token, nil
}

func (a *CloudpodsAdapter) getSession(ctx context.Context, ak string, sk string) (*mcclient.ClientSession, error) {
	// 若工具未传入 ak/sk，则使用连接时 Header 中的 AK/SK（与 Cursor/Claude 配置一致）
	if ak == "" && sk == "" {
		ak, sk = GetAKSKFromContext(ctx)
	}
	var userCred mcclient.TokenCredential
	if auth.IsAuthed() {
		userCred = policy.FetchUserCredential(ctx)
		if userCred != nil {
			log.Infof("getSessionWithUserCred: %v", userCred)
		} else {
			log.Infof("No userCred in context, will use ak/sk for authentication")
			token, err := a.authenticate(ak, sk)
			if err != nil {
				return nil, err
			}
			userCred = token
		}
		a.session = auth.GetSession(ctx, userCred, "")
	} else {
		token, err := a.authenticate(ak, sk)
		if err != nil {
			return nil, err
		}
		a.session = a.client.NewSession(
			context.Background(),
			"",
			"",
			api.EndpointInterfaceApigateway,
			token,
		)
	}
	return a.session, nil
}
