#![allow(
    dead_code,
    unused_imports,
    unused_variables,
    unused_assignments,
    unused,
    clippy::excessive_nesting,
    clippy::vec_init_then_push,
    clippy::ptr_arg,
    clippy::result_large_err
)]

// Provisioning Orchestrator Library
// Exports all modules for use in tests and as a library

use serde::{Deserialize, Serialize};

// Core types that are used throughout the library
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkflowTask {
    pub id: String,
    pub name: String,
    pub command: String,
    pub args: Vec<String>,
    pub dependencies: Vec<String>,
    pub status: TaskStatus,
    pub created_at: chrono::DateTime<chrono::Utc>,
    pub started_at: Option<chrono::DateTime<chrono::Utc>>,
    pub completed_at: Option<chrono::DateTime<chrono::Utc>>,
    pub output: Option<String>,
    pub error: Option<String>,
    /// Arbitrary key-value context carried with the task.
    /// Component tasks set: type=component, component, server, workspace, operation.
    #[serde(default)]
    pub tags: std::collections::HashMap<String, String>,
}

/// NATS payload for `provisioning.component.lifecycle`.
/// Published by the orchestrator executor; consumed by the nu_daemon subscriber.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ComponentLifecycleEvent {
    pub task_id: String,
    pub component: String,
    pub server: String,
    pub workspace: String,
    pub operation: String,
    /// "completed" | "failed"
    pub status: String,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum TaskStatus {
    Pending,
    Running,
    Completed,
    Failed,
    Cancelled,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateServerWorkflow {
    pub infra: String,
    pub settings: String,
    pub servers: Vec<String>,
    pub check_mode: bool,
    pub wait: bool,
    // Rendered and compressed script prepared by CLI
    // If present, orchestrator executes this script directly without constructing commands
    #[serde(default)]
    pub script_compressed: Option<String>,
    #[serde(default)]
    pub script_encoding: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaskservWorkflow {
    pub infra: String,
    pub settings: String,
    pub taskserv: String,
    pub operation: String, // create, delete, generate, check-updates
    pub check_mode: bool,
    pub wait: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClusterWorkflow {
    pub infra: String,
    pub settings: String,
    pub cluster_type: String,
    pub operation: String, // create, delete
    pub check_mode: bool,
    pub wait: bool,
}

/// Unified component lifecycle request body for `/api/v1/workflows/component/{op}`.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ComponentWorkflow {
    /// Workspace root path (absolute).
    pub workspace: String,
    /// Infra subdirectory name under `infra/`.
    pub infra: String,
    /// Component name (must exist in workspace components dir).
    pub component: String,
    /// Target server hostname or cluster controller.
    pub server: String,
    /// Kubernetes namespace (cluster-mode only).
    #[serde(default)]
    pub namespace: Option<String>,
    /// SSH user for remote execution.
    #[serde(default = "default_ssh_user")]
    pub ssh_user: String,
    /// Path to SSH identity file.
    #[serde(default)]
    pub ssh_key_path: Option<String>,
    /// Serialised settings payload forwarded to the component script.
    pub settings: String,
    /// Dry-run flag — passed as `CHECK_MODE=1` to the component script.
    #[serde(default)]
    pub check_mode: bool,
    /// Debug flag — uses `bash -x` on the remote script and leaves /tmp/{name} intact for inspection.
    #[serde(default)]
    pub debug: bool,
    /// Absolute path to the provisioning repo root (`$PROVISIONING`).
    pub provisioning: String,
    /// Base64-encoded tar.gz bundle built by the CLI (copy + Tera render).
    /// When present the orchestrator skips Nu entirely: decode → SCP → SSH execute.
    #[serde(default)]
    pub script_compressed: Option<String>,
    /// Deploy mode declared in settings.ncl: "taskserv" | "cluster" | "container".
    /// Used by the precondition gate to skip live-probe checks for taskserv components.
    #[serde(default)]
    pub mode: Option<String>,
}

fn default_ssh_user() -> String {
    "root".to_string()
}

/// Validate storage type argument
pub fn validate_storage_type(s: &str) -> Result<String, String> {
    let available_types = storage::available_storage_types();
    if available_types.contains(&s.to_string()) {
        Ok(s.to_string())
    } else {
        Err(format!(
            "Invalid storage type '{}'. Available types: {}",
            s,
            available_types.join(", ")
        ))
    }
}

// CLI arguments structure
#[derive(clap::Parser, Clone)]
#[command(
    author,
    version,
    about = "Multi-service task orchestration and batch workflow engine"
)]
#[command(
    long_about = "Orchestrator - Manages distributed task execution, batch workflows, and cluster \
                  provisioning with state management and rollback recovery"
)]
#[command(
    after_help = "CONFIGURATION HIERARCHY (highest to lowest priority):\n  1. CLI: -c/--config \
                  <path> (explicit file)\n  2. CLI: --config-dir <dir> --mode <mode> (directory + \
                  mode)\n  3. CLI: --config-dir <dir> (searches for orchestrator.ncl|toml|json)\n  \
                  4. CLI: --mode <mode> (searches in provisioning/platform/config/)\n  5. ENV: \
                  ORCHESTRATOR_CONFIG (explicit file)\n  6. ENV: PROVISIONING_CONFIG_DIR \
                  (searches for orchestrator.ncl|toml|json)\n  7. ENV: ORCHESTRATOR_MODE \
                  (mode-based in default path)\n  8. Built-in defaults\n\nEXAMPLES:\n  # Explicit \
                  config file\n  orchestrator -c ~/my-config.toml\n\n  # Config directory with \
                  mode\n  orchestrator --config-dir ~/configs --mode enterprise\n\n  # Config \
                  directory (auto-discover file)\n  orchestrator --config-dir \
                  ~/.config/provisioning\n\n  # Via environment variables\n  export \
                  ORCHESTRATOR_CONFIG=~/.config/orchestrator.toml\n  orchestrator\n\n  # \
                  Mode-based configuration\n  orchestrator --mode solo"
)]
pub struct Args {
    /// Configuration file path (highest priority)
    ///
    /// Accepts absolute or relative path. Supports .ncl, .toml, and .json
    /// formats.
    #[arg(short = 'c', long, env = "ORCHESTRATOR_CONFIG")]
    pub config: Option<std::path::PathBuf>,

