# Workspace Version Management Module
# Handles workspace version tracking, compatibility checking, and version metadata

use std log

# Version comparison result
export def compare-versions [
    version1: string
    version2: string
] {
    # Parse semantic versions (e.g., "1.2.3")
    let v1_parts = ($version1 | split row "." | each { into int })
    let v2_parts = ($version2 | split row "." | each { into int })

    # Compare major version
    if ($v1_parts.0 > $v2_parts.0) {
        return "greater"
    } else if ($v1_parts.0 < $v2_parts.0) {
        return "less"
    }

    # Compare minor version
    if ($v1_parts.1 > $v2_parts.1) {
        return "greater"
    } else if ($v1_parts.1 < $v2_parts.1) {
        return "less"
    }

    # Compare patch version
    if ($v1_parts.2 > $v2_parts.2) {
        return "greater"
    } else if ($v1_parts.2 < $v2_parts.2) {
        return "less"
    }

    return "equal"
}

# Check if version is compatible
export def is-version-compatible [
    current: string
    required: string
] {
    let comparison = (compare-versions $current $required)

    # Current version must be >= required version
    $comparison == "equal" or $comparison == "greater"
}

# Get current provisioning system version
export def get-system-version [] {
    # Read from environment or CLI version
    if ($env.PROVISIONING_VERS? | is-not-empty) {
        return $env.PROVISIONING_VERS
    }

    # Fallback: read from CLI script
    let cli_path = ([$env.PROVISIONING "core" "cli" "provisioning"] | path join)
    if ($cli_path | path exists) {
        let version_line = (open $cli_path | lines | where $it =~ "^# Release:" | first)
        if ($version_line | is-not-empty) {
            return ($version_line | str replace "# Release: " "" | str trim)
        }
    }

    # Default fallback
    return "1.0.11"
}

# Get workspace metadata path
export def get-workspace-metadata-path [
    workspace_path: string
] {
    $workspace_path | path join ".provisioning" | path join "metadata.yaml"
}

# Load workspace metadata
export def load-workspace-metadata [
    workspace_path: string
] {
    let metadata_path = (get-workspace-metadata-path $workspace_path)

    if not ($metadata_path | path exists) {
        return {
            version: {
                provisioning: "unknown"
                schema: "unknown"
                workspace_format: "unknown"
            }
            created: "unknown"
            last_updated: "unknown"
            migration_history: []
        }
    }

    # Try to open and parse the metadata file
    open $metadata_path
}

# Save workspace metadata
export def save-workspace-metadata [
    workspace_path: string
    metadata: record
] {
    let metadata_path = (get-workspace-metadata-path $workspace_path)
    let metadata_dir = ($metadata_path | path dirname)

    # Create .provisioning directory if it doesn't exist
    if not ($metadata_dir | path exists) {
        mkdir $metadata_dir
    }

    # Update last_updated timestamp
    let updated_metadata = (
        $metadata
        | upsert last_updated (date now | format date "%Y-%m-%dT%H:%M:%SZ")
    )

    $updated_metadata | to yaml | save -f $metadata_path
}

# Initialize workspace metadata
export def init-workspace-metadata [
    workspace_path: string
    workspace_name: string
] {
    let system_version = (get-system-version)

    let metadata = {
        workspace: {
            name: $workspace_name
            path: $workspace_path
        }
        version: {
            provisioning: $system_version
            schema: "1.0.0"
            workspace_format: "1.0.0"
        }
        created: (date now | format date "%Y-%m-%dT%H:%M:%SZ")
        last_updated: (date now | format date "%Y-%m-%dT%H:%M:%SZ")
        migration_history: []
        compatibility: {
            min_provisioning_version: "1.0.0"
            min_schema_version: "1.0.0"
        }
    }

    save-workspace-metadata $workspace_path $metadata

    return $metadata
}

