"""JWT token service.

⚠️ AUTO-GENERATED BY PRISM - DO NOT EDIT
Manages JWT token creation, verification, and decoding.
"""

from __future__ import annotations

from datetime import datetime, timedelta, timezone
from typing import Any

import jwt
from jwt.exceptions import InvalidTokenError

from {{ project_name }}.config import settings


class TokenService:
    """Handles JWT token creation and verification."""

    def __init__(self):
        """Initialize token service with configuration."""
        self.secret_key = settings.JWT_SECRET
        self.algorithm = "{{ algorithm }}"
        self.access_token_expire = timedelta(minutes={{ access_token_expire_minutes }})
        self.refresh_token_expire = timedelta(days={{ refresh_token_expire_days }})

    def create_access_token(
        self,
        user_id: int,
        roles: list[str] | None = None,
        extra_claims: dict[str, Any] | None = None,
    ) -> str:
        """Create a JWT access token.

        Args:
            user_id: User ID to encode in token
            roles: User roles for authorization
            extra_claims: Additional claims to include

        Returns:
            Encoded JWT token string
        """
        now = datetime.now(timezone.utc)
        expire = now + self.access_token_expire

        payload = {
            "sub": str(user_id),
            "type": "access",
            "iat": now,
            "exp": expire,
            "roles": roles or [],
        }

        if extra_claims:
            payload.update(extra_claims)

        return jwt.encode(payload, self.secret_key, algorithm=self.algorithm)

    def create_refresh_token(self, user_id: int) -> str:
        """Create a JWT refresh token.

        Refresh tokens have longer expiration and can only be used
        to obtain new access tokens.

        Args:
            user_id: User ID to encode in token

        Returns:
            Encoded JWT refresh token string
        """
        now = datetime.now(timezone.utc)
        expire = now + self.refresh_token_expire

        payload = {
            "sub": str(user_id),
            "type": "refresh",
            "iat": now,
            "exp": expire,
        }

        return jwt.encode(payload, self.secret_key, algorithm=self.algorithm)

    def verify_token(self, token: str, token_type: str = "access") -> dict[str, Any]:
        """Verify and decode a JWT token.

        Args:
            token: The JWT token to verify
            token_type: Expected token type ("access" or "refresh")

        Returns:
            Decoded token payload

        Raises:
            InvalidTokenError: If token is invalid, expired, or wrong type
        """
        try:
            payload = jwt.decode(
                token,
                self.secret_key,
                algorithms=[self.algorithm],
            )

            if payload.get("type") != token_type:
                raise InvalidTokenError(f"Invalid token type. Expected {token_type}")

            return payload
        except InvalidTokenError:
            raise

    def decode_token(self, token: str) -> dict[str, Any]:
        """Decode token without verification.

        ⚠️ Use with caution - does not verify signature or expiration.
        Only use for debugging or non-security-critical operations.

        Args:
            token: The JWT token to decode

        Returns:
            Decoded token payload
        """
        return jwt.decode(
            token,
            options={"verify_signature": False},
            algorithms=[self.algorithm],
        )


# Singleton instance
token_service = TokenService()
