use axum::{
    extract::{Path, State},
    http::StatusCode,
    response::Json,
};
use ontoref_derive::onto_api;
use provisioning_orchestrator::{
    rollback::{Checkpoint, RollbackResult, RollbackStatistics},
    SharedState,
};
use serde::Deserialize;
use tracing::{error, info, warn};

use super::ApiResponse;

#[derive(Deserialize)]
pub struct CreateCheckpointRequest {
    pub name: String,
    pub description: Option<String>,
}

#[derive(Deserialize)]
pub struct RollbackRequest {
    pub checkpoint_id: Option<String>,
    pub operation_ids: Option<Vec<String>>,
}

#[onto_api(
    method = "POST",
    path = "/rollback/checkpoints",
    description = "Create a rollback checkpoint",
    auth = "bearer",
    actors = "developer, agent",
    tags = "rollback",
    feature = ""
)]
pub async fn create_checkpoint(
    State(state): State<SharedState>,
    Json(request): Json<CreateCheckpointRequest>,
) -> Result<Json<ApiResponse<String>>, StatusCode> {
    match state
        .rollback_system
        .checkpoint_manager
        .create_checkpoint(request.name, request.description)
        .await
    {
        Ok(checkpoint_id) => {
            info!("Created checkpoint: {}", checkpoint_id);
            Ok(Json(ApiResponse::success(checkpoint_id)))
        }
        Err(e) => {
            error!("Failed to create checkpoint: {}", e);
            Err(StatusCode::INTERNAL_SERVER_ERROR)
        }
    }
}

#[onto_api(
    method = "GET",
    path = "/rollback/checkpoints",
    description = "List rollback checkpoints",
    auth = "bearer",
    actors = "developer, agent",
    tags = "rollback",
    feature = ""
)]
pub async fn list_checkpoints(
    State(state): State<SharedState>,
) -> Result<Json<ApiResponse<Vec<Checkpoint>>>, StatusCode> {
    let checkpoints = state
        .rollback_system
        .checkpoint_manager
        .list_checkpoints()
        .await;
    Ok(Json(ApiResponse::success(checkpoints)))
}

#[onto_api(
    method = "GET",
    path = "/rollback/checkpoints/{id}",
    description = "Get a specific checkpoint",
    auth = "bearer",
    actors = "developer, agent",
    tags = "rollback",
    feature = ""
)]
pub async fn get_checkpoint(
    State(state): State<SharedState>,
    Path(checkpoint_id): Path<String>,
) -> Result<Json<ApiResponse<Checkpoint>>, StatusCode> {
    match state
        .rollback_system
        .checkpoint_manager
        .get_checkpoint(&checkpoint_id)
        .await
    {
        Some(checkpoint) => Ok(Json(ApiResponse::success(checkpoint))),
        None => Err(StatusCode::NOT_FOUND),
    }
}

#[onto_api(
    method = "POST",
    path = "/rollback/execute",
    description = "Execute a rollback operation",
    auth = "admin",
    actors = "developer",
    tags = "rollback",
    feature = ""
)]
pub async fn execute_rollback(
    State(state): State<SharedState>,
    Json(request): Json<RollbackRequest>,
) -> Result<Json<ApiResponse<RollbackResult>>, StatusCode> {
    let result = if let Some(checkpoint_id) = request.checkpoint_id {
        // Rollback to specific checkpoint
        match state
            .rollback_system
            .rollback_executor
            .rollback_to_checkpoint(&checkpoint_id)
            .await
        {
            Ok(result) => result,
            Err(e) => {
                error!(
                    "Failed to execute rollback to checkpoint {}: {}",
                    checkpoint_id, e
                );
                return Err(StatusCode::INTERNAL_SERVER_ERROR);
            }
        }
    } else if let Some(operation_ids) = request.operation_ids {
        // Partial rollback of specific operations
        match state
            .rollback_system
            .rollback_executor
            .rollback_operations(operation_ids)
            .await
        {
            Ok(result) => result,
            Err(e) => {
                error!("Failed to execute partial rollback: {}", e);
                return Err(StatusCode::INTERNAL_SERVER_ERROR);
            }
        }
    } else {
        return Err(StatusCode::BAD_REQUEST);
    };

    if result.success {
        info!(
            "Rollback executed successfully: {} operations",
            result.operations_executed
        );
    } else {
        warn!(
            "Rollback completed with errors: {}/{} operations failed",
            result.operations_failed,
            result.operations_executed + result.operations_failed
        );
    }

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

#[onto_api(
    method = "GET",
    path = "/rollback/statistics",
    description = "Get rollback statistics",
    auth = "bearer",
    actors = "developer, agent",
    tags = "rollback",
    feature = ""
)]
pub async fn get_rollback_statistics(
    State(state): State<SharedState>,
) -> Result<Json<ApiResponse<RollbackStatistics>>, StatusCode> {
    let stats = state.rollback_system.get_statistics().await;
    Ok(Json(ApiResponse::success(stats)))
}

#[onto_api(
    method = "POST",
    path = "/rollback/restore/{id}",
    description = "Restore state from checkpoint",
    auth = "admin",
    actors = "developer",
    tags = "rollback",
    feature = ""
)]
pub async fn restore_from_checkpoint(
    State(state): State<SharedState>,
    Path(checkpoint_id): Path<String>,
) -> Result<Json<ApiResponse<String>>, StatusCode> {
    match state
        .rollback_system
        .state_restorer
        .restore_from_checkpoint(&checkpoint_id)
        .await
    {
        Ok(_) => {
            info!(
                "Successfully restored state from checkpoint: {}",
                checkpoint_id
            );
            Ok(Json(ApiResponse::success(format!(
                "State restored from checkpoint {}",
                checkpoint_id
            ))))
        }
        Err(e) => {
            error!("Failed to restore from checkpoint {}: {}", checkpoint_id, e);
            Err(StatusCode::INTERNAL_SERVER_ERROR)
        }
    }
}
