use sqlx::PgPool; use uuid::Uuid; use anyhow::Result; use crate::models::server::{ServerConnection, ServerConfig, GameAdmin}; /// Get the server connection for a license. pub async fn get_server_connection(pool: &PgPool, license_id: Uuid) -> Result> { let conn = sqlx::query_as::<_, ServerConnection>( "SELECT id, license_id, connection_type, panel_api_endpoint, panel_api_key_encrypted, \ panel_server_identifier, companion_agent_token, companion_last_seen, plugin_last_seen, \ server_ip, server_port, game_port, connection_status, created_at, updated_at \ FROM server_connections WHERE license_id = $1", ) .bind(license_id) .fetch_optional(pool) .await?; Ok(conn) } /// Create a new server connection. pub async fn create_server_connection( pool: &PgPool, license_id: Uuid, connection_type: &str, server_ip: Option<&str>, server_port: Option, game_port: Option, ) -> Result { let row: (Uuid,) = sqlx::query_as( "INSERT INTO server_connections (license_id, connection_type, server_ip, server_port, game_port) \ VALUES ($1, $2, $3, $4, $5) RETURNING id", ) .bind(license_id) .bind(connection_type) .bind(server_ip) .bind(server_port) .bind(game_port) .fetch_one(pool) .await?; Ok(row.0) } /// Update server connection status. pub async fn update_connection_status(pool: &PgPool, license_id: Uuid, status: &str) -> Result<()> { sqlx::query( "UPDATE server_connections SET connection_status = $1, updated_at = NOW() WHERE license_id = $2", ) .bind(status) .bind(license_id) .execute(pool) .await?; Ok(()) } /// Get the server config for a license. pub async fn get_server_config(pool: &PgPool, license_id: Uuid) -> Result> { let config = sqlx::query_as::<_, ServerConfig>( "SELECT id, license_id, server_name, max_players, world_size, current_seed, \ current_map_id, server_description, server_url, server_header_image, tags, \ auto_restart_enabled, auto_restart_cron, auto_restart_timezone, \ crash_recovery_enabled, crash_recovery_max_attempts, crash_recovery_cooldown_minutes, \ force_wipe_eligible, auto_update_on_force_wipe, config_overrides, \ created_at, updated_at \ FROM server_config WHERE license_id = $1", ) .bind(license_id) .fetch_optional(pool) .await?; Ok(config) } /// Create a default server config for a license. pub async fn create_server_config( pool: &PgPool, license_id: Uuid, server_name: &str, ) -> Result { let row: (Uuid,) = sqlx::query_as( "INSERT INTO server_config (license_id, server_name) VALUES ($1, $2) RETURNING id", ) .bind(license_id) .bind(server_name) .fetch_one(pool) .await?; Ok(row.0) } /// Update server config fields. pub async fn update_server_config( pool: &PgPool, license_id: Uuid, server_name: Option<&str>, max_players: Option, world_size: Option, current_seed: Option, ) -> Result<()> { // Dynamic update — only modify provided fields if let Some(name) = server_name { sqlx::query("UPDATE server_config SET server_name = $1, updated_at = NOW() WHERE license_id = $2") .bind(name) .bind(license_id) .execute(pool) .await?; } if let Some(mp) = max_players { sqlx::query("UPDATE server_config SET max_players = $1, updated_at = NOW() WHERE license_id = $2") .bind(mp) .bind(license_id) .execute(pool) .await?; } if let Some(ws) = world_size { sqlx::query("UPDATE server_config SET world_size = $1, updated_at = NOW() WHERE license_id = $2") .bind(ws) .bind(license_id) .execute(pool) .await?; } if let Some(seed) = current_seed { sqlx::query("UPDATE server_config SET current_seed = $1, updated_at = NOW() WHERE license_id = $2") .bind(seed) .bind(license_id) .execute(pool) .await?; } Ok(()) } /// Get all game admins for a license. pub async fn get_game_admins(pool: &PgPool, license_id: Uuid) -> Result> { let admins = sqlx::query_as::<_, GameAdmin>( "SELECT id, license_id, steam_id, display_name, admin_level, permissions, added_by, created_at \ FROM game_admins WHERE license_id = $1 ORDER BY created_at", ) .bind(license_id) .fetch_all(pool) .await?; Ok(admins) } /// Add a game admin. pub async fn create_game_admin( pool: &PgPool, license_id: Uuid, steam_id: &str, display_name: &str, admin_level: &str, added_by: Uuid, ) -> Result { let row: (Uuid,) = sqlx::query_as( "INSERT INTO game_admins (license_id, steam_id, display_name, admin_level, added_by) \ VALUES ($1, $2, $3, $4, $5) RETURNING id", ) .bind(license_id) .bind(steam_id) .bind(display_name) .bind(admin_level) .bind(added_by) .fetch_one(pool) .await?; Ok(row.0) } /// Remove a game admin. pub async fn delete_game_admin(pool: &PgPool, admin_id: Uuid) -> Result<()> { sqlx::query("DELETE FROM game_admins WHERE id = $1") .bind(admin_id) .execute(pool) .await?; Ok(()) }