#!/usr/bin/env nu

# VAPORA Restic Backup Script
# Incremental, deduplicated backups with integrated encryption
# Follows NUSHELL_GUIDELINES.md strictly (0.109.0+)

# Get timestamp
def get-timestamp []: nothing -> string {
    date now | format date "%Y%m%d-%H%M%S"
}

# Initialize Restic repository
def init-restic-repo [
    repo_path: string
    password: string
]: nothing -> record {
    print $"Initializing Restic repository at [$repo_path]..."

    # Check if already initialized
    let check_result = do {
        ^bash -c $"RESTIC_PASSWORD=($password) restic -r ($repo_path) list snapshots"
    } | complete

    if ($check_result.exit_code == 0) {
        {
            success: true
            repo: $repo_path
            action: "verified"
            error: null
        }
    } else {
        # Initialize new repository
        let init_result = do {
            ^bash -c $"RESTIC_PASSWORD=($password) restic -r ($repo_path) init"
        } | complete

        if ($init_result.exit_code == 0) {
            {
                success: true
                repo: $repo_path
                action: "initialized"
                error: null
            }
        } else {
            {
                success: false
                repo: $repo_path
                action: "init-failed"
                error: ($init_result.stderr | str trim)
            }
        }
    }
}

# Backup directory to Restic
def backup-to-restic [
    backup_dir: string
    repo_path: string
    password: string
    tag: string
    backup_type: string
]: nothing -> record {
    print $"Backing up [$backup_type] via Restic..."

    let result = do {
        ^bash -c (
            $"RESTIC_PASSWORD=($password) restic -r ($repo_path) " +
            $"backup ($backup_dir) --tag ($tag) --tag ($backup_type)"
        )
    } | complete

    if ($result.exit_code == 0) {
        {
            success: true
            tag: $tag
            backup_type: $backup_type
            output: ($result.stdout | str trim)
            error: null
        }
    } else {
        {
            success: false
            tag: $tag
            backup_type: $backup_type
            error: ($result.stderr | str trim)
        }
    }
}

# Get repository statistics
def get-repo-stats [
    repo_path: string
    password: string
]: nothing -> record {
    print "Getting repository statistics..."

    let result = do {
        ^bash -c $"RESTIC_PASSWORD=($password) restic -r ($repo_path) stats --mode raw"
    } | complete

    if ($result.exit_code == 0) {
        {
            success: true
            stats: ($result.stdout | str trim)
            error: null
        }
    } else {
        {
            success: false
            stats: null
            error: ($result.stderr | str trim)
        }
    }
}

# List recent snapshots
def list-snapshots [
    repo_path: string
    password: string
    limit: int
]: nothing -> record {
    print $"Listing recent snapshots (limit: [$limit])..."

    let result = do {
        ^bash -c (
            $"RESTIC_PASSWORD=($password) restic -r ($repo_path) " +
            $"list snapshots --max ($limit)"
        )
    } | complete

    if ($result.exit_code == 0) {
        {
            success: true
            count: ($result.stdout | lines | length)
            snapshots: ($result.stdout | str trim)
            error: null
        }
    } else {
        {
            success: false
            count: 0
            snapshots: null
            error: ($result.stderr | str trim)
        }
    }
}

# Verify backup integrity
def verify-repository [
    repo_path: string
    password: string
]: nothing -> record {
    print "Verifying backup integrity..."

    let result = do {
        ^bash -c (
            $"RESTIC_PASSWORD=($password) restic -r ($repo_path) " +
            "check --read-data-subset=10%"
        )
    } | complete

    if ($result.exit_code == 0) {
        {
            success: true
            message: "Integrity check passed"
            error: null
        }
    } else {
        {
            success: false
            message: null
            error: ($result.stderr | str trim)
        }
    }
}

# Cleanup old snapshots
def cleanup-old-snapshots [
    repo_path: string
    password: string
    keep_daily: int
    keep_weekly: int
    keep_monthly: int
]: nothing -> record {
    print $"Cleaning up old snapshots (daily: [$keep_daily], weekly: [$keep_weekly], monthly: [$keep_monthly])..."

    let result = do {
        ^bash -c (
            $"RESTIC_PASSWORD=($password) restic -r ($repo_path) forget " +
            $"--keep-daily ($keep_daily) --keep-weekly ($keep_weekly) " +
            $"--keep-monthly ($keep_monthly) --prune"
        )
    } | complete

    if ($result.exit_code == 0) {
        {
            success: true
            message: ($result.stdout | str trim)
            error: null
        }
    } else {
        {
            success: false
            message: null
            error: ($result.stderr | str trim)
        }
    }
}

