use std::collections::HashMap;
use axum::{routing::{get, post}, Router, extract::State, response::{Json, IntoResponse}, http::StatusCode};
use serde::Deserialize;
use crate::ts_client::TushareClient;
use crate::state::{AppState, ServiceOperationalStatus};
use common_contracts::observability::{HealthStatus, ServiceStatus};

pub fn create_router(app_state: AppState) -> Router {
    Router::new()
        .route("/health", get(health_check))
        .route("/tasks", get(get_tasks))
        .route("/test", post(test_connection))
        .with_state(app_state)
}

#[derive(Deserialize)]
struct TestRequest {
    api_key: Option<String>,
    api_url: Option<String>,
}

async fn test_connection(
    State(state): State<AppState>,
    Json(payload): Json<TestRequest>,
) -> impl IntoResponse {
    let api_url = payload.api_url
        .filter(|s| !s.is_empty())
        .unwrap_or_else(|| state.config.tushare_api_url.clone());

    let api_key = if let Some(k) = payload.api_key.filter(|s| !s.is_empty()) {
        k
    } else if let Some(k) = &state.config.tushare_api_token {
        k.clone()
    } else {
        return (
            StatusCode::BAD_REQUEST,
            Json(serde_json::json!({
                "success": false,
                "message": "No API Key provided or configured"
            }))
        ).into_response();
    };

    let client = TushareClient::new(api_url, api_key);

    // Try to fetch a small amount of data to verify the token
    match client.send_request::<serde_json::Value>(
        "stock_basic", 
        serde_json::json!({"limit": 1}), 
        ""
    ).await {
        Ok(_) => (
            StatusCode::OK,
            Json(serde_json::json!({
                "success": true,
                "message": "Connection successful"
            }))
        ).into_response(),
        Err(e) => (
            StatusCode::BAD_REQUEST,
            Json(serde_json::json!({
                "success": false,
                "message": format!("Connection failed: {}", e)
            }))
        ).into_response(),
    }
}

async fn health_check(State(state): State<AppState>) -> Json<HealthStatus> {
    let mut details = HashMap::new();
    let operational_status = state.status.read().await;

    let (service_status, reason) = match &*operational_status {
        ServiceOperationalStatus::Active => (ServiceStatus::Ok, "ok".to_string()),
        ServiceOperationalStatus::Degraded { reason } => {
            (ServiceStatus::Degraded, reason.clone())
        }
    };
    
    details.insert("operational_status".to_string(), reason);

    let status = HealthStatus {
        module_id: "tushare-provider-service".to_string(),
        status: service_status,
        version: env!("CARGO_PKG_VERSION").to_string(),
        details,
    };
    Json(status)
}

async fn get_tasks(State(state): State<AppState>) -> axum::Json<Vec<common_contracts::observability::TaskProgress>> {
    let tasks = state
        .tasks
        .iter()
        .map(|kv| kv.value().clone())
        .collect::<Vec<_>>();
    axum::Json(tasks)
}
