package domain

import (
	"strings"
	"time"
)

const (
	MetadataHeadlessLoginEnabled             = "headless_login_enabled"
	MetadataHeadlessTokenEndpointAuthMethod  = "headless_token_endpoint_auth_method"
	MetadataHeadlessJWKSURI                  = "headless_jwks_uri"
	MetadataHeadlessJWKS                     = "headless_jwks"
	MetadataRequestObjectSigningAlg          = "request_object_signing_alg"
	MetadataIDTokenClaims                    = "id_token_claims"
	MetadataBackChannelLogoutURI             = "backchannel_logout_uri"
	MetadataBackChannelLogoutSessionRequired = "backchannel_logout_session_required"
	MetadataAutoLoginSupported               = "auto_login_supported"
	MetadataAutoLoginURL                     = "auto_login_url"
)

type HydraClient struct {
	ClientID                         string         `json:"client_id"`
	ClientName                       string         `json:"client_name,omitempty"`
	ClientSecret                     string         `json:"client_secret,omitempty"` // Added
	ClientURI                        string         `json:"client_uri,omitempty"`
	RedirectURIs                     []string       `json:"redirect_uris,omitempty"`
	GrantTypes                       []string       `json:"grant_types,omitempty"`
	ResponseTypes                    []string       `json:"response_types,omitempty"`
	Scope                            string         `json:"scope,omitempty"`
	TokenEndpointAuthMethod          string         `json:"token_endpoint_auth_method,omitempty"`
	SkipConsent                      *bool          `json:"skip_consent,omitempty"`
	JWKSUri                          string         `json:"jwks_uri,omitempty"`
	JWKS                             any            `json:"jwks,omitempty"`
	BackChannelLogoutURI             string         `json:"backchannel_logout_uri,omitempty"`
	BackChannelLogoutSessionRequired *bool          `json:"backchannel_logout_session_required,omitempty"`
	Metadata                         map[string]any `json:"metadata,omitempty"`
}

func (c *HydraClient) SupportsHeadlessLogin() bool {
	// Headless login now supports jwksUri only.
	hasPublicKey := c.HeadlessJWKSURI() != ""
	isPrivateKeyJwt := c.HeadlessTokenEndpointAuthMethod() == "private_key_jwt"
	return hasPublicKey && isPrivateKeyJwt
}

func (c *HydraClient) HeadlessTokenEndpointAuthMethod() string {
	if c.Metadata != nil {
		if raw, ok := c.Metadata[MetadataHeadlessTokenEndpointAuthMethod].(string); ok {
			if value := strings.TrimSpace(raw); value != "" {
				return value
			}
		}
	}
	return strings.TrimSpace(c.TokenEndpointAuthMethod)
}

func (c *HydraClient) HeadlessJWKSURI() string {
	if c.Metadata != nil {
		if raw, ok := c.Metadata[MetadataHeadlessJWKSURI].(string); ok {
			if value := strings.TrimSpace(raw); value != "" {
				return value
			}
		}
	}
	return strings.TrimSpace(c.JWKSUri)
}

func (c *HydraClient) HeadlessJWKS() any {
	if c.Metadata != nil {
		if value, ok := c.Metadata[MetadataHeadlessJWKS]; ok && value != nil {
			return value
		}
	}
	return c.JWKS
}

func (c *HydraClient) IsHeadlessLoginEnabled() bool {
	if !c.SupportsHeadlessLogin() {
		return false
	}
	if c.Metadata == nil {
		return false
	}
	val, ok := c.Metadata[MetadataHeadlessLoginEnabled]
	if !ok {
		return false
	}
	if b, ok := val.(bool); ok {
		return b
	}
	return false
}

func (c *HydraClient) BackchannelLogoutURI() string {
	if c.Metadata != nil {
		if raw, ok := c.Metadata[MetadataBackChannelLogoutURI].(string); ok {
			if value := strings.TrimSpace(raw); value != "" {
				return value
			}
		}
	}
	return strings.TrimSpace(c.BackChannelLogoutURI)
}

func (c *HydraClient) BackchannelLogoutSessionRequiredValue() bool {
	if c.Metadata != nil {
		if raw, ok := c.Metadata[MetadataBackChannelLogoutSessionRequired].(bool); ok {
			return raw
		}
	}
	if c.BackChannelLogoutSessionRequired != nil {
		return *c.BackChannelLogoutSessionRequired
	}
	return false
}

type HydraConsentRequest struct {
	Challenge         string      `json:"challenge"`
	RequestedScope    []string    `json:"requested_scope"`
	RequestedAudience []string    `json:"requested_access_token_audience"`
	Skip              bool        `json:"skip"`
	Subject           string      `json:"subject"`
	Client            HydraClient `json:"client"`
}

type HydraLoginRequest struct {
	Challenge string      `json:"challenge"`
	Subject   string      `json:"subject"`
	Skip      bool        `json:"skip"`
	Client    HydraClient `json:"client"`
}

type HydraConsentSession struct {
	ConsentRequestID string               `json:"consent_request_id,omitempty"`
	Subject          string               `json:"subject,omitempty"`
	GrantedScope     []string             `json:"grant_scope,omitempty"`
	GrantedAudience  []string             `json:"grant_access_token_audience,omitempty"`
	Remember         bool                 `json:"remember"`
	RememberFor      int                  `json:"remember_for,omitempty"`
	AuthenticatedAt  *time.Time           `json:"authenticated_at,omitempty"`
	RequestedAt      *time.Time           `json:"requested_at,omitempty"`
	HandledAt        *time.Time           `json:"handled_at,omitempty"`
	Client           HydraClient          `json:"client"`
	ConsentRequest   *HydraConsentRequest `json:"consent_request,omitempty"`
}
