from sqlalchemy.orm import Session
from typing import Optional, List
from datetime import datetime
from .models import Analyticsevent
from utils.utils import EventType


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


def list_all(
    db: Session,
    limit: int = 20,
    offset: int = 0,
    session_id: Optional[str] = None,
    event_type: Optional[EventType] = None,
    calculation_id: Optional[str] = None,
    start_date: Optional[datetime] = None,
    end_date: Optional[datetime] = None,
) -> List[Analyticsevent]:
    q = db.query(Analyticsevent)
    if session_id is not None:
        q = q.filter(Analyticsevent.session_id == session_id)
    if event_type is not None:
        q = q.filter(Analyticsevent.event_type == event_type)
    if calculation_id is not None:
        q = q.filter(Analyticsevent.calculation_id == calculation_id)
    if start_date is not None:
        q = q.filter(Analyticsevent.created_at >= start_date)
    if end_date is not None:
        q = q.filter(Analyticsevent.created_at <= end_date)
    return q.order_by(Analyticsevent.created_at.desc()).limit(limit).offset(offset).all()


def count_all(
    db: Session,
    session_id: Optional[str] = None,
    event_type: Optional[EventType] = None,
    calculation_id: Optional[str] = None,
    start_date: Optional[datetime] = None,
    end_date: Optional[datetime] = None,
) -> int:
    q = db.query(Analyticsevent.id)
    if session_id is not None:
        q = q.filter(Analyticsevent.session_id == session_id)
    if event_type is not None:
        q = q.filter(Analyticsevent.event_type == event_type)
    if calculation_id is not None:
        q = q.filter(Analyticsevent.calculation_id == calculation_id)
    if start_date is not None:
        q = q.filter(Analyticsevent.created_at >= start_date)
    if end_date is not None:
        q = q.filter(Analyticsevent.created_at <= end_date)
    return q.count()


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


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


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