//! Session database operations

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use uuid::Uuid;

/// Session record from database
#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
pub struct DbSession {
    pub id: Uuid,
    pub machine_id: Option<Uuid>,
    pub started_at: DateTime<Utc>,
    pub ended_at: Option<DateTime<Utc>>,
    pub duration_secs: Option<i32>,
    pub is_support_session: bool,
    pub support_code: Option<String>,
    pub status: String,
}

/// Create a new session record
pub async fn create_session(
    pool: &PgPool,
    session_id: Uuid,
    machine_id: Uuid,
    is_support_session: bool,
    support_code: Option<&str>,
) -> Result<DbSession, sqlx::Error> {
    sqlx::query_as::<_, DbSession>(
        r#"
        INSERT INTO connect_sessions (id, machine_id, is_support_session, support_code, status)
        VALUES ($1, $2, $3, $4, 'active')
        RETURNING *
        "#,
    )
    .bind(session_id)
    .bind(machine_id)
    .bind(is_support_session)
    .bind(support_code)
    .fetch_one(pool)
    .await
}

/// End a session
pub async fn end_session(
    pool: &PgPool,
    session_id: Uuid,
    status: &str,  // 'ended' or 'disconnected' or 'timeout'
) -> Result<(), sqlx::Error> {
    sqlx::query(
        r#"
        UPDATE connect_sessions SET
            ended_at = NOW(),
            duration_secs = EXTRACT(EPOCH FROM (NOW() - started_at))::INTEGER,
            status = $1
        WHERE id = $2
        "#,
    )
    .bind(status)
    .bind(session_id)
    .execute(pool)
    .await?;
    Ok(())
}

/// Get session by ID
pub async fn get_session(pool: &PgPool, session_id: Uuid) -> Result<Option<DbSession>, sqlx::Error> {
    sqlx::query_as::<_, DbSession>("SELECT * FROM connect_sessions WHERE id = $1")
        .bind(session_id)
        .fetch_optional(pool)
        .await
}

/// Get active sessions for a machine
pub async fn get_active_sessions_for_machine(
    pool: &PgPool,
    machine_id: Uuid,
) -> Result<Vec<DbSession>, sqlx::Error> {
    sqlx::query_as::<_, DbSession>(
        "SELECT * FROM connect_sessions WHERE machine_id = $1 AND status = 'active' ORDER BY started_at DESC"
    )
    .bind(machine_id)
    .fetch_all(pool)
    .await
}

/// Get recent sessions (for dashboard)
pub async fn get_recent_sessions(
    pool: &PgPool,
    limit: i64,
) -> Result<Vec<DbSession>, sqlx::Error> {
    sqlx::query_as::<_, DbSession>(
        "SELECT * FROM connect_sessions ORDER BY started_at DESC LIMIT $1"
    )
    .bind(limit)
    .fetch_all(pool)
    .await
}

/// Get all sessions for a machine (for history export)
pub async fn get_sessions_for_machine(
    pool: &PgPool,
    machine_id: Uuid,
) -> Result<Vec<DbSession>, sqlx::Error> {
    sqlx::query_as::<_, DbSession>(
        "SELECT * FROM connect_sessions WHERE machine_id = $1 ORDER BY started_at DESC"
    )
    .bind(machine_id)
    .fetch_all(pool)
    .await
}
