package registry

import (
	"context"
	"fmt"
	"strings"
	"time"

	cr "github.com/aliyun/alibaba-cloud-sdk-go/services/cr_ee"
	"github.com/sandbox0-ai/sandbox0/infra-operator/api/config"
)

type aliyunProvider struct {
	cfg     config.RegistryAliyunConfig
	secrets secretReader
}

func (p *aliyunProvider) GetPushCredentials(ctx context.Context, req PushCredentialsRequest) (*Credential, error) {
	// TODO: add team-scoped ephemeral credentials similar to AWS AssumeRole + session policy.
	registry := normalizeRegistryHost(p.cfg.Registry)
	if registry == "" {
		return nil, fmt.Errorf("aliyun registry is required")
	}
	if p.cfg.Region == "" {
		return nil, fmt.Errorf("aliyun region is required")
	}
	if p.cfg.InstanceID == "" {
		return nil, fmt.Errorf("aliyun instanceId is required")
	}
	accessKey := strings.TrimSpace(p.cfg.AccessKeyID)
	secretKey := strings.TrimSpace(p.cfg.AccessKeySecret)
	if accessKey == "" || secretKey == "" {
		if strings.TrimSpace(p.cfg.CredentialsSecret) == "" {
			return nil, fmt.Errorf("aliyun credentials secret is required")
		}
		var err error
		accessKey, err = p.secrets.readRequired(ctx, p.cfg.CredentialsSecret, p.cfg.AccessKeyKey, "accessKeyId", "aliyun access key")
		if err != nil {
			return nil, err
		}
		secretKey, err = p.secrets.readRequired(ctx, p.cfg.CredentialsSecret, p.cfg.SecretKeyKey, "accessKeySecret", "aliyun secret key")
		if err != nil {
			return nil, err
		}
	}

	client, err := cr.NewClientWithAccessKey(p.cfg.Region, accessKey, secretKey)
	if err != nil {
		return nil, fmt.Errorf("create aliyun cr client: %w", err)
	}
	request := cr.CreateGetAuthorizationTokenRequest()
	request.Scheme = "https"
	request.InstanceId = p.cfg.InstanceID
	response, err := client.GetAuthorizationToken(request)
	if err != nil {
		return nil, fmt.Errorf("get aliyun authorization token: %w", err)
	}
	if response == nil {
		return nil, fmt.Errorf("aliyun authorization response is empty")
	}
	if !response.GetAuthorizationTokenIsSuccess {
		code := strings.TrimSpace(response.Code)
		if code == "" {
			code = "unknown_error"
		}
		return nil, fmt.Errorf("aliyun authorization request failed: %s", code)
	}
	expiresAt := time.Time{}
	if response.ExpireTime > 0 {
		expiresAt = time.UnixMilli(int64(response.ExpireTime))
	}

	return &Credential{
		Provider:     "aliyun",
		PushRegistry: registry,
		Username:     response.TempUsername,
		Password:     response.AuthorizationToken,
		ExpiresAt:    timePtr(expiresAt),
	}, nil
}
