package oidc

import (
	"time"

	"forge.cadoles.com/cadoles/bouncer/internal/proxy/director/layer/authn"
	"forge.cadoles.com/cadoles/bouncer/internal/store"
	"github.com/pkg/errors"
)

type LayerOptions struct {
	authn.LayerOptions
	OIDC   OIDCOptions   `mapstructure:"oidc"`
	Cookie CookieOptions `mapstructure:"cookie"`
}

type OIDCOptions struct {
	ClientID               string            `mapstructure:"clientId"`
	ClientSecret           string            `mapstructure:"clientSecret"`
	PublicBaseURL          string            `mapstructure:"publicBaseURL"`
	LoginCallbackPath      string            `mapstructure:"loginCallbackPath"`
	MatchLoginCallbackPath string            `mapstructure:"matchLoginCallbackPath"`
	LogoutPath             string            `mapstructure:"logoutPath"`
	MatchLogoutPath        string            `mapstructure:"matchLogoutPath"`
	IssuerURL              string            `mapstructure:"issuerURL"`
	SkipIssuerVerification bool              `mapstructure:"skipIssuerVerification"`
	PostLogoutRedirectURLs []string          `mapstructure:"postLogoutRedirectURLs"`
	TLSInsecureSkipVerify  bool              `mapstructure:"tlsInsecureSkipVerify"`
	Scopes                 []string          `mapstructure:"scopes"`
	AuthParams             map[string]string `mapstructure:"authParams"`
}

type CookieOptions struct {
	Name     string        `mapstructure:"name"`
	Domain   string        `mapstructure:"domain"`
	Path     string        `mapstructure:"path"`
	SameSite string        `mapstructure:"sameSite"`
	Secure   bool          `mapstructure:"secure"`
	HTTPOnly bool          `mapstructure:"httpOnly"`
	MaxAge   time.Duration `mapstructure:"maxAge"`
}

func fromStoreOptions(storeOptions store.LayerOptions) (*LayerOptions, error) {
	loginCallbackPath := ".bouncer/authn/oidc/{{ .ProxyName }}/{{ .LayerName }}/callback"
	logoutPath := ".bouncer/authn/oidc/{{ .ProxyName }}/{{ .LayerName }}/logout"

	layerOptions := LayerOptions{
		LayerOptions: authn.DefaultLayerOptions(),
		OIDC: OIDCOptions{
			PublicBaseURL:          "",
			LoginCallbackPath:      loginCallbackPath,
			MatchLoginCallbackPath: "*" + loginCallbackPath,
			LogoutPath:             logoutPath,
			MatchLogoutPath:        "*" + logoutPath,
			Scopes:                 []string{"openid"},
		},
		Cookie: CookieOptions{
			Name:     "",
			Path:     "/",
			HTTPOnly: true,
			MaxAge:   time.Hour,
		},
	}

	if err := authn.FromStoreOptions(storeOptions, &layerOptions); err != nil {
		return nil, errors.WithStack(err)
	}

	return &layerOptions, nil
}