from typing import List, Optional
from sqlalchemy.orm import Session
from src.domain.interfaces.user_repository import UserRepository
from src.domain.entities.user import User
from src.infrastructure.models.user_model import UserModel

_RM_MIN_USER_TYPE = 5
_RM_EXCLUDED_USER_TYPES = [48, 49]

class SqlUserRepository(UserRepository):
    """
    SQLAlchemy Implementation for user repository.
    Reads from your existing Laravel mapped schema.
    """
    def __init__(self, db_session: Session):
        self.db = db_session

    def _to_entity(self, model: Optional[UserModel]) -> Optional[User]:
        if not model:
            return None
        return User(
            id=model.id,
            name=model.name,
            username=model.username,
            email=model.email,
            hashed_password=model.password,
            is_active=True,
            user_type=model.user_type,
        )

    def get_user_by_email(self, email: str) -> Optional[User]:
        model = self.db.query(UserModel).filter(UserModel.email == email).first()
        return self._to_entity(model)

    def get_user_by_username(self, username: str) -> Optional[User]:
        model = self.db.query(UserModel).filter(UserModel.username == username).first()
        return self._to_entity(model)

    def save(self, user: User) -> User:
        """
        Since we are just reading for login first, we can leave this unimplemented
        or map it for inserts later. We don't want to corrupt existing data initially.
        """
        raise NotImplementedError("SQL Writer not configured yet for safety.")

    def get_relationship_managers(self) -> List[User]:
        """
        Mirrors Laravel: User::where('user_type','>=',5)->whereNull('deleted_at')->get(['id','name'])
        Excludes user_type 48 (Merchant 2.0) and 49 (Agency test) as they are not RM roles.
        """
        models = (
            self.db.query(UserModel)
            .filter(
                UserModel.user_type >= _RM_MIN_USER_TYPE,
                UserModel.user_type.notin_(_RM_EXCLUDED_USER_TYPES),
                UserModel.deleted_at.is_(None),
            )
            .order_by(UserModel.name)
            .all()
        )
        return [self._to_entity(m) for m in models if m is not None]
