"""CRUD operations for database access."""

from sqlalchemy.orm import Session
from sqlalchemy import desc, func, or_
from typing import List, Optional, Tuple
import time
import json

from app.database import Event, Session as SessionModel, Statistics, ToolUsage
from app.schemas import EventCreate


def create_event(db: Session, event: EventCreate) -> Event:
    """
    Create a new event and update statistics.

    Args:
        db: Database session
        event: Event data to create

    Returns:
        Created event object
    """
    # Convert tool_input to JSON string if it's a dict
    tool_input_str = None
    if event.tool_input is not None:
        if isinstance(event.tool_input, str):
            tool_input_str = event.tool_input
        else:
            tool_input_str = json.dumps(event.tool_input)

    # Generate description if not provided
    description = event.description
    if not description:
        description = _generate_description(event)

    # Create event
    db_event = Event(
        session_id=event.session_id,
        event_type=event.event_type,
        tool_name=event.tool_name,
        tool_input=tool_input_str,
        tool_output=event.tool_output,
        success=event.success,
        description=description,
        timestamp=event.timestamp,
    )
    db.add(db_event)

    # Update or create session
    session = db.query(SessionModel).filter(SessionModel.session_id == event.session_id).first()
    if not session:
        session = SessionModel(
            session_id=event.session_id,
            started_at=event.timestamp,
            event_count=1,
        )
        db.add(session)
    else:
        session.event_count += 1
        if event.event_type == "SessionEnd":
            session.ended_at = event.timestamp

    # Update tool usage for tool events
    if event.tool_name:
        tool_usage = db.query(ToolUsage).filter(ToolUsage.tool_name == event.tool_name).first()
        if not tool_usage:
            tool_usage = ToolUsage(
                tool_name=event.tool_name,
                usage_count=1,
                first_used=event.timestamp,
                last_used=event.timestamp,
            )
            db.add(tool_usage)
        else:
            tool_usage.usage_count += 1
            tool_usage.last_used = event.timestamp

    # Update statistics
    _update_statistics(db)

    db.commit()
    db.refresh(db_event)
    return db_event


def get_events(
    db: Session,
    skip: int = 0,
    limit: int = 50,
    event_type: Optional[str] = None,
    session_id: Optional[str] = None,
    tool_name: Optional[str] = None,
) -> Tuple[List[Event], int]:
    """
    Get paginated list of events with optional filtering.

    Args:
        db: Database session
        skip: Number of records to skip (offset)
        limit: Maximum number of records to return
        event_type: Filter by event type
        session_id: Filter by session ID
        tool_name: Filter by tool name

    Returns:
        Tuple of (events list, total count)
    """
    query = db.query(Event)

    # Apply filters
    if event_type:
        # Support filtering by multiple event types (comma-separated)
        if "," in event_type:
            event_types = [et.strip() for et in event_type.split(",")]
            query = query.filter(Event.event_type.in_(event_types))
        else:
            query = query.filter(Event.event_type == event_type)

    if session_id:
        query = query.filter(Event.session_id == session_id)

    if tool_name:
        query = query.filter(Event.tool_name == tool_name)

    # Get total count
    total = query.count()

    # Order by timestamp descending (newest first) and apply pagination
    events = query.order_by(desc(Event.timestamp)).offset(skip).limit(limit).all()

    return events, total


def get_event_by_id(db: Session, event_id: int) -> Optional[Event]:
    """Get a single event by ID."""
    return db.query(Event).filter(Event.id == event_id).first()


def delete_all_events(db: Session) -> None:
    """Delete all events and reset statistics (for Reset Stats functionality)."""
    # Delete all events
    db.query(Event).delete()

    # Delete all sessions
    db.query(SessionModel).delete()

    # Delete all tool usage
    db.query(ToolUsage).delete()

    # Reset statistics
    stats = db.query(Statistics).first()
    if stats:
        stats.total_events = 0
        stats.total_tools_used = 0
        stats.total_agents = 0
        stats.total_sessions = 0
        stats.last_updated = time.time()

    db.commit()


def get_statistics(db: Session) -> Statistics:
    """Get current statistics."""
    stats = db.query(Statistics).first()
    if not stats:
        # Initialize if not exists
        stats = Statistics(
            id=1,
            total_events=0,
            total_tools_used=0,
            total_agents=0,
            total_sessions=0,
            last_updated=time.time(),
        )
        db.add(stats)
        db.commit()
        db.refresh(stats)
    return stats


def get_tool_usage(db: Session) -> List[ToolUsage]:
    """Get tool usage statistics."""
    return db.query(ToolUsage).order_by(desc(ToolUsage.usage_count)).all()


def get_sessions(db: Session, limit: int = 100) -> List[SessionModel]:
    """Get list of sessions."""
    return db.query(SessionModel).order_by(desc(SessionModel.started_at)).limit(limit).all()


# Helper functions
def _update_statistics(db: Session) -> None:
    """Update cached statistics."""
    stats = db.query(Statistics).first()
    if not stats:
        stats = Statistics(id=1)
        db.add(stats)

    # Count events
    stats.total_events = db.query(Event).count()

    # Count unique tools
    stats.total_tools_used = db.query(ToolUsage).count()

    # Count agents (SubagentStop events)
    stats.total_agents = db.query(Event).filter(Event.event_type == "SubagentStop").count()

    # Count sessions
    stats.total_sessions = db.query(SessionModel).count()

    # Update timestamp
    stats.last_updated = time.time()


def _generate_description(event: EventCreate) -> str:
    """Generate a human-readable description for an event."""
    if event.description:
        return event.description

    # Generate description based on event type
    if event.event_type == "PreToolUse":
        if event.tool_name:
            return f"Preparing to use {event.tool_name}"
        return "Preparing to use tool"

    elif event.event_type == "PostToolUse":
        if event.tool_name:
            status = "successfully" if event.success else "with errors"
            return f"Executed {event.tool_name} {status}"
        return "Tool execution completed"

    elif event.event_type == "SessionStart":
        return "Session started"

    elif event.event_type == "SessionEnd":
        return "Session ended"

    elif event.event_type == "SubagentStop":
        return "Agent completed task"

    elif event.event_type == "UserPromptSubmit":
        return "User submitted prompt"

    else:
        return f"{event.event_type} event"
