package oidc_provider

import (
	"fmt"
	"net/url"
	"os"

	"github.com/go-resty/resty/v2"
	"github.com/juju/errors"
	"github.com/tidbcloud/auto-deploy/internal/utils"
)

const (
	ENVIROMENT_GITHUB_ID_TOKEN_URL      = "ACTIONS_ID_TOKEN_REQUEST_URL"   // provided by github
	ENVIROMENT_GITHUB_ID_TOKEN          = "ACTIONS_ID_TOKEN_REQUEST_TOKEN" // provided by github
	ENVIROMENT_GITHUB_RUN_ID            = "GITHUB_RUN_ID"                  // provided by github
	ENVIROMENT_GITHUB_ID_TOKEN_AUDIENCE = "ACTIONS_ID_TOKEN_AUDIENCE"      // Not supported by github, provided by workflow

	DEFAULT_AUDIENCE = "auto-deploy-cli"
)

type githubOidcProvider struct {
	client *resty.Client
}

type githubTokenResponse struct {
	Count int    `json:"count"`
	Value string `json:"value"`
}

func (p *githubOidcProvider) GetTokenUrl() string {
	tokenUrl := os.Getenv(ENVIROMENT_GITHUB_ID_TOKEN_URL)
	audience := os.Getenv(ENVIROMENT_GITHUB_ID_TOKEN_AUDIENCE)
	if audience == "" {
		audience = DEFAULT_AUDIENCE
	}
	return tokenUrl + "&audience=" + url.QueryEscape(audience)
}

func (p *githubOidcProvider) GetToken() string {
	token := os.Getenv(ENVIROMENT_GITHUB_ID_TOKEN)
	utils.MaskSensitiveGithubOutput(token)
	return token
}
func (p *githubOidcProvider) GetIdToken() (string, error) {
	var result githubTokenResponse
	req := p.client.R().SetResult(&result)
	req.Header.Add("Authorization", fmt.Sprintf("bearer %s", p.GetToken()))
	_, err := req.Get(p.GetTokenUrl())
	if err != nil {
		return "", errors.Annotatef(err, "Failed to get github id token")
	}

	utils.MaskSensitiveGithubOutput(result.Value)
	return result.Value, nil
}

func (p *githubOidcProvider) IsFake() bool {
	return false
}
func (p *githubOidcProvider) GetRunID() string {
	return os.Getenv(ENVIROMENT_GITHUB_RUN_ID)
}
func (p *githubOidcProvider) GetEnvMap() map[string]string {
	return map[string]string{
		ENVIROMENT_GITHUB_ID_TOKEN_URL: p.GetTokenUrl(),
		ENVIROMENT_GITHUB_ID_TOKEN:     p.GetToken(),
	}
}
