from sqlalchemy.orm import Session, joinedload
from typing import Optional, List
from .models import User, Useractivity
from datetime import datetime


# User repository functions
def get_by_id(db: Session, entity_id: str) -> Optional[User]:
    return db.query(User).filter(User.id == entity_id).first()


def get_by_email(db: Session, email: str) -> Optional[User]:
    return db.query(User).filter(User.email == email.lower()).first()


def list_all(db: Session, limit: int = 20, offset: int = 0, **filters) -> List[User]:
    query = db.query(User)
    
    if "role" in filters and filters["role"]:
        query = query.filter(User.role == filters["role"])
    
    if "status" in filters and filters["status"]:
        query = query.filter(User.status == filters["status"])
    
    if "search" in filters and filters["search"]:
        search_term = f"%{filters['search']}%"
        query = query.filter(
            (User.email.ilike(search_term)) |
            (User.first_name.ilike(search_term)) |
            (User.last_name.ilike(search_term))
        )
    
    return query.order_by(User.created_at.desc()).limit(limit).offset(offset).all()


def create(db: Session, data: dict) -> User:
    user = User(**data)
    db.add(user)
    db.flush()
    return user


def update(db: Session, entity_id: str, data: dict) -> Optional[User]:
    user = get_by_id(db, entity_id)
    if not user:
        return None
    
    for key, value in data.items():
        setattr(user, key, value)
    
    db.flush()
    return user


def delete(db: Session, entity_id: str) -> bool:
    user = get_by_id(db, entity_id)
    if not user:
        return False
    
    db.delete(user)
    db.flush()
    return True


def update_last_login(db: Session, user_id: str) -> Optional[User]:
    user = get_by_id(db, user_id)
    if not user:
        return None
    
    user.last_login_date = datetime.utcnow()
    db.flush()
    return user


# UserActivity repository functions
def get_activity_by_id(db: Session, entity_id: str) -> Optional[Useractivity]:
    return db.query(Useractivity).filter(Useractivity.id == entity_id).first()


def list_all_activities(db: Session, limit: int = 20, offset: int = 0, **filters) -> List[Useractivity]:
    query = db.query(Useractivity)
    
    if "user_id" in filters and filters["user_id"]:
        query = query.filter(Useractivity.user_id == filters["user_id"])
    
    if "stock_id" in filters and filters["stock_id"]:
        query = query.filter(Useractivity.stock_id == filters["stock_id"])
    
    if "activity_type" in filters and filters["activity_type"]:
        query = query.filter(Useractivity.activity_type == filters["activity_type"])
    
    if "session_id" in filters and filters["session_id"]:
        query = query.filter(Useractivity.session_id == filters["session_id"])
    
    return query.order_by(Useractivity.timestamp.desc()).limit(limit).offset(offset).all()


def create_activity(db: Session, data: dict) -> Useractivity:
    activity = Useractivity(**data)
    db.add(activity)
    db.flush()
    return activity


def update_activity(db: Session, entity_id: str, data: dict) -> Optional[Useractivity]:
    activity = get_activity_by_id(db, entity_id)
    if not activity:
        return None
    
    for key, value in data.items():
        setattr(activity, key, value)
    
    db.flush()
    return activity


def delete_activity(db: Session, entity_id: str) -> bool:
    activity = get_activity_by_id(db, entity_id)
    if not activity:
        return False
    
    db.delete(activity)
    db.flush()
    return True


def get_user_activities_with_stock(db: Session, user_id: str, limit: int = 20, offset: int = 0) -> List[Useractivity]:
    from stock_management.models import Stock
    
    return (
        db.query(Useractivity)
        .options(joinedload(Useractivity.stock))
        .filter(Useractivity.user_id == user_id)
        .order_by(Useractivity.timestamp.desc())
        .limit(limit)
        .offset(offset)
        .all()
    )