"""تولید و اعتبارسنجی JWT محلی برای کاربران OTP."""
from __future__ import annotations

from datetime import datetime, timedelta, timezone
from uuid import UUID

import jwt

from app.core.config import settings
from app.models.enums import UserRole
from shared.exceptions import UnauthorizedError
from shared.security import CurrentUser

OTP_ISSUER = "core-service-otp"


class TokenService:
    def create_access_token(
        self,
        *,
        user_id: UUID,
        mobile: str,
        role: UserRole,
    ) -> tuple[str, int]:
        expires_in = settings.jwt_access_token_expire_seconds
        now = datetime.now(timezone.utc)
        payload = {
            "sub": str(user_id),
            "preferred_username": mobile,
            "realm_access": {"roles": [role.value]},
            "iss": OTP_ISSUER,
            "aud": settings.jwt_audience,
            "iat": int(now.timestamp()),
            "exp": int((now + timedelta(seconds=expires_in)).timestamp()),
        }
        token = jwt.encode(payload, settings.jwt_secret, algorithm="HS256")
        return token, expires_in

    def validate_access_token(self, token: str) -> CurrentUser:
        try:
            claims = jwt.decode(
                token,
                settings.jwt_secret,
                algorithms=["HS256"],
                audience=settings.jwt_audience,
                issuer=OTP_ISSUER,
            )
        except jwt.PyJWTError as exc:
            raise UnauthorizedError(f"توکن نامعتبر است: {exc}") from exc

        realm_access = claims.get("realm_access") or {}
        roles = list(realm_access.get("roles", [])) if isinstance(realm_access, dict) else []
        return CurrentUser(
            user_id=str(claims.get("sub", "")),
            username=claims.get("preferred_username"),
            roles=roles,
        )

    def create_refresh_token(self, user_id: UUID) -> str:
        expires_in = settings.jwt_refresh_token_expire_seconds
        now = datetime.now(timezone.utc)
        payload = {
            "sub": str(user_id),
            "type": "refresh",
            "iss": OTP_ISSUER,
            "iat": int(now.timestamp()),
            "exp": int((now + timedelta(seconds=expires_in)).timestamp()),
        }
        return jwt.encode(payload, settings.jwt_secret, algorithm="HS256")

    def validate_refresh_token(self, token: str) -> UUID:
        try:
            claims = jwt.decode(
                token,
                settings.jwt_secret,
                algorithms=["HS256"],
                issuer=OTP_ISSUER,
            )
        except jwt.PyJWTError as exc:
            raise UnauthorizedError(f"توکن refresh نامعتبر است: {exc}") from exc
        if claims.get("type") != "refresh":
            raise UnauthorizedError("توکن refresh نامعتبر است")
        return UUID(str(claims["sub"]))
