//! SystemBackupDef — backup specifications for artefacts outside the cluster.
//!
//! Targets include etcd, k8s certs, host configs, external DNS configurations,
//! builder environment tools, provisioning state, log archives, SOPS/Age key
//! bundles, and vault state. Each target is a discriminated variant; the
//! manager dispatches based on `kind` (see ADR-011 for vault state custody).

use serde::{Deserialize, Serialize};

use super::component::{
    BackupProviderRef, Destination, RetentionPolicy, ScheduleSpec, TagStrategy, Throttle,
    VaultCredRef, VaultKeyRef, VerifyPolicyRef, Hooks,
};

/// Discriminator for [`HostSelector`].
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum HostSelectorKind {
    /// Run on a single control-plane host (any).
    CpOnly,
    /// Run on the first control-plane host (deterministic by name sort).
    CpFirst,
    /// Run on all control-plane hosts.
    ControlPlanes,
    /// Run on all worker hosts.
    Workers,
    /// Run on every server in the workspace.
    AllServers,
    /// Run on the listed hosts.
    List,
}

/// Selects which hosts execute a system backup. Mirrors the Nickel `HostSelector`.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HostSelector {
    /// Variant.
    pub kind: HostSelectorKind,
    /// Hostname list when `kind = List`.
    #[serde(default)]
    pub members: Vec<String>,
}

/// Discriminator for [`SystemBackupTarget`].
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum SystemBackupTargetKind {
    /// etcd snapshot via etcdctl.
    Etcd,
    /// Kubernetes PKI certificates (`/etc/kubernetes/pki`).
    K8sCerts,
    /// Cluster resources (Secret/ConfigMap/CRD content).
    ClusterResources,
    /// Longhorn engine state.
    LonghornEngine,
    /// Host configuration files.
    HostConfigs,
    /// External DNS server configuration and zone files.
    ExternalDns,
    /// Builder environment tools and caches.
    BuilderEnv,
    /// Provisioning state (definitions, state, locks).
    ProvisioningState,
    /// Log archive (loki / journald / files).
    LogsArchive,
    /// SOPS/Age key bundle (separate custody chain).
    SopsKeys,
    /// secretumvault state (with bootstrap-key encryption per ADR-011).
    VaultState,
}

/// Discriminated target description.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemBackupTarget {
    /// Variant.
    pub kind: SystemBackupTargetKind,

    // ── 'etcd
    /// etcd endpoints.
    #[serde(default)]
    pub endpoints: Vec<String>,
    /// CA reference.
    #[serde(default)]
    pub ca_ref: Option<VaultCredRef>,
    /// Client cert reference.
    #[serde(default)]
    pub cert_ref: Option<VaultCredRef>,
    /// Client key reference.
    #[serde(default)]
    pub key_ref: Option<VaultCredRef>,

    // ── 'k8s_certs / 'host_configs / 'logs_archive (paths)
    /// Path list.
    #[serde(default)]
    pub paths: Vec<String>,
    /// Exclusion globs.
    #[serde(default)]
    pub exclude: Vec<String>,

    // ── 'cluster_resources
    /// Namespace list.
    #[serde(default)]
    pub namespaces: Vec<String>,
    /// Kind list (`secret`, `certificate`, ...).
    #[serde(default)]
    pub kinds: Vec<String>,

    // ── 'longhorn_engine
    /// Component list (`volumes`, `engines`, `replicas`, `settings`).
    #[serde(default)]
    pub components: Vec<String>,

    // ── 'external_dns
    /// Source kind (`coredns`, `powerdns`, `unbound`, ...).
    #[serde(default)]
    pub source_kind: Option<String>,
    /// Config file paths.
    #[serde(default)]
    pub config_paths: Vec<String>,
    /// Zone file directories.
    #[serde(default)]
    pub zones_paths: Vec<String>,

    // ── 'builder_env
    /// Tool names (informational tags).
    #[serde(default)]
    pub tools: Vec<String>,
    /// Secret names that must accompany the artefact.
    #[serde(default)]
    pub secrets: Vec<String>,

    // ── 'provisioning_state
    /// Definitions directory.
    #[serde(default)]
    pub definitions_path: Option<String>,
    /// State directory.
    #[serde(default)]
    pub state_path: Option<String>,
    /// Lock directory.
    #[serde(default)]
    pub lock_path: Option<String>,

    // ── 'logs_archive
    /// Loki/journald selector.
    #[serde(default)]
    pub selector: Option<String>,
    /// Archive format.
    #[serde(default)]
    pub format: Option<String>,

    // ── 'sops_keys / 'vault_state
    /// Age key file paths.
    #[serde(default)]
    pub age_keys: Vec<String>,
    /// Recipient public keys.
    #[serde(default)]
    pub recipients: Vec<String>,
    /// Vault HTTP endpoint to back up.
    #[serde(default)]
    pub vault_endpoint: Option<String>,
    /// Specific vault paths to capture (omitted = full state).
    #[serde(default)]
    pub vault_paths: Vec<String>,
}

/// Top-level system backup definition.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemBackupDef {
    /// Identifier (used in CLI: `prvng-backup one-shot backup <name>`).
    pub name: String,
    /// Target description.
    pub target: SystemBackupTarget,
    /// Host selector.
    pub host_selector: HostSelector,
    /// Provider.
    pub provider: BackupProviderRef,
    /// Schedule.
    pub schedule: ScheduleSpec,
    /// Retention.
    pub retention: RetentionPolicy,
    /// Destinations.
    pub destinations: Vec<Destination>,
    /// Encryption key. For `VaultState`, ADR-011 requires a bootstrap key
    /// stored OUTSIDE vault (offline custody).
    pub encryption: VaultKeyRef,
    /// Tag strategy.
    pub tag_strategy: TagStrategy,
    /// Optional verify reference.
    #[serde(default)]
    pub verify: Option<VerifyPolicyRef>,
    /// Optional hooks.
    #[serde(default)]
    pub hooks: Option<Hooks>,
    /// Optional throttle.
    #[serde(default)]
    pub throttle: Option<Throttle>,
}
