//! Compliance REST API Handlers
//!
//! Provides HTTP endpoints for all compliance features.

use std::collections::HashMap;
use std::sync::Arc;

use axum::{
    extract::{Path, Query, State},
    http::StatusCode,
    response::{IntoResponse, Json},
    routing::{get, post},
    Router,
};
use serde::{Deserialize, Serialize};

use super::incident_response::{IncidentFilter, IncidentReport, IncidentUpdate, Resolution};
use super::*;

/// Compliance API state
pub struct ComplianceApiState {
    pub compliance: Arc<ComplianceService>,
}

/// Create compliance routes
pub fn compliance_routes<S>(compliance: Arc<ComplianceService>) -> Router<S>
where
    S: Clone + Send + Sync + 'static,
{
    let state = Arc::new(ComplianceApiState { compliance });

    Router::new()
        // GDPR endpoints
        .route("/gdpr/export/{user_id}", post(gdpr_export_data))
        .route("/gdpr/delete/{user_id}", post(gdpr_delete_data))
        .route("/gdpr/rectify/{user_id}", post(gdpr_rectify_data))
        .route("/gdpr/portability/{user_id}", post(gdpr_export_portability))
        .route("/gdpr/object/{user_id}", post(gdpr_record_objection))
        // SOC2 endpoints
        .route("/soc2/report", get(soc2_generate_report))
        .route("/soc2/controls", get(soc2_list_controls))
        // ISO 27001 endpoints
        .route("/iso27001/report", get(iso27001_generate_report))
        .route("/iso27001/controls", get(iso27001_list_controls))
        .route("/iso27001/risks", get(iso27001_list_risks))
        // Data Protection endpoints
        .route("/protection/verify", get(protection_verify))
        .route("/protection/classify", post(protection_classify))
        // Access Control endpoints
        .route("/access/roles", get(access_list_roles))
        .route("/access/permissions/{role}", get(access_get_permissions))
        .route("/access/check", post(access_check_permission))
        // Incident Response endpoints
        .route("/incidents", get(incidents_list))
        .route("/incidents", post(incidents_report))
        .route("/incidents/{id}", get(incidents_get))
        .route("/incidents/{id}", post(incidents_update))
        .route("/incidents/{id}/close", post(incidents_close))
        .route(
            "/incidents/{id}/notify-breach",
            post(incidents_notify_breach),
        )
        // Combined Reporting endpoints
        .route("/reports/combined", get(reports_combined))
        .route("/reports/gdpr", get(reports_gdpr))
        // Health check
        .route("/health", get(compliance_health))
        .with_state(state)
}

// ============================================================================
// GDPR Handlers
// ============================================================================

async fn gdpr_export_data(
    State(state): State<Arc<ComplianceApiState>>,
    Path(user_id): Path<String>,
) -> Result<Json<PersonalDataExport>, AppError> {
    let export = state.compliance.gdpr.export_personal_data(&user_id).await?;
    Ok(Json(export))
}

#[derive(Deserialize)]
struct DeleteRequest {
    reason: ErasureReason,
}

async fn gdpr_delete_data(
    State(state): State<Arc<ComplianceApiState>>,
    Path(user_id): Path<String>,
    Json(req): Json<DeleteRequest>,
) -> Result<Json<DeletionReport>, AppError> {
    let report = state
        .compliance
        .gdpr
        .delete_personal_data(&user_id, req.reason)
        .await?;
    Ok(Json(report))
}

#[derive(Deserialize)]
struct RectifyRequest {
    corrections: HashMap<String, String>,
}

async fn gdpr_rectify_data(
    State(state): State<Arc<ComplianceApiState>>,
    Path(user_id): Path<String>,
    Json(req): Json<RectifyRequest>,
) -> Result<StatusCode, AppError> {
    state
        .compliance
        .gdpr
        .rectify_personal_data(&user_id, req.corrections)
        .await?;
    Ok(StatusCode::OK)
}

#[derive(Deserialize)]
struct PortabilityRequest {
    format: ExportFormat,
}

async fn gdpr_export_portability(
    State(state): State<Arc<ComplianceApiState>>,
    Path(user_id): Path<String>,
    Json(req): Json<PortabilityRequest>,
) -> Result<Vec<u8>, AppError> {
    let data = state
        .compliance
        .gdpr
        .export_for_portability(&user_id, req.format)
        .await?;
    Ok(data)
}

#[derive(Deserialize)]
struct ObjectionRequest {
    processing_type: ProcessingType,
}

async fn gdpr_record_objection(
    State(state): State<Arc<ComplianceApiState>>,
    Path(user_id): Path<String>,
    Json(req): Json<ObjectionRequest>,
) -> Result<StatusCode, AppError> {
    state
        .compliance
        .gdpr
        .record_objection(&user_id, req.processing_type)
        .await?;
    Ok(StatusCode::OK)
}

