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


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


def list_all(db: Session, limit: int = 20, offset: int = 0, **filters) -> List[Cancellation]:
    query = db.query(Cancellation)
    
    if "user_id" in filters and filters["user_id"]:
        query = query.filter(Cancellation.user_id == filters["user_id"])
    
    if "booking_id" in filters and filters["booking_id"]:
        query = query.filter(Cancellation.booking_id == filters["booking_id"])
    
    if "refund_status" in filters and filters["refund_status"]:
        query = query.filter(Cancellation.refund_status == filters["refund_status"])
    
    return query.order_by(Cancellation.created_at.desc()).limit(limit).offset(offset).all()


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


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


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


def get_with_details(db: Session, cancellation_id: str) -> Optional[Cancellation]:
    return (
        db.query(Cancellation)
        .options(
            joinedload(Cancellation.booking)
                .joinedload("schedule")
                .joinedload("bus"),
            joinedload(Cancellation.booking)
                .joinedload("schedule")
                .joinedload("route"),
            joinedload(Cancellation.user)
        )
        .filter(Cancellation.id == cancellation_id)
        .first()
    )