#!/usr/bin/env nu
# Backup KOGRAL graphs to archive
#
# Usage: nu kogral-backup.nu [--output <path>] [--format <tar|zip>] [--compress]

def main [
    --output: string = "kogral-backup"  # Output filename (without extension)
    --format: string = "tar"        # Archive format: tar or zip
    --compress                      # Compress the archive
    --kogral-dir: string = ".kogral"        # KOGRAL directory
    --include-metadata              # Include .git and other metadata
] {
    print $"(ansi green_bold)KOGRAL Backup(ansi reset)"
    print $"KOGRAL Directory: ($kogral-dir)"
    print $"Format: ($format)"
    print $"Compress: ($compress)"

    # Check if .kogral directory exists
    if not ($kogral-dir | path exists) {
        print $"(ansi red)Error: KOGRAL directory not found: ($kogral-dir)(ansi reset)"
        exit 1
    }

    # Generate timestamp
    let timestamp = date now | format date "%Y%m%d_%H%M%S"
    let backup_name = $"($output)_($timestamp)"

    # Determine file extension
    let extension = if $compress {
        if $format == "tar" { ".tar.gz" } else { ".zip" }
    } else {
        if $format == "tar" { ".tar" } else { ".zip" }
    }

    let backup_file = $"($backup_name)($extension)"

    print $"\n(ansi cyan_bold)Preparing backup...(ansi reset)"
    print $"Output file: ($backup_file)"

    # Count files
    let stats = get_kogral_stats $kogral_dir

    print $"\n(ansi cyan_bold)Files to backup:(ansi reset)"
    print $"  Notes:      ($stats.notes)"
    print $"  Decisions:  ($stats.decisions)"
    print $"  Guidelines: ($stats.guidelines)"
    print $"  Patterns:   ($stats.patterns)"
    print $"  Journal:    ($stats.journal)"
    print $"  Config:     ($stats.config)"
    print $"  Total:      ($stats.total)"

    # Create backup
    print $"\n(ansi cyan_bold)Creating backup...(ansi reset)"

    match $format {
        "tar" => {
            create_tar_backup $kogral_dir $backup_file $compress $include_metadata
        },
        "zip" => {
            create_zip_backup $kogral_dir $backup_file $include_metadata
        },
        _ => {
            print $"(ansi red)Error: Invalid format. Use: tar or zip(ansi reset)"
            exit 1
        }
    }

    # Verify backup
    if ($backup_file | path exists) {
        let size = ls $backup_file | get size | first
        print $"\n(ansi green_bold)✓ Backup created successfully(ansi reset)"
        print $"File: ($backup_file)"
        print $"Size: ($size)"
    } else {
        print $"\n(ansi red)✗ Backup creation failed(ansi reset)"
        exit 1
    }

    # Generate manifest
    print $"\n(ansi cyan_bold)Generating manifest...(ansi reset)"
    let manifest = generate_manifest $kogral_dir $backup_file $stats $timestamp
    let manifest_file = $"($backup_name).manifest.json"
    $manifest | to json | save $manifest_file
    print $"Manifest saved: ($manifest_file)"

    print $"\n(ansi green_bold)✓ Backup completed(ansi reset)"
}

def get_kogral_stats [kogral_dir: string] -> record {
    let notes = (glob $"($kogral_dir)/notes/**/*.md" | length)
    let decisions = (glob $"($kogral_dir)/decisions/**/*.md" | length)
    let guidelines = (glob $"($kogral_dir)/guidelines/**/*.md" | length)
    let patterns = (glob $"($kogral_dir)/patterns/**/*.md" | length)
    let journal = (glob $"($kogral_dir)/journal/**/*.md" | length)
    let config = if ($"($kogral_dir)/config.toml" | path exists) { 1 } else { 0 }

    {
        notes: $notes,
        decisions: $decisions,
        guidelines: $guidelines,
        patterns: $patterns,
        journal: $journal,
        config: $config,
        total: ($notes + $decisions + $guidelines + $patterns + $journal + $config)
    }
}

def create_tar_backup [kogral_dir: string, output: string, compress: bool, include_metadata: bool] {
    let compress_flag = if $compress { "z" } else { "" }
    let exclude_flags = if not $include_metadata {
        ["--exclude=.git", "--exclude=.DS_Store"]
    } else {
        []
    }

    print $"  Creating tar archive..."

    # Use tar command
    let tar_cmd = if $compress {
        $"tar -c($compress_flag)f ($output) ($exclude_flags | str join ' ') ($kogral_dir)"
    } else {
        $"tar -cf ($output) ($exclude_flags | str join ' ') ($kogral_dir)"
    }

    try {
        bash -c $tar_cmd
        print $"  (ansi green)✓ Tar archive created(ansi reset)"
    } catch {
        print $"  (ansi red)✗ Tar archive creation failed(ansi reset)"
    }
}

def create_zip_backup [kogral_dir: string, output: string, include_metadata: bool] {
    print $"  Creating zip archive..."

    let exclude_pattern = if not $include_metadata { "*.git* */.DS_Store" } else { "" }

    try {
        bash -c $"zip -r ($output) ($kogral_dir) -x ($exclude_pattern)"
        print $"  (ansi green)✓ Zip archive created(ansi reset)"
    } catch {
        print $"  (ansi red)✗ Zip archive creation failed(ansi reset)"
    }
}

def generate_manifest [kogral_dir: string, backup_file: string, stats: record, timestamp: string] -> record {
    let config_path = $"($kogral_dir)/config.toml"
    let config = if ($config_path | path exists) {
        open $config_path | from toml
    } else {
        { graph: { name: "unknown", version: "unknown" } }
    }

    {
        backup_timestamp: $timestamp,
        backup_file: $backup_file,
        kogral_directory: $kogral_dir,
        graph_name: $config.graph.name,
        graph_version: $config.graph.version,
        statistics: $stats,
        created_by: "kogral-backup.nu",
        version: "1.0.0"
    }
}
