use axum::{
    extract::State,
    http::StatusCode,
    response::Json,
};
use ontoref_derive::onto_api;
use provisioning_orchestrator::SharedState;
use serde::{Deserialize, Serialize};
use tracing::error;

use super::ApiResponse;

// DNS Management Routes

#[onto_api(
    method = "GET",
    path = "/api/v1/dns/records",
    description = "List DNS records",
    auth = "bearer",
    actors = "developer, agent",
    tags = "dns",
    feature = ""
)]
pub async fn list_dns_records(
    State(state): State<SharedState>,
) -> Result<Json<ApiResponse<Vec<provisioning_orchestrator::dns::DnsRecord>>>, StatusCode> {
    match state.dns_manager.list_records().await {
        Ok(records) => Ok(Json(ApiResponse::success(records))),
        Err(e) => {
            error!("Failed to list DNS records: {}", e);
            Err(StatusCode::INTERNAL_SERVER_ERROR)
        }
    }
}

// Extension Management Routes

#[onto_api(
    method = "GET",
    path = "/api/v1/extensions/loaded",
    description = "List loaded extensions",
    auth = "bearer",
    actors = "developer, agent",
    tags = "extensions",
    feature = ""
)]
pub async fn list_loaded_extensions(
    State(state): State<SharedState>,
) -> Result<Json<ApiResponse<Vec<provisioning_orchestrator::extensions::Extension>>>, StatusCode> {
    let extensions = state.extension_manager.list_loaded_extensions().await;
    Ok(Json(ApiResponse::success(extensions)))
}

#[derive(Deserialize)]
pub struct ReloadExtensionRequest {
    pub extension_type: String,
    pub name: String,
}

#[onto_api(
    method = "POST",
    path = "/api/v1/extensions/reload",
    description = "Reload an extension",
    auth = "bearer",
    actors = "developer, agent",
    tags = "extensions",
    feature = ""
)]
pub async fn reload_extension(
    State(state): State<SharedState>,
    Json(request): Json<ReloadExtensionRequest>,
) -> Result<Json<ApiResponse<String>>, StatusCode> {
    use provisioning_orchestrator::extensions::ExtensionType;

    let ext_type = match request.extension_type.as_str() {
        "provider" => ExtensionType::Provider,
        "taskserv" => ExtensionType::Taskserv,
        "cluster" => ExtensionType::Cluster,
        _ => return Err(StatusCode::BAD_REQUEST),
    };

    match state
        .extension_manager
        .reload_extension(ext_type, request.name.clone())
        .await
    {
        Ok(_) => Ok(Json(ApiResponse::success(format!(
            "Extension {} reloaded",
            request.name
        )))),
        Err(e) => {
            error!("Failed to reload extension: {}", e);
            Err(StatusCode::INTERNAL_SERVER_ERROR)
        }
    }
}

// OCI Registry Routes

#[derive(Deserialize)]
pub struct ListOciArtifactsRequest {
    pub namespace: String,
}

#[onto_api(
    method = "POST",
    path = "/api/v1/oci/artifacts",
    description = "List OCI artifacts in a namespace",
    auth = "bearer",
    actors = "developer, agent",
    tags = "oci",
    feature = ""
)]
pub async fn list_oci_artifacts(
    State(state): State<SharedState>,
    Json(request): Json<ListOciArtifactsRequest>,
) -> Result<Json<ApiResponse<Vec<provisioning_orchestrator::oci::OciArtifact>>>, StatusCode> {
    match state
        .oci_manager
        .list_oci_artifacts(&request.namespace)
        .await
    {
        Ok(artifacts) => Ok(Json(ApiResponse::success(artifacts))),
        Err(e) => {
            error!("Failed to list OCI artifacts: {}", e);
            Err(StatusCode::INTERNAL_SERVER_ERROR)
        }
    }
}

// Service Orchestration Routes

#[onto_api(
    method = "GET",
    path = "/api/v1/services/list",
    description = "List all orchestrated services",
    auth = "bearer",
    actors = "developer, agent",
    tags = "services",
    feature = ""
)]
pub async fn list_services(
    State(state): State<SharedState>,
) -> Result<Json<ApiResponse<Vec<provisioning_orchestrator::services::Service>>>, StatusCode> {
    let services = state.service_orchestrator.list_services().await;
    Ok(Json(ApiResponse::success(services)))
}

#[derive(Serialize)]
pub struct ServiceStatusResponse {
    pub name: String,
    pub status: provisioning_orchestrator::services::ServiceStatus,
}

#[onto_api(
    method = "GET",
    path = "/api/v1/services/status",
    description = "Get status of all orchestrated services",
    auth = "bearer",
    actors = "developer, agent",
    tags = "services",
    feature = ""
)]
pub async fn get_services_status(
    State(state): State<SharedState>,
) -> Result<Json<ApiResponse<Vec<ServiceStatusResponse>>>, StatusCode> {
    let services = state.service_orchestrator.list_services().await;
    let mut statuses = Vec::new();

    for service in services {
        if let Ok(status) = state
            .service_orchestrator
            .get_service_status(&service.name)
            .await
        {
            statuses.push(ServiceStatusResponse {
                name: service.name,
                status,
            });
        }
    }

    Ok(Json(ApiResponse::success(statuses)))
}
