//! BackupScope and DumpStrategy types — the unit of backup work.
//!
//! Each scope expands to one provider invocation with deterministic tags.
//! The discriminator is `kind`; the rest of the fields are populated only
//! for variants that use them (Nickel emits `default = []`/`default = {}`).

use std::collections::BTreeMap;

use serde::{Deserialize, Serialize};

/// Discriminator for [`BackupScope`].
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ScopeKind {
    /// Snapshot a fixed list of paths.
    ServiceFull,
    /// Snapshot per domain (one tag set per domain).
    PerDomain,
    /// Snapshot per mailbox (selector-driven enumeration).
    PerMailbox,
    /// Snapshot a database via a [`DumpStrategy`].
    Database,
    /// Snapshot a CSI volume by name.
    VolumeSnapshot,
    /// Archive logs from a source (loki / journald / files).
    LogsArchive,
    /// Export a subset of a key-value store (etcd / consul).
    KvExport,
}

/// Database engine, when scope kind is [`ScopeKind::Database`].
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum DbEngine {
    /// PostgreSQL — supports streaming pg_dump and WAL archiving externally.
    Postgresql,
    /// MariaDB.
    Mariadb,
    /// MySQL.
    Mysql,
    /// Redis (RDB snapshot or AOF).
    Redis,
    /// MongoDB (mongodump).
    Mongodb,
    /// SurrealDB.
    Surrealdb,
    /// etcd (etcdctl snapshot).
    Etcd,
    /// SQLite (file-level).
    Sqlite,
}

/// Discriminator for [`DumpStrategy`].
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum DumpStrategyKind {
    /// Stream the dump straight to the provider's stdin.
    StreamToStdin,
    /// Write the dump to a path, then snapshot the path.
    DumpToPath,
    /// Like `DumpToPath` but with a custom dump command.
    PreDumpThenPath,
    /// CSI VolumeSnapshot CRD (crash-consistent, no app coordination).
    CsiVolumeSnapshot,
    /// Application quiesce hook + snapshot + unquiesce.
    AppQuiesceThenSnapshot,
}

/// Strategy for capturing a database scope. See ADR-013 for the consistency
/// trade-offs across variants.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DumpStrategy {
    /// Variant discriminator.
    pub kind: DumpStrategyKind,

    /// Custom dump command (optional, used by `PreDumpThenPath`).
    #[serde(default)]
    pub dump_command: Option<String>,

    /// Path where the dump file lives (`DumpToPath`, `PreDumpThenPath`).
    #[serde(default)]
    pub path: Option<String>,

    /// Whether to remove the dump file after the snapshot completes.
    #[serde(default = "default_true")]
    pub cleanup: bool,

    /// CSI volume name (`CsiVolumeSnapshot`, `AppQuiesceThenSnapshot`).
    #[serde(default)]
    pub volume: Option<String>,

    /// CSI VolumeSnapshotClass.
    #[serde(default)]
    pub snapshot_class: Option<String>,

    /// Quiesce command (`AppQuiesceThenSnapshot`).
    #[serde(default)]
    pub quiesce_cmd: Option<String>,

    /// Unquiesce command (`AppQuiesceThenSnapshot`).
    #[serde(default)]
    pub unquiesce_cmd: Option<String>,
}

fn default_true() -> bool { true }

/// One unit of backup work. The provider receives this via [`crate::policy::component::BackupPolicy`].
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BackupScope {
    /// Discriminator.
    pub kind: ScopeKind,

    /// Identifier for the scope (used in CLI: `--scope <name>`).
    pub name: String,

    /// Path list (`ServiceFull`, `LogsArchive`).
    #[serde(default)]
    pub paths: Vec<String>,

    /// Exclusion globs.
    #[serde(default)]
    pub exclude: Vec<String>,

    /// Domain list (`PerDomain`).
    #[serde(default)]
    pub domains: Vec<String>,

    /// Base path for per-domain / per-mailbox scopes.
    #[serde(default)]
    pub base_path: String,

    /// Mailbox selector (`PerMailbox`).
    #[serde(default)]
    pub selector: Option<String>,

    /// Database engine (`Database`).
    #[serde(default)]
    pub engine: Option<DbEngine>,

    /// Dump strategy (`Database`).
    #[serde(default)]
    pub dump_strategy: Option<DumpStrategy>,

    /// Volume names (`VolumeSnapshot`).
    #[serde(default)]
    pub volumes: Vec<String>,

    /// CSI VolumeSnapshotClass (`VolumeSnapshot`).
    #[serde(default)]
    pub snapshot_class: Option<String>,

    /// Log sources (`LogsArchive`).
    #[serde(default)]
    pub sources: Vec<String>,

    /// Log archive format (`LogsArchive`).
    #[serde(default)]
    pub format: Option<String>,

    /// Rotation duration (`LogsArchive`).
    #[serde(default)]
    pub rotation: Option<String>,

    /// KV source kind (`KvExport`).
    #[serde(default)]
    pub source: Option<String>,

    /// Tag prefix prepended to determinístico tags.
    #[serde(default)]
    pub tag_prefix: String,

    /// Static extra tags (key-value).
    #[serde(default)]
    pub tags: BTreeMap<String, String>,
}
