  # #region auth_service [C:5] [TYPE Module] [SEMANTICS sqlalchemy, auth, credential, session, jwt]
  # @defgroup Services Module group.
  # @BRIEF Orchestrates credential authentication and ADFS JIT user provisioning.
  # @LAYER     Domain
  # @RELATION DEPENDS_ON -> [AuthRepository]
  # @RELATION DEPENDS_ON -> [verify_password]
  # @RELATION DEPENDS_ON -> [create_access_token]
  # @RELATION DEPENDS_ON -> [User]
  # @RELATION DEPENDS_ON -> [Role]
  # @INVARIANT  Authentication succeeds only for active users with valid credentials; issued sessions encode subject and scopes from assigned roles.
  # @PRE        Core auth models and security utilities available.
  # @POST       User identity verified and session tokens issued according to role scopes.
  # @SIDE_EFFECT  Writes last login timestamps and JIT-provisions external users.
  # @DATA_CONTRACT  [Credentials | ADFSClaims] -> [UserEntity | SessionToken]
  
> from datetime import UTC, datetime
> from typing import Any
  
> from sqlalchemy.orm import Session
  
> from ..core.auth.jwt import create_access_token
> from ..core.auth.logger import log_security_event
> from ..core.auth.repository import AuthRepository
> from ..core.auth.security import verify_password
> from ..core.logger import belief_scope
> from ..models.auth import User
  
  
  # #region AuthService [C:3] [TYPE Class]
  # @defgroup Services Module group.
  # @BRIEF Provides high-level authentication services.
  # @RELATION DEPENDS_ON -> [AuthRepository]
  # @RELATION DEPENDS_ON -> [User]
  # @RELATION DEPENDS_ON -> [Role]
> class AuthService:
      # region AuthService_init [TYPE Function]
      # @PURPOSE: Initializes the authentication service with repository access over an active DB session.
      # @PRE  db is a valid SQLAlchemy Session instance bound to the auth persistence context.
      # @POST  self.repo is initialized and ready for auth user/role CRUD operations.
      # @SIDE_EFFECT  Allocates AuthRepository and binds it to the provided Session.
      # @DATA_CONTRACT  Input(Session) -> Model(AuthRepository)
      # @PARAM  db (Session) - SQLAlchemy session.
>     def __init__(self, db: Session):
>         self.db = db
>         self.repo = AuthRepository(db)
  
      # endregion AuthService_init
  
      # region AuthService.authenticate_user [TYPE Function]
      # @PURPOSE: Validates credentials and account state for local username/password authentication.
      # @PRE  username and password are non-empty credential inputs.
      # @POST  Returns User only when user exists, is active, and password hash verification succeeds; otherwise returns None.
      # @SIDE_EFFECT  Persists last_login update for successful authentications via repository.
      # @DATA_CONTRACT  Input(str username, str password) -> Output(User | None)
      # @RELATION DEPENDS_ON ->[AuthRepository]
      # @RELATION CALLS ->[verify_password]
      # @RELATION DEPENDS_ON ->[User]
      # @PARAM  username (str) - The username.
      # @PARAM  password (str) - The plain password.
      # @RETURN  Optional[User] - The authenticated user or None.
>     def authenticate_user(self, username: str, password: str) -> User | None:
>         with belief_scope("auth.authenticate_user"):
>             user = self.repo.get_user_by_username(username)
>             if not user or not user.is_active:
>                 return None
  
>             if not verify_password(password, user.password_hash):
>                 return None
  
              # Update last login
>             user.last_login = datetime.now(UTC)
>             self.db.commit()
>             self.db.refresh(user)
  
>             return user
  
      # endregion AuthService.authenticate_user
  
      # region AuthService.create_session [TYPE Function]
      # @PURPOSE: Issues an access token payload for an already authenticated user.
      # @PRE  user is a valid User entity containing username and iterable roles with role.name values.
      # @POST  Returns session dict with non-empty access_token and token_type='bearer'.
      # @SIDE_EFFECT  Generates signed JWT via auth JWT provider.
      # @DATA_CONTRACT  Input(User) -> Output(Dict[str, str]{access_token, token_type})
      # @RELATION CALLS ->[create_access_token]
      # @RELATION DEPENDS_ON ->[User]
      # @RELATION DEPENDS_ON ->[Role]
      # @PARAM  user (User) - The authenticated user.
      # @RETURN  Dict[str, str] - Session data.
>     def create_session(self, user: User) -> dict[str, str]:
>         with belief_scope("auth.create_session"):
>             roles = [role.name for role in user.roles]
>             access_token = create_access_token(
>                 data={"sub": user.username, "scopes": roles}
>             )
>             return {"access_token": access_token, "token_type": "bearer"}
  
      # endregion AuthService.create_session
  
      # region AuthService.provision_adfs_user [TYPE Function]
      # @PURPOSE: Performs ADFS Just-In-Time provisioning and role synchronization from AD group mappings.
      # @PRE  user_info contains identity claims where at least one of 'upn' or 'email' is present; 'groups' may be absent.
      # @POST  Returns persisted user entity with roles synchronized to mapped AD groups and refreshed state.
      # @SIDE_EFFECT  May insert new User, mutate user.roles, commit transaction, and refresh ORM state.
      # @DATA_CONTRACT  Input(Dict[str, Any]{upn|email, email, groups[]}) -> Output(User persisted)
      # @RELATION DEPENDS_ON ->[AuthRepository]
      # @RELATION DEPENDS_ON ->[User]
      # @RELATION DEPENDS_ON ->[Role]
      # @PARAM  user_info (Dict[str, Any]) - Claims from ADFS token.
      # @RETURN  User - The provisioned user.
>     def provision_adfs_user(self, user_info: dict[str, Any]) -> User:
>         with belief_scope("auth.provision_adfs_user"):
>             username = user_info.get("upn") or user_info.get("email")
>             email = user_info.get("email")
>             groups = user_info.get("groups", [])
  
>             user = self.repo.get_user_by_username(username)
>             if not user:
>                 user = User(
>                     username=username,
>                     email=email,
>                     full_name=user_info.get("name"),
>                     auth_source="ADFS",
>                     is_active=True,
>                     is_ad_user=True,
>                 )
>                 self.db.add(user)
>                 log_security_event("USER_PROVISIONED", username, {"source": "ADFS"})
  
              # Sync roles from AD groups
>             mapped_roles = self.repo.get_roles_by_ad_groups(groups)
>             user.roles = mapped_roles
  
>             user.last_login = datetime.now(UTC)
>             self.db.commit()
>             self.db.refresh(user)
  
>             return user
  
      # endregion AuthService.provision_adfs_user
  
  
  # #endregion AuthService
  
  # #endregion auth_service
