"""
Data models and DTOs for the FreeExile Account Management System.
Conforms to Python 3.11+ dataclasses with slots and strict typing.
"""

from __future__ import annotations
import enum
import time
from typing import Dict, List, Optional
from dataclasses import dataclass, field


class AccountStatus(enum.Enum):
    UNSPECIFIED = 0
    PENDING_ACTIVATION = 1
    ACTIVE = 2
    SUSPENDED = 3
    BANNED = 4


class Role(enum.Enum):
    PLAYER = "player"
    MODERATOR = "moderator"
    GM = "gm"
    ADMIN = "admin"


class OAuthProviderType(enum.Enum):
    UNSPECIFIED = 0
    GOOGLE = 1
    APPLE = 2
    FACEBOOK = 3


@dataclass(slots=True, frozen=True)
class OAuthIdentity:
    """External OAuth identity binding."""
    provider: OAuthProviderType
    provider_user_id: str
    email: str
    linked_at: float = field(default_factory=time.time)


@dataclass(slots=True)
class Account:
    """Core game account entity."""
    account_id: str
    email: str
    username: str
    password_hash: str
    status: AccountStatus = AccountStatus.PENDING_ACTIVATION
    roles: List[str] = field(default_factory=lambda: ["player"])
    created_at: float = field(default_factory=time.time)
    last_login_at: Optional[float] = None
    failed_login_attempts: int = 0
    lockout_until: Optional[float] = None
    oauth_identities: Dict[OAuthProviderType, OAuthIdentity] = field(default_factory=dict)

    def is_locked(self, current_time: Optional[float] = None) -> bool:
        if self.lockout_until is None:
            return False
        now = current_time if current_time is not None else time.time()
        return now < self.lockout_until

    def is_active(self) -> bool:
        return self.status == AccountStatus.ACTIVE


@dataclass(slots=True, frozen=True)
class AuthTokenPair:
    """JWT Access and Refresh token pair."""
    access_token: str
    refresh_token: str
    expires_in_seconds: int = 900  # 15 minutes default
    token_type: str = "Bearer"


@dataclass(slots=True, frozen=True)
class AccountRegistrationResult:
    """Result of a quick registration attempt."""
    success: bool
    message: str
    account_id: Optional[str] = None
    requires_verification: bool = True
    code_expires_in_seconds: int = 900


@dataclass(slots=True, frozen=True)
class EmailVerificationResult:
    """Result of an email activation attempt."""
    success: bool
    message: str
    account_id: Optional[str] = None
    access_token: Optional[str] = None
    refresh_token: Optional[str] = None
    expires_in_seconds: int = 900


@dataclass(slots=True, frozen=True)
class LoginResult:
    """Result of an account login attempt."""
    success: bool
    message: str
    access_token: Optional[str] = None
    refresh_token: Optional[str] = None
    account_id: Optional[str] = None
    username: Optional[str] = None
    status: Optional[AccountStatus] = None
    requires_captcha: bool = False
    remember_token: Optional[str] = None


@dataclass(slots=True, frozen=True)
class RefreshTokenResult:
    """Result of a token refresh attempt."""
    success: bool
    message: str
    access_token: Optional[str] = None
    refresh_token: Optional[str] = None
    expires_in_seconds: int = 900


@dataclass(slots=True, frozen=True)
class OAuthLoginResult:
    """Result of an OAuth authentication attempt."""
    success: bool
    message: str
    access_token: Optional[str] = None
    refresh_token: Optional[str] = None
    account_id: Optional[str] = None
    username: Optional[str] = None
    is_new_account: bool = False
