package auth

import (
	"time"

	"github.com/go-webauthn/webauthn/webauthn"
)

type Role string

const (
	RoleViewer Role = "viewer"
	RoleEditor Role = "editor"
	RoleAdmin  Role = "admin"
)

type Scope string

const (
	ScopeDocsRead  Scope = "docs:read"
	ScopeDocsWrite Scope = "docs:write"
	ScopeSyncRead  Scope = "sync:read"
	ScopeSyncWrite Scope = "sync:write"
	ScopeAdmin     Scope = "admin"
)

type Permission string

const (
	PermissionNone  Permission = ""
	PermissionRead  Permission = "read"
	PermissionWrite Permission = "write"
	PermissionAdmin Permission = "admin"
)

type ResourceType string

const (
	ResourceGlobal     ResourceType = "global"
	ResourceCollection ResourceType = "collection"
	ResourceDocument   ResourceType = "document"
	ResourceFolder     ResourceType = "folder"
)

type Principal struct {
	UserID      string    `json:"userId"`
	Email       string    `json:"email"`
	DisplayName string    `json:"displayName"`
	Role        Role      `json:"role"`
	Scopes      []Scope   `json:"scopes,omitempty"`
	Method      string    `json:"method"`
	SessionID   string    `json:"sessionId,omitempty"`
	APIKeyID    string    `json:"apiKeyId,omitempty"`
	ExpiresAt   time.Time `json:"expiresAt,omitempty"`
}

type User struct {
	ID           string
	Email        string
	DisplayName  string
	Role         Role
	Disabled     bool
	PasswordHash string
	CreatedAt    time.Time
	LastSeenAt   time.Time
	Credentials  []webauthn.Credential
}

type UserAccessUpdate struct {
	ID       string `json:"id"`
	Role     Role   `json:"role"`
	Disabled bool   `json:"disabled"`
}

type ResourcePermission struct {
	ID           string       `json:"id"`
	UserID       string       `json:"userId"`
	UserEmail    string       `json:"userEmail,omitempty"`
	UserName     string       `json:"userName,omitempty"`
	ResourceType ResourceType `json:"resourceType"`
	ResourceID   string       `json:"resourceId"`
	Permission   Permission   `json:"permission"`
	GrantedBy    string       `json:"grantedBy,omitempty"`
	CreatedAt    time.Time    `json:"createdAt"`
}

type ResourcePermissionUpdate struct {
	UserID     string     `json:"userId"`
	Permission Permission `json:"permission"`
}

type PasswordResetToken struct {
	ID          string
	UserID      string
	TokenHash   string
	CreatedAt   time.Time
	ExpiresAt   time.Time
	UsedAt      *time.Time
	InitiatedBy string
}

func (u User) WebAuthnID() []byte {
	return []byte(u.ID)
}

func (u User) WebAuthnName() string {
	return u.Email
}

func (u User) WebAuthnDisplayName() string {
	if u.DisplayName != "" {
		return u.DisplayName
	}
	return u.Email
}

func (u User) WebAuthnCredentials() []webauthn.Credential {
	return u.Credentials
}

type Session struct {
	ID        string
	UserID    string
	TokenHash string
	CreatedAt time.Time
	ExpiresAt time.Time
	RevokedAt *time.Time
}

type APIKey struct {
	ID         string     `json:"id"`
	UserID     string     `json:"userId"`
	Name       string     `json:"name"`
	KeyHash    string     `json:"-"`
	Scopes     []Scope    `json:"scopes"`
	CreatedAt  time.Time  `json:"createdAt"`
	ExpiresAt  *time.Time `json:"expiresAt,omitempty"`
	LastUsedAt *time.Time `json:"lastUsedAt,omitempty"`
	RevokedAt  *time.Time `json:"revokedAt,omitempty"`
}

type CreatedAPIKey struct {
	Record APIKey `json:"record"`
	Token  string `json:"token"`
}

type InstanceSettings struct {
	SetupComplete  bool `json:"setupComplete"`
	SignupsEnabled bool `json:"signupsEnabled"`
}

type DeviceCode struct {
	ID              string
	UserID          string
	DeviceCodeHash  string
	UserCodeHash    string
	UserCodeDisplay string
	Name            string
	Scopes          []Scope
	Status          string
	CreatedAt       time.Time
	ExpiresAt       time.Time
	ApprovedAt      *time.Time
	LastPolledAt    *time.Time
}

type DeviceStart struct {
	DeviceCode              string `json:"deviceCode"`
	UserCode                string `json:"userCode"`
	VerificationURI         string `json:"verificationUri"`
	VerificationURIComplete string `json:"verificationUriComplete"`
	ExpiresIn               int    `json:"expiresIn"`
	Interval                int    `json:"interval"`
}
