//! Support code database operations use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use sqlx::PgPool; use uuid::Uuid; /// Support code record from database #[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)] pub struct DbSupportCode { pub id: Uuid, pub code: String, pub session_id: Option, pub created_by: String, pub created_at: DateTime, pub expires_at: Option>, pub status: String, pub client_name: Option, pub client_machine: Option, pub connected_at: Option>, } /// Create a new support code pub async fn create_support_code( pool: &PgPool, code: &str, created_by: &str, ) -> Result { sqlx::query_as::<_, DbSupportCode>( r#" INSERT INTO connect_support_codes (code, created_by, status) VALUES ($1, $2, 'pending') RETURNING * "#, ) .bind(code) .bind(created_by) .fetch_one(pool) .await } /// Get support code by code string pub async fn get_support_code(pool: &PgPool, code: &str) -> Result, sqlx::Error> { sqlx::query_as::<_, DbSupportCode>( "SELECT * FROM connect_support_codes WHERE code = $1" ) .bind(code) .fetch_optional(pool) .await } /// Update support code when client connects pub async fn mark_code_connected( pool: &PgPool, code: &str, session_id: Option, client_name: Option<&str>, client_machine: Option<&str>, ) -> Result<(), sqlx::Error> { sqlx::query( r#" UPDATE connect_support_codes SET status = 'connected', session_id = $1, client_name = $2, client_machine = $3, connected_at = NOW() WHERE code = $4 "#, ) .bind(session_id) .bind(client_name) .bind(client_machine) .bind(code) .execute(pool) .await?; Ok(()) } /// Mark support code as completed pub async fn mark_code_completed(pool: &PgPool, code: &str) -> Result<(), sqlx::Error> { sqlx::query("UPDATE connect_support_codes SET status = 'completed' WHERE code = $1") .bind(code) .execute(pool) .await?; Ok(()) } /// Mark support code as cancelled pub async fn mark_code_cancelled(pool: &PgPool, code: &str) -> Result<(), sqlx::Error> { sqlx::query("UPDATE connect_support_codes SET status = 'cancelled' WHERE code = $1") .bind(code) .execute(pool) .await?; Ok(()) } /// Get active support codes (pending or connected) pub async fn get_active_support_codes(pool: &PgPool) -> Result, sqlx::Error> { sqlx::query_as::<_, DbSupportCode>( "SELECT * FROM connect_support_codes WHERE status IN ('pending', 'connected') ORDER BY created_at DESC" ) .fetch_all(pool) .await } /// Check if code exists and is valid for connection pub async fn is_code_valid(pool: &PgPool, code: &str) -> Result { let result = sqlx::query_scalar::<_, bool>( "SELECT EXISTS(SELECT 1 FROM connect_support_codes WHERE code = $1 AND status = 'pending')" ) .bind(code) .fetch_one(pool) .await?; Ok(result) } /// Check if code is cancelled pub async fn is_code_cancelled(pool: &PgPool, code: &str) -> Result { let result = sqlx::query_scalar::<_, bool>( "SELECT EXISTS(SELECT 1 FROM connect_support_codes WHERE code = $1 AND status = 'cancelled')" ) .bind(code) .fetch_one(pool) .await?; Ok(result) } /// Link session to support code pub async fn link_session_to_code( pool: &PgPool, code: &str, session_id: Uuid, ) -> Result<(), sqlx::Error> { sqlx::query("UPDATE connect_support_codes SET session_id = $1 WHERE code = $2") .bind(session_id) .bind(code) .execute(pool) .await?; Ok(()) }