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


def get_by_id(db: Session, activitylog_id: str) -> Optional[Activitylog]:
    return db.query(Activitylog).filter(Activitylog.id == activitylog_id).first()


def list_all(
    db: Session,
    limit: int = 20,
    offset: int = 0,
    entity_type: Optional[str] = None,
    entity_id: Optional[str] = None,
    user_id: Optional[str] = None,
    action_type: Optional[str] = None,
    start_date: Optional[datetime] = None,
    end_date: Optional[datetime] = None,
) -> List[Activitylog]:
    query = db.query(Activitylog)

    if entity_type:
        query = query.filter(Activitylog.entity_type == entity_type)
    if entity_id:
        query = query.filter(Activitylog.entity_id == entity_id)
    if user_id:
        query = query.filter(Activitylog.user_id == user_id)
    if action_type:
        query = query.filter(Activitylog.action_type == action_type)
    if start_date:
        query = query.filter(Activitylog.timestamp >= start_date)
    if end_date:
        query = query.filter(Activitylog.timestamp <= end_date)

    return query.order_by(Activitylog.timestamp.desc()).limit(limit).offset(offset).all()


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


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


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


def get_with_details(db: Session, activitylog_id: str) -> Optional[Activitylog]:
    return (
        db.query(Activitylog)
        .options(joinedload(Activitylog.user))
        .filter(Activitylog.id == activitylog_id)
        .first()
    )


def count_all(
    db: Session,
    entity_type: Optional[str] = None,
    entity_id: Optional[str] = None,
    user_id: Optional[str] = None,
    action_type: Optional[str] = None,
    start_date: Optional[datetime] = None,
    end_date: Optional[datetime] = None,
) -> int:
    query = db.query(Activitylog)

    if entity_type:
        query = query.filter(Activitylog.entity_type == entity_type)
    if entity_id:
        query = query.filter(Activitylog.entity_id == entity_id)
    if user_id:
        query = query.filter(Activitylog.user_id == user_id)
    if action_type:
        query = query.filter(Activitylog.action_type == action_type)
    if start_date:
        query = query.filter(Activitylog.timestamp >= start_date)
    if end_date:
        query = query.filter(Activitylog.timestamp <= end_date)

    return query.count()