# app/modules/tenancy/services/user_auth_service.py
"""
Service for user-level auth operations: password reset, email verification.

Handles:
- Password reset token creation, validation, and password update
- Email verification token creation and resend logic
"""

import logging

from sqlalchemy import select
from sqlalchemy.orm import Session

from app.modules.tenancy.exceptions import InvalidTokenException
from app.modules.tenancy.models import User
from app.modules.tenancy.models.email_verification_token import EmailVerificationToken
from app.modules.tenancy.models.user_password_reset_token import UserPasswordResetToken
from middleware.auth import AuthManager

logger = logging.getLogger(__name__)


class UserAuthService:
    """Service for user password reset and email verification."""

    def __init__(self):
        self.auth_manager = AuthManager()

    def request_password_reset(self, db: Session, email: str) -> tuple[User | None, str | None]:
        """
        Create a password reset token for a user by email.

        Returns (user, plaintext_token) if user exists and is active,
        otherwise (None, None).
        """
        user = db.execute(
            select(User).where(User.email == email)
        ).scalar_one_or_none()

        if not user or not user.is_active:
            return None, None

        plaintext_token = UserPasswordResetToken.create_for_user(db, user.id)
        return user, plaintext_token

    def reset_password(self, db: Session, token: str, new_password: str) -> User:
        """
        Validate reset token and set new password.

        Args:
            db: Database session
            token: Plaintext reset token
            new_password: New password to set

        Returns:
            The user whose password was reset

        Raises:
            InvalidTokenException: If token is invalid or expired
        """
        token_record = UserPasswordResetToken.find_valid_token(db, token)

        if not token_record:
            raise InvalidTokenException("Invalid or expired password reset token")

        user = token_record.user
        user.hashed_password = self.auth_manager.hash_password(new_password)
        token_record.mark_used(db)

        return user

    def request_verification_resend(self, db: Session, email: str) -> tuple[User | None, str | None]:
        """
        Create a new email verification token for an unverified user.

        Returns (user, plaintext_token) if user exists and is not yet verified,
        otherwise (None, None).
        """
        user = db.execute(
            select(User).where(User.email == email)
        ).scalar_one_or_none()

        if not user or user.is_email_verified:
            return None, None

        plaintext_token = EmailVerificationToken.create_for_user(db, user.id)
        return user, plaintext_token


user_auth_service = UserAuthService()
