package automation

import (
	"context"
	"fmt"
	"net/http"
	"net/url"
	"strings"
)

const automationRepositoryTokenScopeReadOnly = "read_only"

type AutomationRepositoryCredentialCheckRequest struct {
	WorkspaceID     string
	RepositoryOwner string
	RepositoryName  string
	GitRef          string
	CommitSHA       string
}

type AutomationRepositoryCredentialAvailability struct {
	RepoTokenAvailable bool   `json:"repo_token_available"`
	RepoTokenScope     string `json:"repo_token_scope,omitempty"`
}

type AutomationRepositoryCredentialChecker interface {
	CheckAutomationRepositoryCredential(ctx context.Context, request AutomationRepositoryCredentialCheckRequest) (AutomationRepositoryCredentialAvailability, error)
}

type AGSHTTPAutomationRepositoryCredentialChecker struct {
	Handler             http.Handler
	AuthHeader          string
	AuthorizationHeader string
}

func (c AGSHTTPAutomationRepositoryCredentialChecker) CheckAutomationRepositoryCredential(ctx context.Context, request AutomationRepositoryCredentialCheckRequest) (AutomationRepositoryCredentialAvailability, error) {
	availability := AutomationRepositoryCredentialAvailability{RepoTokenScope: automationRepositoryTokenScopeReadOnly}
	if c.Handler == nil || strings.TrimSpace(c.AuthorizationHeader) == "" {
		return availability, nil
	}
	owner := strings.TrimSpace(request.RepositoryOwner)
	repo := strings.TrimSpace(request.RepositoryName)
	ref := strings.TrimSpace(request.CommitSHA)
	if ref == "" {
		ref = strings.TrimSpace(request.GitRef)
	}
	if owner == "" || repo == "" || ref == "" {
		return availability, nil
	}
	resolver := AGSHTTPAutomationSourceResolver{Handler: c.Handler, AuthHeader: c.AuthHeader}
	path := "/api/v3/repos/" + url.PathEscape(owner) + "/" + url.PathEscape(repo) + "/commits/" + url.PathEscape(ref)
	status, _ := resolver.do(ctx, strings.TrimSpace(c.AuthorizationHeader), http.MethodGet, path)
	switch status {
	case http.StatusOK:
		availability.RepoTokenAvailable = true
		return availability, nil
	case http.StatusUnauthorized, http.StatusForbidden, http.StatusNotFound:
		return availability, nil
	default:
		return availability, fmt.Errorf("check automation repository credential via AGS: status %d", status)
	}
}
