//! 管理员处理器

use axum::{
    extract::{Path, Query, State},
    http::StatusCode,
    response::IntoResponse,
    Json,
};
use serde::Serialize;
use std::sync::Arc;

use crate::models::{
    ApiResponse, DeviceResponse, PaginatedResponse, PaginationParams, SessionResponse,
    StatsResponse, UserResponse,
};
use crate::services::{
    auth::UserRepository,
    device::DeviceRepository,
    session::SessionRepository,
    AppState,
};
use super::{api_error, AdminUser};

/// 服务器配置响应
#[derive(Debug, Serialize)]
pub struct ServerConfigResponse {
    pub version: String,
    pub http_port: u16,
    pub stun_port: u16,
    pub stun_enabled: bool,
    pub stun_servers: Vec<String>,
    pub turn_port: u16,
    pub turn_enabled: bool,
    pub turn_server: Option<String>,
    pub turn_username: String,
    pub turn_realm: String,
    pub jwt_expiry_hours: i64,
    pub database_type: String,
}

/// 获取所有用户
pub async fn list_users(
    State(state): State<Arc<AppState>>,
    _admin: AdminUser,
    Query(params): Query<PaginationParams>,
) -> impl IntoResponse {
    let repo = UserRepository::new(&state.db);

    match repo.find_all(params.offset(), params.limit()).await {
        Ok((users, total)) => {
            let items: Vec<UserResponse> = users.into_iter().map(Into::into).collect();
            let total_pages = ((total as f64) / (params.limit() as f64)).ceil() as u32;

            let response = PaginatedResponse {
                items,
                total,
                page: params.page.unwrap_or(1),
                limit: params.limit(),
                total_pages,
            };

            (StatusCode::OK, Json(ApiResponse::ok(response))).into_response()
        }
        Err(e) => api_error(StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
    }
}

/// 删除用户
pub async fn delete_user(
    State(state): State<Arc<AppState>>,
    _admin: AdminUser,
    Path(user_id): Path<String>,
) -> impl IntoResponse {
    let repo = UserRepository::new(&state.db);

    match repo.delete(&user_id).await {
        Ok(_) => (StatusCode::OK, Json(ApiResponse::ok("用户已删除"))).into_response(),
        Err(e) => api_error(StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
    }
}

/// 获取所有设备（包含绑定用户信息）
pub async fn list_all_devices(
    State(state): State<Arc<AppState>>,
    _admin: AdminUser,
    Query(params): Query<PaginationParams>,
) -> impl IntoResponse {
    let repo = DeviceRepository::new(&state.db);

    match repo.find_all_with_username(params.offset(), params.limit()).await {
        Ok((devices, total)) => {
            // 使用实时 WebSocket 连接状态覆盖数据库中的状态
            let mut items: Vec<DeviceResponse> = Vec::with_capacity(devices.len());
            for device in devices {
                let mut device_resp: DeviceResponse = device.into();
                // 检查实际的 WebSocket 连接状态
                device_resp.is_online = state.is_device_online(&device_resp.device_id).await;
                items.push(device_resp);
            }
            let total_pages = ((total as f64) / (params.limit() as f64)).ceil() as u32;

            let response = PaginatedResponse {
                items,
                total,
                page: params.page.unwrap_or(1),
                limit: params.limit(),
                total_pages,
            };

            (StatusCode::OK, Json(ApiResponse::ok(response))).into_response()
        }
        Err(e) => api_error(StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
    }
}

/// 获取所有会话
pub async fn list_all_sessions(
    State(state): State<Arc<AppState>>,
    _admin: AdminUser,
    Query(params): Query<PaginationParams>,
) -> impl IntoResponse {
    let repo = SessionRepository::new(&state.db);

    match repo.find_all(params.offset(), params.limit()).await {
        Ok((sessions, total)) => {
            let items: Vec<SessionResponse> = sessions.into_iter().map(Into::into).collect();
            let total_pages = ((total as f64) / (params.limit() as f64)).ceil() as u32;

            let response = PaginatedResponse {
                items,
                total,
                page: params.page.unwrap_or(1),
                limit: params.limit(),
                total_pages,
            };

            (StatusCode::OK, Json(ApiResponse::ok(response))).into_response()
        }
        Err(e) => api_error(StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
    }
}

/// 获取统计信息
pub async fn get_stats(
    State(state): State<Arc<AppState>>,
    _admin: AdminUser,
) -> impl IntoResponse {
    let user_repo = UserRepository::new(&state.db);
    let device_repo = DeviceRepository::new(&state.db);
    let session_repo = SessionRepository::new(&state.db);

    let total_users = user_repo.find_all(0, 1).await.map(|(_, t)| t).unwrap_or(0);
    let (_, total_devices) = device_repo.find_all(0, 1).await.unwrap_or((vec![], 0));
    // 使用实时 WebSocket 连接数作为在线设备数
    let online_devices = state.count_online_devices().await as i64;
    let active_sessions = session_repo.count_active().await.unwrap_or(0);
    let (_, total_sessions) = session_repo.find_all(0, 1).await.unwrap_or((vec![], 0));

    let response = StatsResponse {
        total_users,
        total_devices,
        online_devices,
        active_sessions,
        total_sessions,
    };

    (StatusCode::OK, Json(ApiResponse::ok(response))).into_response()
}

/// 获取服务器配置
pub async fn get_server_config(
    State(state): State<Arc<AppState>>,
    _admin: AdminUser,
) -> impl IntoResponse {
    let config = &state.config;
    
    // 获取 TURN 服务器地址
    let turn_server = if config.enable_local_turn {
        let host = config.public_ip.as_deref().unwrap_or("localhost");
        Some(format!("turn:{}:{}", host, config.turn_port))
    } else {
        config.turn_server.clone()
    };
    
    let response = ServerConfigResponse {
        version: env!("CARGO_PKG_VERSION").to_string(),
        http_port: config.port,
        stun_port: config.stun_port,
        stun_enabled: config.enable_local_stun,
        stun_servers: config.stun_servers.clone(),
        turn_port: config.turn_port,
        turn_enabled: config.enable_local_turn,
        turn_server,
        turn_username: config.turn_username.clone(),
        turn_realm: config.turn_realm.clone(),
        jwt_expiry_hours: config.jwt_expiry / 3600,
        database_type: "SQLite".to_string(),
    };

    (StatusCode::OK, Json(ApiResponse::ok(response))).into_response()
}

/// 环境配置响应
#[derive(Debug, Serialize)]
pub struct EnvConfigResponse {
    pub content: String,
}

/// 环境配置请求
#[derive(Debug, serde::Deserialize)]
pub struct EnvConfigRequest {
    pub content: String,
}

/// 获取环境配置文件
pub async fn get_env_config(
    _admin: AdminUser,
) -> impl IntoResponse {
    let env_path = std::path::Path::new(".env");
    
    let content = if env_path.exists() {
        std::fs::read_to_string(env_path).unwrap_or_default()
    } else {
        // 返回默认配置模板
        generate_default_env_config()
    };
    
    let response = EnvConfigResponse { content };
    (StatusCode::OK, Json(ApiResponse::ok(response))).into_response()
}

/// 保存环境配置文件
pub async fn save_env_config(
    _admin: AdminUser,
    Json(req): Json<EnvConfigRequest>,
) -> impl IntoResponse {
    let env_path = std::path::Path::new(".env");
    
    match std::fs::write(env_path, &req.content) {
        Ok(_) => {
            tracing::info!("Environment config saved");
            (StatusCode::OK, Json(ApiResponse::ok("配置已保存"))).into_response()
        }
        Err(e) => {
            tracing::error!("Failed to save env config: {}", e);
            api_error(StatusCode::INTERNAL_SERVER_ERROR, format!("保存失败: {}", e))
        }
    }
}

/// Generate default environment config
fn generate_default_env_config() -> String {
    r#"# EasyRemote Server Configuration

# Server Settings
HOST=0.0.0.0
PORT=9099

# STUN Server Settings
ENABLE_LOCAL_STUN=true
STUN_PORT=3478

# TURN Server Settings
ENABLE_LOCAL_TURN=true
TURN_PORT=3479
TURN_USERNAME=easyremote
TURN_PASSWORD=easyremote123
TURN_REALM=easyremote

# Public IP (optional, for generating correct STUN/TURN URLs)
# PUBLIC_IP=your.public.ip

# Database Settings
DATABASE_URL=sqlite:easyremote.db?mode=rwc

# JWT Settings
# JWT_SECRET=your-secret-key-here
JWT_EXPIRY=86400

# Log Level
RUST_LOG=info,tower_http=debug
"#.to_string()
}
