#!/usr/bin/env nu
# Run schema migrations for KOGRAL
#
# Usage: nu kogral-migrate.nu [--target <version>] [--dry-run]

def main [
    --target: string = "latest"  # Target migration version
    --dry-run                    # Show what would be migrated without making changes
    --kogral-dir: string = ".kogral"     # KOGRAL directory
] {
    print $"(ansi green_bold)KOGRAL Migration(ansi reset)"
    print $"Target version: ($target)"
    print $"KOGRAL Directory: ($kogral_dir)"

    if $dry_run {
        print $"(ansi yellow)DRY RUN MODE - No changes will be made(ansi reset)"
    }

    # 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
    }

    # Load current version from config
    let config_path = $"($kogral_dir)/config.toml"
    if not ($config_path | path exists) {
        print $"(ansi red)Error: Config file not found: ($config_path)(ansi reset)"
        exit 1
    }

    let config = open $config_path | from toml
    let current_version = $config.graph.version

    print $"\n(ansi cyan_bold)Current schema version:(ansi reset) ($current_version)"

    # Define available migrations
    let migrations = [
        { version: "1.0.0", description: "Initial schema" },
        { version: "1.1.0", description: "Add metadata field to nodes" },
        { version: "1.2.0", description: "Add embedding support" },
    ]

    print $"\n(ansi cyan_bold)Available migrations:(ansi reset)"
    for migration in $migrations {
        let indicator = if $migration.version == $current_version {
            $"(ansi green)✓ [CURRENT](ansi reset)"
        } else {
            "  "
        }
        print $"($indicator) ($migration.version) - ($migration.description)"
    }

    # Determine migrations to run
    let target_version = if $target == "latest" {
        $migrations | last | get version
    } else {
        $target
    }

    print $"\n(ansi cyan_bold)Target version:(ansi reset) ($target_version)"

    if $current_version == $target_version {
        print $"\n(ansi green)Already at target version. No migrations needed.(ansi reset)"
        exit 0
    }

    # Find migrations to apply
    let to_apply = $migrations | where version > $current_version and version <= $target_version

    if ($to_apply | length) == 0 {
        print $"\n(ansi yellow)No migrations to apply(ansi reset)"
        exit 0
    }

    print $"\n(ansi cyan_bold)Migrations to apply:(ansi reset)"
    for migration in $to_apply {
        print $"  → ($migration.version): ($migration.description)"
    }

    if $dry_run {
        print $"\n(ansi yellow)[DRY RUN] Would apply ($to_apply | length) migration(s)(ansi reset)"
        exit 0
    }

    # Apply migrations
    print $"\n(ansi cyan_bold)Applying migrations...(ansi reset)"

    mut final_version = $current_version

    for migration in $to_apply {
        print $"\n(ansi blue)Migrating to ($migration.version)...(ansi reset)"
        apply_migration $migration $kogral_dir
        $final_version = $migration.version
    }

    # Phase: Update version in config
    print $"\n(ansi cyan_bold)Updating config version...(ansi reset)"
    update_config_version $config_path $final_version

    print $"\n(ansi green_bold)✓ Migration completed(ansi reset)"
    print $"Schema version: ($current_version) → ($final_version)"
}

def apply_migration [migration: record, kogral_dir: string] {
    match $migration.version {
        "1.0.0" => {
            print "  ✓ Initial schema (no action needed)"
        },
        "1.1.0" => {
            # Phase 1: Add metadata field to existing nodes
            print "  Adding metadata field support..."
            add_metadata_field $kogral_dir
            print "  ✓ Metadata field added"
        },
        "1.2.0" => {
            # Phase 2: Add embedding support
            print "  Adding embedding support..."
            add_embedding_support $kogral_dir
            print "  ✓ Embedding support added"
        },
        _ => {
            print $"  (ansi yellow)Unknown migration version: ($migration.version)(ansi reset)"
        }
    }
}

def update_config_version [config_path: string, new_version: string] {
    # Phase 1: Read current config
    let config = open $config_path | from toml

    # Phase 2: Update version
    let updated = $config | insert "graph.version" $new_version

    # Phase 3: Convert back to TOML and save
    $updated | to toml | save --force $config_path
    print "  ✓ Config version updated"
}

def add_metadata_field [kogral_dir: string] {
    # Phase 1: Find all markdown files
    let all_files = find_all_markdown_files $kogral_dir

    # Phase 2: Process each file
    mut updated = 0
    for file in $all_files {
        let content = open $file
        let lines = $content | lines

        # Phase 3: Check if metadata field exists
        let has_metadata_field = $lines | any { |l| $l =~ '^(metadata|---):' }

        if not $has_metadata_field {
            # Phase 4: Add empty metadata field before closing ---
            let updated_content = insert_metadata_field $content
            $updated_content | save --force $file
            $updated = $updated + 1
        }
    }

    print $"  Updated ($updated) files"
}

def add_embedding_support [kogral_dir: string] {
    # Phase 1: Find all markdown files
    let all_files = find_all_markdown_files $kogral_dir

    # Phase 2: Note that embeddings will be generated on next reindex
    print $"  Embedding vectors will be generated on next reindex"
    print $"  Run 'kogral-reindex.nu' after migration to populate embeddings"
}

def find_all_markdown_files [kogral_dir: string] {
    # Phase 1: Collect from all node type directories
    mut all_files = []

    for dir_type in ["notes" "decisions" "guidelines" "patterns" "journal"] {
        let dir_path = $"($kogral_dir)/($dir_type)"
        if ($dir_path | path exists) {
            let files = glob $"($dir_path)/**/*.md"
            $all_files = ($all_files | append $files)
        }
    }

    $all_files
}

def insert_metadata_field [content: string] {
    let lines = $content | lines

    # Phase 1: Find the closing --- of frontmatter
    mut closing_idx = 0
    mut found_opening = false

    for idx in (0..<($lines | length)) {
        if $idx == 0 and ($lines | get $idx | str trim) == "---" {
            $found_opening = true
            continue
        }

        if $found_opening and ($lines | get $idx | str trim) == "---" {
            $closing_idx = $idx
            break
        }
    }

    # Phase 2: Insert metadata field before closing ---
    if $found_opening and $closing_idx > 0 {
        let before = $lines | take $closing_idx
        let after = $lines | skip $closing_idx

        let updated = $before | append ["metadata: {}"] | append $after
        $updated | str join "\n"
    } else {
        # No frontmatter, return as-is
        $content
    }
}
