package barcode

import (
	"github.com/ory/fosite/compose"
	"github.com/ory/fosite/handler/oauth2"
	"github.com/ory/fosite/handler/openid"

	iamConfig "edge-infra.dev/pkg/edge/iam/config"
	"edge-infra.dev/pkg/edge/iam/device"
	"edge-infra.dev/pkg/edge/iam/profile"
	"edge-infra.dev/pkg/edge/iam/prometheus"
	"edge-infra.dev/pkg/edge/iam/session"
)

var (
	signInBarcode      = "sign_in_barcode"
	signUpBarcode      = "sign_up_barcode"
	signUpBarcodeScope = "sign_up_barcode_scope"
)

// CodeGrantFactory builds a fosite handler for the barcode_code flow
func CodeGrantFactory(_ *compose.Config, storage interface{}, _ interface{}) interface{} {
	return &CodeGrantHandler{
		BarcodeStrategy: &OpaqueStrategy{},
		SignedStrategy: &SignedStrategy{
			HMACStrategy: iamConfig.HMACStrategy(),
		},
		BarcodeStorage:          storage.(Storage),
		BarcodeCodeHMACStrategy: iamConfig.HMACStrategy(),
		Metrics:                 prometheus.NewMetrics(),
	}
}

func ScopeFactory(_ *compose.Config, storage interface{}, _ interface{}) interface{} {
	return &ScopeHandler{
		BarcodeGenStrategy: &OpaqueStrategy{},
		BarcodeStorage:     storage.(Storage),
		Metrics:            prometheus.NewMetrics(),
	}
}

// GrantFactory builds a fosite handler for the barcode flow
func GrantFactory(config *compose.Config, storage interface{}, strategy interface{}) interface{} {
	return &GrantHandler{
		BarcodeStrategy:   &OpaqueStrategy{},
		LoginHintStrategy: iamConfig.HMACStrategy(),
		SignedStrategy: &SignedStrategy{
			HMACStrategy: iamConfig.HMACStrategy(),
		},
		BarcodeStorage:       storage.(Storage),
		AccessTokenStrategy:  strategy.(oauth2.AccessTokenStrategy),
		ScopeStrategy:        config.GetScopeStrategy(),
		AccessTokenStorage:   storage.(oauth2.AccessTokenStorage),
		ProfileStorage:       storage.(profile.Storage),
		DeviceStorage:        storage.(device.Storage),
		LoginSessionStorage:  storage.(session.LoginSessionStorage),
		ProfileTTL:           iamConfig.GetProfileTTL(),
		BarcodeLength:        iamConfig.GetBarcodeLength(),
		RefreshTokenStrategy: strategy.(oauth2.RefreshTokenStrategy),
		RefreshTokenStorage:  storage.(oauth2.RefreshTokenStorage),
		RefreshTokenScopes:   config.GetRefreshTokenScopes(),
		RevocationStorage:    storage.(oauth2.TokenRevocationStorage),
		IDTokenHandleHelper:  &openid.IDTokenHandleHelper{IDTokenStrategy: strategy.(openid.OpenIDConnectTokenStrategy)},
		Metrics:              prometheus.NewMetrics(),
	}
}