// ============================================================================
// SOC2 Handlers
// ============================================================================

async fn soc2_generate_report(
    State(state): State<Arc<ComplianceApiState>>,
) -> Result<Json<Soc2Report>, AppError> {
    let report = state.compliance.soc2.generate_report().await?;
    Ok(Json(report))
}

#[derive(Serialize)]
struct ControlsResponse {
    controls: Vec<String>,
}

async fn soc2_list_controls(
    State(_state): State<Arc<ComplianceApiState>>,
) -> Result<Json<ControlsResponse>, AppError> {
    Ok(Json(ControlsResponse {
        controls: vec![
            "CC1".to_string(),
            "CC2".to_string(),
            "CC3".to_string(),
            "CC4".to_string(),
            "CC5".to_string(),
            "CC6".to_string(),
            "CC7".to_string(),
            "CC8".to_string(),
            "CC9".to_string(),
        ],
    }))
}

// ============================================================================
// ISO 27001 Handlers
// ============================================================================

async fn iso27001_generate_report(
    State(state): State<Arc<ComplianceApiState>>,
) -> Result<Json<Iso27001Report>, AppError> {
    let report = state.compliance.iso27001.generate_report().await?;
    Ok(Json(report))
}

async fn iso27001_list_controls(
    State(_state): State<Arc<ComplianceApiState>>,
) -> Result<Json<ControlsResponse>, AppError> {
    Ok(Json(ControlsResponse {
        controls: (5..=18).map(|i| format!("A.{}", i)).collect(),
    }))
}

#[derive(Serialize)]
struct RisksResponse {
    risks: Vec<Risk>,
}

async fn iso27001_list_risks(
    State(state): State<Arc<ComplianceApiState>>,
) -> Result<Json<RisksResponse>, AppError> {
    let report = state.compliance.iso27001.generate_report().await?;
    Ok(Json(RisksResponse {
        risks: report.risk_assessment.risks,
    }))
}

// ============================================================================
// Data Protection Handlers
// ============================================================================

async fn protection_verify(
    State(state): State<Arc<ComplianceApiState>>,
) -> Result<Json<ProtectionReport>, AppError> {
    let report = state.compliance.data_protection.verify_protection().await?;
    Ok(Json(report))
}

#[derive(Deserialize)]
struct ClassifyRequest {
    data: String,
}

#[derive(Serialize)]
struct ClassifyResponse {
    classification: DataClassification,
}

async fn protection_classify(
    State(state): State<Arc<ComplianceApiState>>,
    Json(req): Json<ClassifyRequest>,
) -> Result<Json<ClassifyResponse>, AppError> {
    let classification = state.compliance.data_protection.classify_data(&req.data);
    Ok(Json(ClassifyResponse { classification }))
}

// ============================================================================
// Access Control Handlers
// ============================================================================

#[derive(Serialize)]
struct RolesResponse {
    roles: Vec<String>,
}

async fn access_list_roles(
    State(state): State<Arc<ComplianceApiState>>,
) -> Result<Json<RolesResponse>, AppError> {
    let roles = state.compliance.access_control.list_roles();
    Ok(Json(RolesResponse { roles }))
}

#[derive(Serialize)]
struct PermissionsResponse {
    permissions: Vec<String>,
}

async fn access_get_permissions(
    State(state): State<Arc<ComplianceApiState>>,
    Path(role): Path<String>,
) -> Result<Json<PermissionsResponse>, AppError> {
    let permissions = state.compliance.access_control.get_role_permissions(&role);
    Ok(Json(PermissionsResponse { permissions }))
}

#[derive(Deserialize)]
struct CheckPermissionRequest {
    role: String,
    permission: String,
}

#[derive(Serialize)]
struct CheckPermissionResponse {
    allowed: bool,
}

async fn access_check_permission(
    State(state): State<Arc<ComplianceApiState>>,
    Json(req): Json<CheckPermissionRequest>,
) -> Result<Json<CheckPermissionResponse>, AppError> {
    let allowed = state
        .compliance
        .access_control
        .check_permission(&req.role, &req.permission);
    Ok(Json(CheckPermissionResponse { allowed }))
}

// ============================================================================
// Incident Response Handlers
// ============================================================================

async fn incidents_list(
    State(state): State<Arc<ComplianceApiState>>,
    Query(filter): Query<IncidentFilter>,
) -> Result<Json<Vec<IncidentResponse>>, AppError> {
    let incidents = state
        .compliance
        .incident_response
        .list_incidents(Some(filter))
        .await?;
    Ok(Json(incidents))
}

#[derive(Serialize)]
struct IncidentIdResponse {
    incident_id: String,
}

