// Package server_api contains internal APIs that are used by server/kas code.
package server_api //nolint:staticcheck

import (
	"crypto/sha256"

	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/api"
	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/gitaly/vendored/gitalypb"
	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/pkg/entity"
)

const (
	// AgentNameRegex
	// https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/identity_and_auth.md#agent-identity-and-name
	AgentNameRegex = `[a-z0-9](?:[-a-z0-9]*[a-z0-9])?`
	tokenKeyLength = 20
)

// AgentInfo is an interface to represent information about different types of agent.
type AgentInfo interface {
	AgentKey() api.AgentKey
}

type ProjectInfo struct {
	ProjectID  int64
	GitalyInfo *entity.GitalyInfo
	Repository *gitalypb.Repository
	// DefaultBranch is the name of the default branch in a repository.
	DefaultBranch string
}

func AgentToken2key(token api.AgentToken) []byte {
	// We use only the first 20 bytes or half the length of the token (depending on what is longer)
	// as a key or fallback to the total length of the key, if it's shorter.
	// Under the assumption of a randomly generated token of length at least 40 (routable tokens),
	// with an alphabet of at least
	//
	// - upper-case characters (26)
	// - lower-case characters (26),
	// - numbers (10),
	//
	// (see https://gitlab.com/gitlab-org/gitlab/blob/master/app/models/clusters/agent_token.rb)
	//
	// we have at least 62^20 different possible token prefixes. Since the token is
	// randomly generated, to obtain the token from this hash, one would have to
	// also guess the second half, and validate it by attempting to log in (kas
	// cannot validate tokens on its own)
	n := min(max(tokenKeyLength, len(token)/2), len(token))
	tokenHash := sha256.Sum256([]byte(token[:n]))
	return tokenHash[:]
}
