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


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


def list_all(
    db: Session,
    limit: int = 20,
    offset: int = 0,
    reporter_id: Optional[str] = None,
    reported_user_id: Optional[str] = None,
    reported_listing_id: Optional[str] = None,
    status: Optional[str] = None,
    report_type: Optional[str] = None,
) -> List[Report]:
    query = db.query(Report)
    
    if reporter_id:
        query = query.filter(Report.reporter_id == reporter_id)
    if reported_user_id:
        query = query.filter(Report.reported_user_id == reported_user_id)
    if reported_listing_id:
        query = query.filter(Report.reported_listing_id == reported_listing_id)
    if status:
        query = query.filter(Report.status == status)
    if report_type:
        query = query.filter(Report.report_type == report_type)
    
    return query.order_by(Report.created_at.desc()).limit(limit).offset(offset).all()


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


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


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


def get_with_details(db: Session, entity_id: str) -> Optional[Report]:
    return (
        db.query(Report)
        .options(
            joinedload(Report.reporter),
            joinedload(Report.reported_user),
            joinedload(Report.reported_listing),
            joinedload(Report.reviewed_by),
        )
        .filter(Report.id == entity_id)
        .first()
    )