//go:generate ${GOBIN}/dummygen -d=api_dummy.go -package=api ${GO_MODULE}/pkg/service/jump/api JumpServiceAPI
//go:generate ${GOBIN}/mockgen -destination api_mock.go -package=api ${GO_MODULE}/pkg/service/jump/api JumpServiceAPI
package api

import (
	"context"
	"fmt"
	"slices"

	jmpent "github.com/tidbcloud/devops/entity/jump"
)

type ListAuthorizationParam struct {
	Page              int // default 1
	PerPage           int // default 20
	Phase             *jmpent.AuthorizationPhase
	Applicant         *string
	DestinationTypeIs *jmpent.DestinationType
	DestinationIDLike *string
	ShowUnaccessible  *bool
}

func (l ListAuthorizationParam) Normalize() (ListAuthorizationParam, error) {
	if l.Page < 0 {
		l.Page = 1
	}
	if l.PerPage < 0 {
		l.PerPage = 20
	}
	if l.Phase != nil && !slices.Contains(jmpent.AuthorizationPhaseValues, *l.Phase) {
		return ListAuthorizationParam{}, fmt.Errorf("invalid phase value: %s", *l.Phase)
	}

	return l, nil
}

type CreateAuthorizationParam struct {
	Applicant           string                     `json:"applicant"`
	Privilege           jmpent.JumpPrivilege       `json:"privilege"`
	Expiration          jmpent.JumpExpiration      `json:"expiration"`
	Reason              string                     `json:"reason"`
	EnableGatewayAccess bool                       `json:"enable_gateway_access"`
	Destinations        []*jmpent.DestinationUnion `json:"destination"`
}

type CancelAuthorizaitonParam struct {
	Force   bool `json:"force"`
	Timeout int  `json:"timeout"`
}

type JumpServiceAPI interface {
	ListAuthorizations(ctx context.Context, param ListAuthorizationParam) ([]*jmpent.Authorization, int64, error)
	GetAuthorization(ctx context.Context, id uint64) (*jmpent.Authorization, error)
	CreateAuthorization(ctx context.Context, param CreateAuthorizationParam) (*uint64, error)
	CancelAuthorizaiton(ctx context.Context, id uint64, param CancelAuthorizaitonParam) error

	// GetUser returns the userid in jump server of the given email.
	// If the user does not exist, return (nil, nil).
	GetUser(ctx context.Context, email string) (*string /* userid */, error)
	InitUser(ctx context.Context, email string) error

	GetConnection(ctx context.Context, id uint64, applicant string, method jmpent.ConnectionMethod) (*jmpent.Connection, error)
	ListAvailableDestinations(ctx context.Context, typ jmpent.DestinationType) ([]string, error)
}
