use std::sync::Arc;

use axum::{
    extract::State,
    http::StatusCode,
    routing::{get, post},
    Json, Router,
};
use tokio::net::TcpListener;

use crate::handlers::RequestHandler;
use crate::protocol::JsonRpcRequest;
use crate::Result;

pub struct SseTransport {
    host: String,
    port: u16,
    request_handler: Arc<RequestHandler>,
}

impl SseTransport {
    pub fn new(host: String, port: u16, request_handler: Arc<RequestHandler>) -> Self {
        Self {
            host,
            port,
            request_handler,
        }
    }

    fn router(&self) -> Router {
        Router::new()
            .route("/health", get(health_handler))
            .route("/mcp", post(mcp_handler))
            .with_state(self.request_handler.clone())
    }

    pub async fn bind(&self) -> Result<()> {
        let addr_str = format!("{}:{}", self.host, self.port);
        let listener = TcpListener::bind(&addr_str).await?;

        tracing::info!("SSE transport listening on http://{}", addr_str);

        let router = self.router();
        axum::serve(listener, router).await?;

        Ok(())
    }
}

async fn health_handler() -> impl axum::response::IntoResponse {
    Json(serde_json::json!({
        "status": "healthy",
        "version": env!("CARGO_PKG_VERSION"),
    }))
}

async fn mcp_handler(
    State(handler): State<Arc<RequestHandler>>,
    Json(request): Json<JsonRpcRequest>,
) -> impl axum::response::IntoResponse {
    let response = handler.handle(&request).await;
    (StatusCode::OK, Json(response))
}
