//! 会话处理器

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

use crate::models::{ApiResponse, HistoryResponse, PaginatedResponse, PaginationParams, SessionResponse};
use crate::services::{
    device::DeviceRepository,
    session::{HistoryRepository, SessionRepository},
    AppState,
};
use super::{api_error, AuthUser};

/// 获取活跃会话列表
pub async fn list_sessions(
    State(state): State<Arc<AppState>>,
    user: AuthUser,
) -> impl IntoResponse {
    let session_repo = SessionRepository::new(&state.db);
    let device_repo = DeviceRepository::new(&state.db);

    // 获取用户的设备
    let devices = match device_repo.find_by_user(&user.user_id).await {
        Ok(devices) => devices,
        Err(e) => return api_error(StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
    };

    let device_ids: Vec<&str> = devices.iter().map(|d| d.device_id.as_str()).collect();

    // 获取活跃会话
    match session_repo.find_active().await {
        Ok(sessions) => {
            // 过滤出与用户设备相关的会话
            let filtered: Vec<SessionResponse> = sessions
                .into_iter()
                .filter(|s| {
                    device_ids.contains(&s.controller_device_id.as_str())
                        || device_ids.contains(&s.controlled_device_id.as_str())
                })
                .map(Into::into)
                .collect();

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

/// 获取控制历史记录
pub async fn get_history(
    State(state): State<Arc<AppState>>,
    user: AuthUser,
    Query(params): Query<PaginationParams>,
) -> impl IntoResponse {
    let repo = HistoryRepository::new(&state.db);

    match repo.find_by_user(&user.user_id, params.offset(), params.limit()).await {
        Ok((history, total)) => {
            let items: Vec<HistoryResponse> = history.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_session(
    State(state): State<Arc<AppState>>,
    Path(session_id): Path<String>,
    _user: AuthUser,
) -> impl IntoResponse {
    let repo = SessionRepository::new(&state.db);

    match repo.find_by_id(&session_id).await {
        Ok(session) => {
            let response: SessionResponse = session.into();
            (StatusCode::OK, Json(ApiResponse::ok(response))).into_response()
        }
        Err(_) => api_error(StatusCode::NOT_FOUND, "会话不存在"),
    }
}

/// 结束会话
pub async fn end_session(
    State(state): State<Arc<AppState>>,
    Path(session_id): Path<String>,
    user: AuthUser,
) -> impl IntoResponse {
    let session_repo = SessionRepository::new(&state.db);
    let device_repo = DeviceRepository::new(&state.db);

    // 获取会话
    let session = match session_repo.find_by_id(&session_id).await {
        Ok(session) => session,
        Err(_) => return api_error(StatusCode::NOT_FOUND, "会话不存在"),
    };

    // 验证用户有权结束会话
    let user_devices = match device_repo.find_by_user(&user.user_id).await {
        Ok(devices) => devices,
        Err(e) => return api_error(StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
    };

    let device_ids: Vec<&str> = user_devices.iter().map(|d| d.device_id.as_str()).collect();
    let is_owner = device_ids.contains(&session.controller_device_id.as_str())
        || device_ids.contains(&session.controlled_device_id.as_str());

    if !is_owner && user.role != "admin" {
        return api_error(StatusCode::FORBIDDEN, "无权结束此会话");
    }

    // 发送断开连接消息
    let message = serde_json::json!({
        "type": "session_end",
        "session_id": session_id,
    });

    state.send_to_device(&session.controller_device_id, &message.to_string()).await;
    state.send_to_device(&session.controlled_device_id, &message.to_string()).await;

    // 更新会话状态
    match session_repo.end_session(&session_id).await {
        Ok(_) => (StatusCode::OK, Json(ApiResponse::ok("会话已结束"))).into_response(),
        Err(e) => api_error(StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
    }
}