# Collect backup results using reduce
def collect-results [
    items: list
]: nothing -> list {
    $items | reduce --fold [] {|item, acc|
        $acc | append $item
    }
}

# Main Restic backup
def main [
    --repo: string = ""
    --password: string = ""
    --database-dir: string = "/tmp/vapora-db-backup"
    --k8s-dir: string = "/tmp/vapora-k8s-backup"
    --iac-dir: string = "provisioning"
    --backup-db
    --backup-k8s
    --backup-iac
    --verify
    --cleanup
    --keep-daily: int = 7
    --keep-weekly: int = 4
    --keep-monthly: int = 12
]: nothing {
    print "=== VAPORA Restic Backup ==="
    print ""

    # Validate inputs
    if ($repo == "") {
        print "ERROR: --repo required (s3://bucket/path or /local/path)"
        exit 1
    }

    if ($password == "") {
        print "ERROR: --password required"
        exit 1
    }

    # Initialize repository
    let init_result = (init-restic-repo $repo $password)
    if (not $init_result.success) {
        print $"ERROR: Repository initialization failed: [$init_result.error]"
        exit 1
    }

    print $"✓ Repository [$init_result.action]"

    let backup_tag = (get-timestamp)

    # Backup database if requested
    let db_backup = if $backup_db {
        let result = (backup-to-restic $database_dir $repo $password $backup_tag "database")
        if (not $result.success) {
            print $"WARNING: Database backup failed: [$result.error]"
        } else {
            print "✓ Database backed up"
        }
        $result
    } else {
        { success: false backup_type: "database" }
    }

    # Backup Kubernetes if requested
    let k8s_backup = if $backup_k8s {
        let result = (backup-to-restic $k8s_dir $repo $password $backup_tag "kubernetes")
        if (not $result.success) {
            print $"WARNING: Kubernetes backup failed: [$result.error]"
        } else {
            print "✓ Kubernetes configs backed up"
        }
        $result
    } else {
        { success: false backup_type: "kubernetes" }
    }

    # Backup IaC if requested
    let iac_backup = if $backup_iac {
        let result = (backup-to-restic $iac_dir $repo $password $backup_tag "iac")
        if (not $result.success) {
            print $"WARNING: IaC backup failed: [$result.error]"
        } else {
            print "✓ IaC backed up"
        }
        $result
    } else {
        { success: false backup_type: "iac" }
    }

    # Collect results
    let backups = (collect-results [
        $db_backup
        $k8s_backup
        $iac_backup
    ])

    # Verify repository
    if $verify {
        let verify_result = (verify-repository $repo $password)
        if (not $verify_result.success) {
            print $"WARNING: Integrity check failed: [$verify_result.error]"
        } else {
            print "✓ Backup integrity verified"
        }
    }

    # Cleanup old snapshots
    if $cleanup {
        let cleanup_result = (cleanup-old-snapshots $repo $password $keep_daily $keep_weekly $keep_monthly)
        if (not $cleanup_result.success) {
            print $"WARNING: Cleanup failed: [$cleanup_result.error]"
        } else {
            print "✓ Old snapshots cleaned up"
        }
    }

    # Show repository stats
    let stats_result = (get-repo-stats $repo $password)
    if ($stats_result.success) {
        print ""
        print "Repository Statistics:"
        print $stats_result.stats
    }

    # List recent snapshots
    let snapshots_result = (list-snapshots $repo $password 5)
    if ($snapshots_result.success) {
        print ""
        print $"Recent snapshots ([$snapshots_result.count] shown):"
        print $snapshots_result.snapshots
    }

    # Summary
    print ""
    print "=== Backup Complete ==="
    print $"Repository: [$repo]"
    print $"Timestamp: [$backup_tag]"
    let successful = ($backups | where {|b| $b.success} | length)
    print $"Successful backups: [$successful]"
}
