//! Session query types and builders.
//!
//! This module provides types for querying sessions:
//! - [`SessionOrder`]: Field to order results by
//! - [`SessionQuery`]: Fluent builder for constructing queries

use chrono::{DateTime, Utc};

use super::super::Order;

/// Sort order for session queries
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum SessionOrder {
    /// Order by session start time (default: newest first)
    #[default]
    StartedAt,
    /// Order by last activity time
    LastActivity,
    /// Order by total cost
    Cost,
}

/// Query builder for session retrieval.
///
/// `SessionQuery` provides a fluent API for constructing session queries
/// with filters, ordering, and pagination.
///
/// Default ordering is newest first (descending by started_at).
#[derive(Clone)]
pub struct SessionQuery {
    /// Filter by machine_id (for multi-machine scenarios)
    pub machine_id: Option<String>,

    /// Filter by framework (claude, cursor, gemini, codex)
    pub framework: Option<String>,

    /// Filter to only active sessions (ended_at IS NULL)
    pub active_only: bool,

    /// Filter sessions with activity after this timestamp
    pub active_since: Option<DateTime<Utc>>,

    /// Filter sessions started after this timestamp
    pub started_after: Option<DateTime<Utc>>,

    /// Filter sessions started before this timestamp
    pub started_before: Option<DateTime<Utc>>,

    /// Filter by GitHub repository (owner/repo format)
    pub github_repo: Option<String>,

    /// Filter by GitHub issue number
    pub github_issue: Option<i32>,

    /// Filter by GitHub PR number
    pub github_pr: Option<i32>,

    /// Maximum number of sessions to return
    pub limit: Option<usize>,

    /// Order by field
    pub order_by: SessionOrder,

    /// Sort direction (default: Desc for newest first)
    pub direction: Order,
}

impl Default for SessionQuery {
    fn default() -> Self {
        Self {
            machine_id: None,
            framework: None,
            active_only: false,
            active_since: None,
            started_after: None,
            started_before: None,
            github_repo: None,
            github_issue: None,
            github_pr: None,
            limit: None,
            order_by: SessionOrder::default(),
            direction: Order::Desc, // Default to newest first
        }
    }
}

impl SessionQuery {
    /// Create a new empty query (defaults to recent sessions first)
    pub fn new() -> Self {
        Self::default()
    }

    /// Filter to only active sessions
    pub fn active_only(mut self) -> Self {
        self.active_only = true;
        self
    }

    /// Filter by machine_id (for multi-machine scenarios)
    pub fn with_machine_id(mut self, machine_id: impl Into<String>) -> Self {
        self.machine_id = Some(machine_id.into());
        self
    }

    /// Filter by framework
    pub fn with_framework(mut self, framework: impl Into<String>) -> Self {
        self.framework = Some(framework.into());
        self
    }

    /// Filter sessions with activity since the given timestamp
    pub fn with_active_since(mut self, ts: DateTime<Utc>) -> Self {
        self.active_since = Some(ts);
        self
    }

    /// Filter sessions started after the given timestamp
    pub fn with_started_after(mut self, ts: DateTime<Utc>) -> Self {
        self.started_after = Some(ts);
        self
    }

    /// Filter sessions started before the given timestamp
    pub fn with_started_before(mut self, ts: DateTime<Utc>) -> Self {
        self.started_before = Some(ts);
        self
    }

    /// Filter by GitHub repository (owner/repo format)
    pub fn with_github_repo(mut self, repo: impl Into<String>) -> Self {
        self.github_repo = Some(repo.into());
        self
    }

    /// Filter by GitHub issue number
    pub fn with_github_issue(mut self, issue: i32) -> Self {
        self.github_issue = Some(issue);
        self
    }

    /// Filter by GitHub PR number
    pub fn with_github_pr(mut self, pr: i32) -> Self {
        self.github_pr = Some(pr);
        self
    }

    /// Set the maximum number of sessions to return
    pub fn with_limit(mut self, limit: usize) -> Self {
        self.limit = Some(limit);
        self
    }

    /// Order by the given field
    pub fn with_order_by(mut self, order: SessionOrder) -> Self {
        self.order_by = order;
        self
    }

    /// Set the sort direction (Asc/Desc).
    ///
    /// This method is consistent with `EventQuery::with_direction()`.
    pub fn with_direction(mut self, direction: Order) -> Self {
        self.direction = direction;
        self
    }

    /// Set ascending order (convenience method).
    ///
    /// Equivalent to `.with_direction(Order::Asc)`.
    pub fn ascending(self) -> Self {
        self.with_direction(Order::Asc)
    }

    /// Set descending order (convenience method).
    ///
    /// Equivalent to `.with_direction(Order::Desc)`.
    pub fn descending(self) -> Self {
        self.with_direction(Order::Desc)
    }
}
