"""
Recovery key used to obtain access token.

Recovery key has a token string, date of creation, optional date of expiration and optional count of uses left.
"""

from datetime import datetime, timezone
import secrets
from typing import Optional
from pydantic import BaseModel
from mnemonic import Mnemonic

from selfprivacy_api.models.tokens.time import is_past, ensure_timezone


class RecoveryKey(BaseModel):
    """
    Recovery key used to obtain access token.

    Recovery key has a key string, date of creation, optional date of expiration and optional count of uses left.
    """

    key: str
    created_at: datetime
    expires_at: Optional[datetime]
    uses_left: Optional[int]

    def is_valid(self) -> bool:
        """
        Check if the recovery key is valid.
        """
        if self.expires_at is not None and is_past(self.expires_at):
            return False
        if self.uses_left is not None and self.uses_left <= 0:
            return False
        return True

    def as_mnemonic(self) -> str:
        """
        Get the recovery key as a mnemonic.
        """
        return Mnemonic(language="english").to_mnemonic(bytes.fromhex(self.key))

    @staticmethod
    def generate(
        expiration: Optional[datetime],
        uses_left: Optional[int],
    ) -> "RecoveryKey":
        """
        Factory to generate a random token.
        If passed naive time as expiration, assumes utc
        """
        creation_date = datetime.now(timezone.utc)
        if expiration is not None:
            expiration = ensure_timezone(expiration)
        key = secrets.token_bytes(24).hex()
        return RecoveryKey(
            key=key,
            created_at=creation_date,
            expires_at=expiration,
            uses_left=uses_left,
        )