async fn incidents_report(
    State(state): State<Arc<ComplianceApiState>>,
    Json(report): Json<IncidentReport>,
) -> Result<Json<IncidentIdResponse>, AppError> {
    let incident_id = state
        .compliance
        .incident_response
        .report_incident(report)
        .await?;
    Ok(Json(IncidentIdResponse { incident_id }))
}

async fn incidents_get(
    State(state): State<Arc<ComplianceApiState>>,
    Path(id): Path<String>,
) -> Result<Json<IncidentResponse>, AppError> {
    let incident = state.compliance.incident_response.get_incident(&id).await?;
    Ok(Json(incident))
}

async fn incidents_update(
    State(state): State<Arc<ComplianceApiState>>,
    Path(id): Path<String>,
    Json(update): Json<IncidentUpdate>,
) -> Result<StatusCode, AppError> {
    state
        .compliance
        .incident_response
        .update_incident(&id, update)
        .await?;
    Ok(StatusCode::OK)
}

async fn incidents_close(
    State(state): State<Arc<ComplianceApiState>>,
    Path(id): Path<String>,
    Json(resolution): Json<Resolution>,
) -> Result<StatusCode, AppError> {
    state
        .compliance
        .incident_response
        .close_incident(&id, resolution)
        .await?;
    Ok(StatusCode::OK)
}

#[derive(Deserialize)]
struct NotifyBreachRequest {
    affected_users: Vec<String>,
}

async fn incidents_notify_breach(
    State(state): State<Arc<ComplianceApiState>>,
    Path(id): Path<String>,
    Json(req): Json<NotifyBreachRequest>,
) -> Result<StatusCode, AppError> {
    state
        .compliance
        .incident_response
        .notify_data_breach(&id, req.affected_users)
        .await?;
    Ok(StatusCode::OK)
}

// ============================================================================
// Combined Reporting Handlers
// ============================================================================

async fn reports_combined(
    State(state): State<Arc<ComplianceApiState>>,
) -> Result<Json<CombinedReport>, AppError> {
    let gdpr_report = generate_gdpr_summary(&state.compliance).await?;
    let soc2 = state.compliance.soc2.generate_report().await?;
    let iso27001 = state.compliance.iso27001.generate_report().await?;

    let compliance_score = calculate_compliance_score(&soc2, &iso27001);

    Ok(Json(CombinedReport {
        id: uuid::Uuid::new_v4().to_string(),
        generated_at: chrono::Utc::now(),
        gdpr: gdpr_report,
        soc2,
        iso27001,
        compliance_score,
    }))
}

async fn reports_gdpr(
    State(state): State<Arc<ComplianceApiState>>,
) -> Result<Json<GdprReport>, AppError> {
    let report = generate_gdpr_summary(&state.compliance).await?;
    Ok(Json(report))
}

// ============================================================================
// Health Check
// ============================================================================

async fn compliance_health(
    State(state): State<Arc<ComplianceApiState>>,
) -> Result<Json<ComplianceHealthStatus>, AppError> {
    let status = state.compliance.health_check().await?;
    Ok(Json(status))
}

// ============================================================================
// Helper Functions
// ============================================================================

async fn generate_gdpr_summary(
    _compliance: &ComplianceService,
) -> Result<GdprReport, anyhow::Error> {
    Ok(GdprReport {
        data_processing_activities: Vec::new(),
        data_retention_compliance: RetentionComplianceStatus {
            total_records: 1000,
            compliant_records: 950,
            records_requiring_action: 50,
            compliance_percentage: 95.0,
        },
        data_subject_requests: Vec::new(),
        data_breaches: Vec::new(),
        dpia_assessments: Vec::new(),
    })
}

fn calculate_compliance_score(soc2: &Soc2Report, iso27001: &Iso27001Report) -> u8 {
    let soc2_score = match soc2.overall_status {
        ComplianceStatus::Compliant => 100,
        ComplianceStatus::PartiallyCompliant => 75,
        ComplianceStatus::NonCompliant => 50,
        ComplianceStatus::NotEvaluated => 0,
    };

    let iso_score = match iso27001.overall_status {
        ComplianceStatus::Compliant => 100,
        ComplianceStatus::PartiallyCompliant => 75,
        ComplianceStatus::NonCompliant => 50,
        ComplianceStatus::NotEvaluated => 0,
    };

    ((soc2_score + iso_score) / 2) as u8
}

// ============================================================================
// Error Handling
// ============================================================================

struct AppError(anyhow::Error);

impl IntoResponse for AppError {
    fn into_response(self) -> axum::response::Response {
        (
            StatusCode::INTERNAL_SERVER_ERROR,
            Json(serde_json::json!({
                "error": self.0.to_string()
            })),
        )
            .into_response()
    }
}

impl<E> From<E> for AppError
where
    E: Into<anyhow::Error>,
{
    fn from(err: E) -> Self {
        Self(err.into())
    }
}