    /// Configuration directory (searches for orchestrator.ncl|toml|json)
    ///
    /// Searches for configuration files in order of preference: .ncl > .toml >
    /// .json Can also search for mode-specific files:
    /// orchestrator.{mode}.{ncl|toml|json}
    #[arg(long, env = "PROVISIONING_CONFIG_DIR")]
    pub config_dir: Option<std::path::PathBuf>,

    /// Deployment mode (solo, multiuser, cicd, enterprise)
    ///
    /// Determines which configuration profile to use. Searches in:
    /// provisioning/platform/config/orchestrator.{mode}.{ncl|toml}
    #[arg(short = 'm', long, env = "ORCHESTRATOR_MODE")]
    pub mode: Option<String>,

    /// Port to listen on (overrides config if specified)
    #[arg(short = 'p', long)]
    pub port: Option<u16>,

    /// Data directory for storage
    #[arg(short = 'd', long, default_value = "./data")]
    pub data_dir: String,

    /// Storage backend type
    #[arg(long, default_value = "filesystem", value_parser = validate_storage_type)]
    pub storage_type: String,

    /// SurrealDB server URL (for surrealdb-server mode)
    #[arg(long)]
    pub surrealdb_url: Option<String>,

    /// SurrealDB namespace
    #[arg(long, default_value = "orchestrator")]
    pub surrealdb_namespace: Option<String>,

    /// SurrealDB database name
    #[arg(long, default_value = "tasks")]
    pub surrealdb_database: Option<String>,

    /// SurrealDB username (for surrealdb-server mode)
    #[arg(long)]
    pub surrealdb_username: Option<String>,

    /// SurrealDB password (for surrealdb-server mode)
    #[arg(long)]
    pub surrealdb_password: Option<String>,

    /// Nushell executable path
    #[arg(long, default_value = "nu")]
    pub nu_path: String,

    /// Provisioning script path
    #[arg(long, default_value = "provisioning")]
    pub provisioning_path: String,

    /// Print all #[onto_api] registered routes as JSON and exit.
    /// Pipe to api-catalog-orchestrator.json: `just export-api-catalog`
    #[arg(long)]
    pub dump_api_catalog: bool,
}

// ============================================================================
// Core Modules (Always Available with 'core' feature)
// ============================================================================

pub mod app_state_builder;
pub mod config;
pub mod config_manager;
pub mod middleware;
pub mod response;
pub mod orchestrator_state;
pub mod preconditions;
pub mod probes;
pub mod secrets;
pub mod security;
pub mod security_integration;
pub mod services;
pub mod ssh_exec;
pub mod state;
pub mod storage;

// ============================================================================
// Optional Modules (Feature-Gated)
// ============================================================================

// Audit: Security event logging
#[cfg(feature = "audit")]
pub mod audit;

// Workflow: Orchestration, batch jobs, task management
#[cfg(feature = "workflow")]
pub mod batch;

#[cfg(feature = "workflow")]
pub mod formula;

#[cfg(feature = "workflow")]
pub mod dependency;

#[cfg(feature = "workflow")]
pub mod migration;