# Check workspace version compatibility
export def check-workspace-compatibility [
    workspace_path: string
] {
    let metadata = (load-workspace-metadata $workspace_path)
    let system_version = (get-system-version)

    # Check if metadata exists and has version info
    if ($metadata.version.provisioning == "unknown") {
        return {
            compatible: false
            reason: "no_metadata"
            message: "Workspace metadata not found or corrupted"
            requires_migration: true
            current_system: $system_version
            workspace_version: "unknown"
        }
    }

    let workspace_version = $metadata.version.provisioning
    let min_required = ($metadata.compatibility?.min_provisioning_version? | default "2.0.0")

    # Check if system version meets minimum requirement
    let system_compatible = (is-version-compatible $system_version $min_required)

    if not $system_compatible {
        return {
            compatible: false
            reason: "version_too_old"
            message: $"Provisioning system version ($system_version) is older than required ($min_required)"
            requires_migration: false
            requires_upgrade: true
            current_system: $system_version
            workspace_version: $workspace_version
            min_required: $min_required
        }
    }

    # Check if workspace needs migration
    let version_comparison = (compare-versions $system_version $workspace_version)

    if ($version_comparison == "greater") {
        # System is newer - workspace may need migration
        return {
            compatible: true
            reason: "migration_available"
            message: $"Workspace can be migrated from ($workspace_version) to ($system_version)"
            requires_migration: true
            migration_optional: true
            current_system: $system_version
            workspace_version: $workspace_version
        }
    }

    if ($version_comparison == "less") {
        # Workspace is newer than system - incompatible
        return {
            compatible: false
            reason: "workspace_too_new"
            message: $"Workspace version ($workspace_version) is newer than system ($system_version)"
            requires_migration: false
            requires_upgrade: true
            current_system: $system_version
            workspace_version: $workspace_version
        }
    }

    # Versions match - fully compatible
    return {
        compatible: true
        reason: "version_match"
        message: "Workspace and system versions match"
        requires_migration: false
        current_system: $system_version
        workspace_version: $workspace_version
    }
}

# Add migration record to workspace metadata
export def add-migration-record [
    workspace_path: string
    from_version: string
    to_version: string
    migration_type: string
    success: bool
    notes?: string
] {
    let metadata = (load-workspace-metadata $workspace_path)

    let migration_record = {
        from_version: $from_version
        to_version: $to_version
        migration_type: $migration_type
        timestamp: (date now | format date "%Y-%m-%dT%H:%M:%SZ")
        success: $success
        notes: ($notes | default "")
    }

    let updated_metadata = (
        $metadata
        | upsert migration_history ($metadata.migration_history | append $migration_record)
        | upsert version.provisioning $to_version
    )

    save-workspace-metadata $workspace_path $updated_metadata
}

# Get workspace version summary
export def get-version-summary [
    workspace_path: string
] {
    let metadata = (load-workspace-metadata $workspace_path)
    let system_version = (get-system-version)
    let compatibility = (check-workspace-compatibility $workspace_path)

    return {
        system: {
            version: $system_version
        }
        workspace: {
            name: ($metadata.workspace?.name? | default "unknown")
            path: $workspace_path
            version: ($metadata.version?.provisioning? | default "unknown")
            schema_version: ($metadata.version?.schema? | default "unknown")
            format_version: ($metadata.version?.workspace_format? | default "unknown")
            created: ($metadata.created? | default "unknown")
            last_updated: ($metadata.last_updated? | default "unknown")
        }
        compatibility: $compatibility
        migrations: {
            count: ($metadata.migration_history? | default [] | length)
            last_migration: (
                $metadata.migration_history?
                | default []
                | last
                | default null
            )
        }
    }
}

# Validate workspace has required structure
export def validate-workspace-structure [
    workspace_path: string
] {
    mut issues = []

    # Check for required directories
    let required_dirs = [
        "config"
        "infra"
        ".provisioning"
    ]

    for dir in $required_dirs {
        let dir_path = ($workspace_path | path join $dir)
        if not ($dir_path | path exists) {
            $issues = ($issues | append {
                type: "missing_directory"
                path: $dir
                severity: "error"
                message: $"Required directory missing: ($dir)"
            })
        }
    }

    # Check for required files (Nickel or YAML configuration)
    let config_schema_path = ($workspace_path | path join "config" | path join "provisioning.ncl")
    let config_yaml_path = ($workspace_path | path join "config" | path join "provisioning.yaml")

    if (not ($config_schema_path | path exists) and not ($config_yaml_path | path exists)) {
        $issues = ($issues | append {
            type: "missing_file"
            path: "config/provisioning.ncl or config/provisioning.yaml"
            severity: "error"
            message: "Main configuration file missing (provisioning.ncl or provisioning.yaml required)"
        })
    }

    let metadata_path = (get-workspace-metadata-path $workspace_path)
    if not ($metadata_path | path exists) {
        $issues = ($issues | append {
            type: "missing_metadata"
            path: ".provisioning/metadata.yaml"
            severity: "warning"
            message: "Workspace metadata missing - run migration"
        })
    }

    return {
        valid: (($issues | where severity == "error" | length) == 0)
        issues: $issues
        warnings: ($issues | where severity == "warning" | length)
        errors: ($issues | where severity == "error" | length)
    }
}
