package models

import (
	"time"

	"github.com/google/uuid"
)

// OAuthClient represents a registered OAuth 2.0 client application
type OAuthClient struct {
	ID           uuid.UUID  `json:"id" db:"id"`
	ClientID     string     `json:"client_id" db:"client_id"`
	ClientSecret string     `json:"-" db:"client_secret"` // Never expose in JSON
	Name         string     `json:"name" db:"name"`
	Description  *string    `json:"description,omitempty" db:"description"`
	RedirectURIs []string   `json:"redirect_uris" db:"redirect_uris"` // JSON array
	Scopes       []string   `json:"scopes" db:"scopes"`               // Allowed scopes
	GrantTypes   []string   `json:"grant_types" db:"grant_types"`     // authorization_code, refresh_token
	IsPublic     bool       `json:"is_public" db:"is_public"`         // Public clients (SPAs) don't have secret
	IsActive     bool       `json:"is_active" db:"is_active"`
	CreatedBy    *uuid.UUID `json:"created_by,omitempty" db:"created_by"`
	CreatedAt    time.Time  `json:"created_at" db:"created_at"`
	UpdatedAt    time.Time  `json:"updated_at" db:"updated_at"`
}

// OAuthAuthorizationCode represents an authorization code for the OAuth flow
type OAuthAuthorizationCode struct {
	ID                  uuid.UUID  `json:"id" db:"id"`
	Code                string     `json:"-" db:"code"` // Hashed
	ClientID            string     `json:"client_id" db:"client_id"`
	UserID              uuid.UUID  `json:"user_id" db:"user_id"`
	RedirectURI         string     `json:"redirect_uri" db:"redirect_uri"`
	Scopes              []string   `json:"scopes" db:"scopes"`
	CodeChallenge       *string    `json:"-" db:"code_challenge"`        // For PKCE
	CodeChallengeMethod *string    `json:"-" db:"code_challenge_method"` // S256 or plain
	ExpiresAt           time.Time  `json:"expires_at" db:"expires_at"`
	UsedAt              *time.Time `json:"used_at,omitempty" db:"used_at"`
	CreatedAt           time.Time  `json:"created_at" db:"created_at"`
}

// OAuthAccessToken represents an OAuth access token
type OAuthAccessToken struct {
	ID        uuid.UUID  `json:"id" db:"id"`
	TokenHash string     `json:"-" db:"token_hash"`
	ClientID  string     `json:"client_id" db:"client_id"`
	UserID    uuid.UUID  `json:"user_id" db:"user_id"`
	Scopes    []string   `json:"scopes" db:"scopes"`
	ExpiresAt time.Time  `json:"expires_at" db:"expires_at"`
	RevokedAt *time.Time `json:"revoked_at,omitempty" db:"revoked_at"`
	CreatedAt time.Time  `json:"created_at" db:"created_at"`
}

// OAuthRefreshToken represents an OAuth refresh token
type OAuthRefreshToken struct {
	ID            uuid.UUID  `json:"id" db:"id"`
	TokenHash     string     `json:"-" db:"token_hash"`
	AccessTokenID uuid.UUID  `json:"access_token_id" db:"access_token_id"`
	ClientID      string     `json:"client_id" db:"client_id"`
	UserID        uuid.UUID  `json:"user_id" db:"user_id"`
	Scopes        []string   `json:"scopes" db:"scopes"`
	ExpiresAt     time.Time  `json:"expires_at" db:"expires_at"`
	RevokedAt     *time.Time `json:"revoked_at,omitempty" db:"revoked_at"`
	CreatedAt     time.Time  `json:"created_at" db:"created_at"`
}

// OAuthAuthorizeRequest for the authorization endpoint
type OAuthAuthorizeRequest struct {
	ResponseType        string `form:"response_type" binding:"required"` // Must be "code"
	ClientID            string `form:"client_id" binding:"required"`
	RedirectURI         string `form:"redirect_uri" binding:"required"`
	Scope               string `form:"scope"`                            // Space-separated scopes
	State               string `form:"state" binding:"required"`         // CSRF protection
	CodeChallenge       string `form:"code_challenge"`                   // PKCE
	CodeChallengeMethod string `form:"code_challenge_method"`            // S256 (recommended) or plain
}

// OAuthTokenRequest for the token endpoint
type OAuthTokenRequest struct {
	GrantType    string `form:"grant_type" binding:"required"` // authorization_code or refresh_token
	Code         string `form:"code"`                          // For authorization_code grant
	RedirectURI  string `form:"redirect_uri"`                  // For authorization_code grant
	ClientID     string `form:"client_id" binding:"required"`
	ClientSecret string `form:"client_secret"`                 // For confidential clients
	CodeVerifier string `form:"code_verifier"`                 // For PKCE
	RefreshToken string `form:"refresh_token"`                 // For refresh_token grant
	Scope        string `form:"scope"`                         // For refresh_token grant (optional)
}

// OAuthTokenResponse for successful token requests
type OAuthTokenResponse struct {
	AccessToken  string `json:"access_token"`
	TokenType    string `json:"token_type"` // Always "Bearer"
	ExpiresIn    int    `json:"expires_in"` // Seconds until expiration
	RefreshToken string `json:"refresh_token,omitempty"`
	Scope        string `json:"scope,omitempty"`
}

// OAuthErrorResponse for OAuth errors (RFC 6749)
type OAuthErrorResponse struct {
	Error            string `json:"error"`
	ErrorDescription string `json:"error_description,omitempty"`
	ErrorURI         string `json:"error_uri,omitempty"`
}