#[cfg(feature = "workflow")]
pub mod monitor;

#[cfg(feature = "workflow")]
pub mod queue;

#[cfg(feature = "workflow")]
pub mod rollback;

#[cfg(feature = "workflow")]
pub mod workflow;

// Compliance: Policy evaluation and break-glass emergency access
#[cfg(feature = "compliance")]
pub mod break_glass;

#[cfg(feature = "compliance")]
pub mod compliance;

// GitOps: Webhook handler and git pull executor
pub mod webhooks;

// Platform: Infrastructure integration
#[cfg(feature = "platform")]
pub mod dns;

#[cfg(feature = "platform")]
pub mod extensions;

#[cfg(feature = "platform")]
pub use security::oci;

// SSH: SSH key management
#[cfg(feature = "ssh")]
pub mod ssh;

// Infrastructure state service — NATS subscriber + SurrealDB writer
#[cfg(feature = "nats")]
pub mod infra_state;

// Build infrastructure: ephemeral VM pool for buildkit runners (ADR-039)
pub mod vm_pool;

// Testing: Test environment and container management
#[cfg(feature = "testing")]
pub mod container_manager;

#[cfg(feature = "testing")]
pub mod test_environment;

#[cfg(feature = "testing")]
pub mod test_orchestrator;

// Forward declaration for AppState - actual definition is in main.rs
// This allows modules to reference it via crate::AppState

// ============================================================================
// Re-exports - Stable API
// ============================================================================

// Core types (always available)
pub use app_state_builder::{
    create_orchestrator_app_state, DefaultOrchestratorAppStateBuilder, OrchestratorAppStateBuilder,
};
// Feature-gated re-exports
#[cfg(feature = "audit")]
pub use audit::{
    ActionInfo, ActionType, AuditEvent, AuditLogger, AuditLoggerConfig, AuditStatus, AuditStorage,
    AuthorizationInfo, FileStorage, RetentionPolicy, SiemFormat, UserInfo,
};
#[cfg(feature = "compliance")]
pub use break_glass::{
    create_router as create_break_glass_router, Approval, ApprovalConfig, AutoRevokeConfig,
    BreakGlassAuditEvent, BreakGlassConfig, BreakGlassEventType, BreakGlassRequest,
    BreakGlassService, BreakGlassSession, EmergencyAccessToken, Permission, RequestStatus, Role,
    SessionStatus, User,
};
#[cfg(feature = "compliance")]
pub use compliance::{
    compliance_routes, AccessControlConfig, AccessControlMatrix, ComplianceConfig,
    ComplianceHealthStatus, ComplianceService, ComplianceStatus, ControlResult, CriterionResult,
    DataClassification, DataProtection, DataProtectionConfig, DeletionReport, ErasureReason,
    ExportFormat, GdprService, GdprServiceConfig, IncidentResponse, IncidentResponseConfig,
    IncidentResponseService, IncidentSeverity, IncidentType, Iso27001Compliance, Iso27001Config,
    Iso27001Report, PersonalDataExport, ProtectionReport, RiskAssessment, Soc2Compliance,
    Soc2Config, Soc2Report,
};
#[cfg(feature = "platform")]
pub use dns::{CoreDnsClient, DnsManager, DnsRecord, DnsRecordType};
#[cfg(feature = "platform")]
pub use extensions::{
    Extension, ExtensionLoader, ExtensionManager, ExtensionMetadata, ExtensionType,
};
pub use middleware::AuditMiddleware;
#[cfg(feature = "platform")]
pub use oci::{OciArtifact, OciClient, OciManager, OciManifest};
pub use orchestrator_state::{AppState, SharedState};
pub use response::ApiResponse;
pub use secrets::{
    create_secrets_router, Credentials, DynamicSecret, RenewRequest, RevokeRequest, SecretMetadata,
    SecretRequest, SecretStats, SecretType, SecretsConfig, SecretsService,
};
pub use security::{
    auth_middleware,
    token_validator::{
        RevocationStats, TokenClaims, TokenType, TokenValidationError, TokenValidator,
        ValidatedToken,
    },
    AuthError, AuthenticatedUser, SecurityContext,
};
pub use services::{HealthStatus, Service, ServiceManager, ServiceOrchestrator, ServiceStatus};
#[cfg(feature = "ssh")]
pub use ssh::{
    create_ssh_routes, SshConfig, SshKeyDeployment, SshKeyManager, SshKeyRequest, SshKeyStats,
    SshKeyType, SshManagerState, TemporalSshKey,
};
pub use storage::traits::TaskStorage;
#[cfg(feature = "testing")]
pub use test_environment::{TestEnvironment, TestEnvironmentConfig, TestEnvironmentType};
