use axum::{
    extract::{Path, State},
    http::StatusCode,
    response::Json,
};
use ontoref_derive::onto_api;
use provisioning_orchestrator::{
    test_environment::{
        CreateTestEnvironmentRequest, RunTestRequest, TestEnvironment, TestEnvironmentResponse,
        TestResult,
    },
    SharedState,
};
use tracing::error;

use super::ApiResponse;

#[onto_api(
    method = "POST",
    path = "/test/environments/create",
    description = "Create a test environment",
    auth = "bearer",
    actors = "developer, ci",
    tags = "test-env",
    feature = ""
)]
pub async fn create_test_environment(
    State(state): State<SharedState>,
    Json(request): Json<CreateTestEnvironmentRequest>,
) -> Result<Json<ApiResponse<TestEnvironmentResponse>>, StatusCode> {
    match state.test_orchestrator.create_environment(request).await {
        Ok(response) => Ok(Json(ApiResponse::success(response))),
        Err(e) => {
            error!("Failed to create test environment: {}", e);
            Err(StatusCode::INTERNAL_SERVER_ERROR)
        }
    }
}

#[onto_api(
    method = "GET",
    path = "/test/environments/{id}",
    description = "Get a test environment by ID",
    auth = "bearer",
    actors = "developer, ci",
    tags = "test-env",
    feature = ""
)]
pub async fn get_test_environment(
    State(state): State<SharedState>,
    Path(env_id): Path<String>,
) -> Result<Json<ApiResponse<TestEnvironment>>, StatusCode> {
    match state.test_orchestrator.get_environment(&env_id).await {
        Some(env) => Ok(Json(ApiResponse::success(env))),
        None => Err(StatusCode::NOT_FOUND),
    }
}

#[onto_api(
    method = "GET",
    path = "/test/environments",
    description = "List all test environments",
    auth = "bearer",
    actors = "developer, ci",
    tags = "test-env",
    feature = ""
)]
pub async fn list_test_environments(
    State(state): State<SharedState>,
) -> Result<Json<ApiResponse<Vec<TestEnvironment>>>, StatusCode> {
    let environments = state.test_orchestrator.list_environments().await;
    Ok(Json(ApiResponse::success(environments)))
}

#[onto_api(
    method = "POST",
    path = "/test/environments/{id}/run",
    description = "Run tests in a test environment",
    auth = "bearer",
    actors = "developer, ci",
    tags = "test-env",
    feature = ""
)]
pub async fn run_environment_tests(
    State(state): State<SharedState>,
    Path(env_id): Path<String>,
    Json(request): Json<RunTestRequest>,
) -> Result<Json<ApiResponse<Vec<TestResult>>>, StatusCode> {
    match state.test_orchestrator.run_tests(&env_id, request).await {
        Ok(results) => Ok(Json(ApiResponse::success(results))),
        Err(e) => {
            error!("Failed to run tests: {}", e);
            Err(StatusCode::INTERNAL_SERVER_ERROR)
        }
    }
}

#[onto_api(
    method = "DELETE",
    path = "/test/environments/{id}",
    description = "Cleanup a test environment",
    auth = "bearer",
    actors = "developer, ci",
    tags = "test-env",
    feature = ""
)]
pub async fn cleanup_test_environment(
    State(state): State<SharedState>,
    Path(env_id): Path<String>,
) -> Result<Json<ApiResponse<String>>, StatusCode> {
    match state
        .test_orchestrator
        .cleanup_environment(&env_id, false)
        .await
    {
        Ok(_) => Ok(Json(ApiResponse::success(format!(
            "Environment {} cleaned up",
            env_id
        )))),
        Err(e) => {
            error!("Failed to cleanup environment: {}", e);
            Err(StatusCode::INTERNAL_SERVER_ERROR)
        }
    }
}

#[onto_api(
    method = "GET",
    path = "/test/environments/{id}/logs",
    description = "Get logs for a test environment",
    auth = "bearer",
    actors = "developer, ci",
    tags = "test-env",
    feature = ""
)]
pub async fn get_environment_logs(
    State(state): State<SharedState>,
    Path(env_id): Path<String>,
) -> Result<Json<ApiResponse<Vec<String>>>, StatusCode> {
    match state.test_orchestrator.get_environment_logs(&env_id).await {
        Ok(logs) => Ok(Json(ApiResponse::success(logs))),
        Err(e) => {
            error!("Failed to get environment logs: {}", e);
            Err(StatusCode::INTERNAL_SERVER_ERROR)
        }
    }
}
