# Authentication Command Handlers
# Handles: auth login, auth logout, auth status, auth mfa, etc.

use ../flags.nu *
use ../../lib_provisioning/plugins/auth.nu *

# Main authentication command dispatcher
export def handle_authentication_command [
    command: string
    ops: string
    flags: record
] {
    match $command {
        "auth" | "login" | "whoami" | "mfa" => {
            let subcommand = if ($ops | is-not-empty) {
                ($ops | split row " " | get 0)
            } else if $command == "login" {
                "login"
            } else if $command == "whoami" {
                "status"
            } else if $command == "mfa" {
                "mfa"
            } else {
                "status"
            }

            let remaining_ops = if ($ops | is-not-empty) {
                ($ops | split row " " | skip 1 | str join " ")
            } else {
                ""
            }

            match $subcommand {
                "login" => { handle_auth_login $remaining_ops $flags }
                "logout" => { handle_auth_logout $flags }
                "status" | "whoami" => { handle_auth_status $flags }
                "sessions" | "list" => { handle_auth_sessions $flags }
                "refresh" => { handle_auth_refresh $flags }
                "mfa" | "mfa-enroll" | "mfa-verify" => {
                    handle_auth_mfa $subcommand $remaining_ops $flags
                }
                "help" => { show_auth_help }
                _ => {
                    print $"❌ Unknown auth subcommand: ($subcommand)"
                    print ""
                    print "Available auth subcommands:"
                    print "  login        - Login with credentials"
                    print "  logout       - Logout (revoke session)"
                    print "  status       - Show current authentication status"
                    print "  whoami       - Alias for status"
                    print "  sessions     - List active sessions"
                    print "  list         - Alias for sessions"
                    print "  refresh      - Refresh authentication token"
                    print "  mfa          - MFA operations"
                    print "  mfa-enroll   - Enroll in MFA"
                    print "  mfa-verify   - Verify MFA code"
                    print "  help         - Show this help message"
                    print ""
                    print "Use 'provisioning auth help' for more details"
                    exit 1
                }
            }
        }
        _ => {
            print $"❌ Unknown authentication command: ($command)"
            print ""
            print "Available authentication commands:"
            print "  login               - Login with username and password"
            print "  logout              - Logout (revoke session)"
            print "  status | whoami     - Show current user and session status"
            print "  sessions | list     - List active sessions"
            print "  refresh             - Refresh authentication token"
            print "  mfa                 - Multi-factor authentication"
            print "  mfa-enroll          - Enroll in MFA (TOTP or WebAuthn)"
            print "  mfa-verify          - Verify MFA code"
            print "  help                - Show auth help"
            print ""
            print "Examples:"
            print "  provisioning auth login"
            print "  provisioning auth status"
            print "  provisioning mfa totp enroll"
            print "  provisioning mfa verify --code 123456"
            print ""
            print "Use 'provisioning help authentication' for more details"
            exit 1
        }
    }
}

# Login with username and password
def handle_auth_login [ops: string, flags: record] {
    let username = if ($ops | is-not-empty) {
        ($ops | split row " " | get 0)
    } else {
        input $"(_ansi cyan)Username:(_ansi reset) "
    }

    if ($username | is-empty) {
        print $"(_ansi red)❌ Username is required(_ansi reset)"
        exit 1
    }

    # Prompt for password securely
    print $"(_ansi cyan)Password for ($username):(_ansi reset) "
    let password = (input --suppress-output)

    if ($password | is-empty) {
        print $"(_ansi red)❌ Password is required(_ansi reset)"
        exit 1
    }

    print $"\n(_ansi cyan)Authenticating...(_ansi reset)"

    let result = (do -i {
        plugin-login $username $password
    })

    if $result != null {
        print $"\n(_ansi green_bold)✓ Login successful!(_ansi reset)\n"
        print $"(_ansi cyan)User:(_ansi reset)       ($result.user? | default $username)"
        print $"(_ansi cyan)Role:(_ansi reset)       ($result.role? | default 'N/A')"
        print $"(_ansi cyan)Expires:(_ansi reset)    ($result.expires_at? | default 'N/A')"
        print $"(_ansi cyan)MFA:(_ansi reset)        ($result.mfa_enabled? | default false)"

        if ($result.mfa_required? | default false) {
            print $"\n(_ansi yellow)⚠️  MFA verification required(_ansi reset)"
            print $"(_ansi cyan)Use: provisioning auth mfa verify --code <6-digit-code>(_ansi reset)"
        } else {
            print $"\n(_ansi green)Session active and ready(_ansi reset)"
        }
    } else {
        print $"\n(_ansi red_bold)❌ Login failed(_ansi reset)"
        print $"(_ansi red)Authentication error occurred(_ansi reset)"
        exit 1
    }
}

# Logout and clear tokens
def handle_auth_logout [flags: record] {
    print $"(_ansi cyan)Logging out...(_ansi reset)"

    let result = (do -i {
        plugin-logout
    })

    if $result != null {
        print $"\n(_ansi green_bold)✓ Logged out successfully(_ansi reset)"
        print $"(_ansi default_dimmed)All tokens have been cleared(_ansi reset)"
    } else {
        print $"\n(_ansi yellow)⚠️  Logout completed with warnings(_ansi reset)"
        print $"(_ansi default_dimmed)Token cleanup may have failed(_ansi reset)"
    }
}

# Show authentication status
def handle_auth_status [flags: record] {
    print $"(_ansi cyan_bold)Authentication Status(_ansi reset)\n"

    let status = (do -i {
        plugin-auth-status
    })

    if $status != null {
        if ($status.authenticated? | default false) {
            print $"(_ansi green)Status:(_ansi reset)      Authenticated ✓"
            print $"(_ansi cyan)User:(_ansi reset)        ($status.user? | default 'N/A')"
            print $"(_ansi cyan)Role:(_ansi reset)        ($status.role? | default 'N/A')"
            print $"(_ansi cyan)Expires at:(_ansi reset)  ($status.expires_at? | default 'N/A')"
            print $"(_ansi cyan)MFA enabled:(_ansi reset) ($status.mfa_enabled? | default false)"

            if ($status.permissions? | is-not-empty) {
                print $"\n(_ansi cyan_bold)Permissions:(_ansi reset)"
                for perm in $status.permissions {
                    print $"  • ($perm)"
                }
            }

            if ($status.warning? | is-not-empty) {
                print $"\n(_ansi yellow)⚠️  ($status.warning)(_ansi reset)"
            }
        } else {
            print $"(_ansi red)Status:(_ansi reset) Not authenticated ✗"
            print $"(_ansi cyan)Message:(_ansi reset) ($status.message? | default 'No active session')"
            print $"\n(_ansi default_dimmed)Use 'provisioning auth login' to authenticate(_ansi reset)"
        }

        # Show plugin mode
        print $"\n(_ansi default_dimmed)Mode: ($status.mode? | default 'unknown')(_ansi reset)"
    } else {
        print $"(_ansi red)❌ Failed to get auth status(_ansi reset)"
        print $"(_ansi red)Status check error occurred(_ansi reset)"
        exit 1
    }
}

# List active sessions
def handle_auth_sessions [flags: record] {
    print $"(_ansi cyan_bold)Active Sessions(_ansi reset)\n"

    let sessions = (do -i {
        plugin-sessions
    })

    if $sessions != null {
        if ($sessions | length) == 0 {
            print $"(_ansi yellow)No active sessions found(_ansi reset)"
            return
        }

        $sessions | table -e
    } else {
        print $"(_ansi red)❌ Failed to list sessions(_ansi reset)"
        print $"(_ansi red)Session listing error occurred(_ansi reset)"
        exit 1
    }
}

# Refresh access token
def handle_auth_refresh [flags: record] {
    print $"(_ansi cyan)Refreshing access token...(_ansi reset)"

    let result = (do -i {
        plugin-verify
    })

    if $result != null {
        if ($result.valid? | default false) {
            print $"(_ansi green)✓ Token is still valid(_ansi reset)"
            print $"(_ansi cyan)Expires:(_ansi reset) ($result.expires_at? | default 'N/A')"
        } else {
            print $"(_ansi yellow)Token expired or invalid, please login again(_ansi reset)"
        }
    } else {
        print $"(_ansi red)❌ Token verification failed(_ansi reset)"
        print $"(_ansi red)Verification error occurred(_ansi reset)"
        exit 1
    }
}

# Handle MFA commands
def handle_auth_mfa [subcommand: string, ops: string, flags: record] {
    let mfa_action = if $subcommand == "mfa" {
        if ($ops | is-not-empty) {
            ($ops | split row " " | get 0)
        } else {
            "help"
        }
    } else if $subcommand == "mfa-enroll" {
        "enroll"
    } else if $subcommand == "mfa-verify" {
        "verify"
    } else {
        "help"
    }

    let remaining_ops = if $subcommand == "mfa" and ($ops | is-not-empty) {
        ($ops | split row " " | skip 1 | str join " ")
    } else {
        $ops
    }

    match $mfa_action {
        "enroll" | "enable" | "setup" => { handle_mfa_enroll $remaining_ops $flags }
        "verify" | "check" => { handle_mfa_verify $remaining_ops $flags }
        "help" => { show_mfa_help }
        _ => {
            print $"❌ Unknown MFA action: ($mfa_action)"
            print "Use 'provisioning auth mfa help' for available commands"
            exit 1
        }
    }
}

# Enroll in MFA
def handle_mfa_enroll [ops: string, flags: record] {
    let mfa_type = if ($ops | is-not-empty) {
        ($ops | split row " " | get 0)
    } else {
        "totp"
    }

    if $mfa_type not-in ["totp" "webauthn"] {
        print $"(_ansi red)❌ Invalid MFA type: ($mfa_type)(_ansi reset)"
        print $"(_ansi cyan)Valid types: totp, webauthn(_ansi reset)"
        exit 1
    }

    print $"(_ansi cyan_bold)Enrolling in MFA ($mfa_type)...(_ansi reset)\n"

    let result = (do -i {
        plugin-mfa-enroll --type $mfa_type
    })

    if $result != null {
        if $mfa_type == "totp" {
            print $"(_ansi green_bold)✓ TOTP enrollment initiated(_ansi reset)\n"
            print $"(_ansi cyan_bold)Secret:(_ansi reset) ($result.secret? | default 'N/A')\n"

            if ($result.qr_code? | is-not-empty) {
                print $"(_ansi cyan_bold)QR Code:(_ansi reset)"
                print $result.qr_code
                print ""
            }

            print $"(_ansi yellow_bold)📱 Setup Instructions:(_ansi reset)"
            print $"  1. Open your authenticator app (Google Authenticator, Authy, etc.)"
            print $"  2. Scan the QR code above or manually enter the secret"
            print $"  3. Verify with the 6-digit code:\n"
            print $"     (_ansi cyan)provisioning auth mfa verify --code <6-digit-code>(_ansi reset)\n"
        } else {
            print $"(_ansi green_bold)✓ WebAuthn enrollment initiated(_ansi reset)\n"
            print $"(_ansi yellow_bold)🔑 Setup Instructions:(_ansi reset)"
            print $"  1. Follow browser prompts to register your security key"
            print $"  2. Touch your YubiKey, use Touch ID, or Windows Hello"
            print $"  3. Complete registration in the web interface\n"
        }
    } else {
        print $"\n(_ansi red_bold)❌ MFA enrollment failed(_ansi reset)"
        print $"(_ansi red)Enrollment error occurred(_ansi reset)"
        exit 1
    }
}

# Verify MFA code
def handle_mfa_verify [ops: string, flags: record] {
    let code = if ($flags.code? | is-not-empty) {
        $flags.code
    } else if ($ops | is-not-empty) {
        ($ops | split row " " | get 0)
    } else {
        input $"(_ansi cyan)Enter 6-digit MFA code:(_ansi reset) "
    }

    if ($code | is-empty) {
        print $"(_ansi red)❌ MFA code is required(_ansi reset)"
        exit 1
    }

    print $"(_ansi cyan)Verifying MFA code...(_ansi reset)"

    let result = (do -i {
        plugin-mfa-verify $code
    })

    if $result != null {
        print $"\n(_ansi green_bold)✓ MFA verified successfully!(_ansi reset)\n"
        print $"(_ansi cyan)Status:(_ansi reset) ($result.status? | default 'Active')"

        if ($result.backup_codes? | is-not-empty) {
            print $"\n(_ansi yellow_bold)⚠️  Backup Codes \(save these securely\):(_ansi reset)"
            for code in $result.backup_codes {
                print $"  • ($code)"
            }
            print $"\n(_ansi default_dimmed)Use these codes if you lose access to your MFA device(_ansi reset)"
        }
    } else {
        print $"\n(_ansi red_bold)❌ MFA verification failed(_ansi reset)"
        print $"(_ansi red)Verification error occurred(_ansi reset)"
        print $"\n(_ansi yellow)💡 Tip: Make sure the code is current (30-second window)(_ansi reset)"
        exit 1
    }
}

# Show authentication help
def show_auth_help [] {
    print $"
(_ansi cyan_bold)╔══════════════════════════════════════════════════╗(_ansi reset)
(_ansi cyan_bold)║(_ansi reset)  🔐 AUTHENTICATION COMMANDS                      (_ansi cyan_bold)║(_ansi reset)
(_ansi cyan_bold)╚══════════════════════════════════════════════════╝(_ansi reset)

(_ansi green_bold)[Session Management](_ansi reset)
  (_ansi blue)auth login <username>(_ansi reset)     Login and store JWT tokens
  (_ansi blue)auth logout(_ansi reset)               Logout and clear tokens
  (_ansi blue)auth status(_ansi reset)               Show current authentication status
  (_ansi blue)auth sessions(_ansi reset)             List active sessions
  (_ansi blue)auth refresh(_ansi reset)              Verify/refresh token

(_ansi green_bold)[Multi-Factor Authentication](_ansi reset)
  (_ansi blue)auth mfa enroll <type>(_ansi reset)    Enroll in MFA (totp or webauthn)
  (_ansi blue)auth mfa verify --code <code>(_ansi reset) Verify MFA code

(_ansi green_bold)EXAMPLES(_ansi reset)

  # Login interactively
  provisioning auth login

  # Login with username
  provisioning auth login admin

  # Check authentication status
  provisioning auth status
  provisioning whoami         (_ansi default_dimmed)# shortcut(_ansi reset)

  # Enroll in TOTP MFA
  provisioning auth mfa enroll totp

  # Verify MFA code
  provisioning auth mfa verify --code 123456

  # List active sessions
  provisioning auth sessions

  # Logout
  provisioning auth logout

(_ansi green_bold)SHORTCUTS(_ansi reset)

  login      → auth login
  logout     → auth logout
  whoami     → auth status
  mfa        → auth mfa
  mfa-enroll → auth mfa enroll
  mfa-verify → auth mfa verify

(_ansi default_dimmed)💡 Authentication uses JWT tokens with RS256 signing
   Tokens are stored securely and expire after 15 minutes
   MFA is required for sensitive operations in production(_ansi reset)
"
}

# Show MFA help
def show_mfa_help [] {
    print $"
(_ansi cyan_bold)╔══════════════════════════════════════════════════╗(_ansi reset)
(_ansi cyan_bold)║(_ansi reset)  🔐 MULTI-FACTOR AUTHENTICATION                  (_ansi cyan_bold)║(_ansi reset)
(_ansi cyan_bold)╚══════════════════════════════════════════════════╝(_ansi reset)

(_ansi green_bold)[MFA Types](_ansi reset)

  (_ansi blue)TOTP (Time-based One-Time Password)(_ansi reset)
    • 6-digit codes that change every 30 seconds
    • Works with Google Authenticator, Authy, etc.
    • No internet required after setup

  (_ansi blue)WebAuthn/FIDO2(_ansi reset)
    • Hardware security keys (YubiKey)
    • Biometric authentication (Touch ID, Windows Hello)
    • Phishing-resistant

(_ansi green_bold)[Commands](_ansi reset)

  (_ansi blue)auth mfa enroll totp(_ansi reset)       Enroll in TOTP MFA
  (_ansi blue)auth mfa enroll webauthn(_ansi reset)   Enroll in WebAuthn MFA
  (_ansi blue)auth mfa verify --code <code>(_ansi reset) Verify MFA code

(_ansi green_bold)EXAMPLES(_ansi reset)

  # Enroll in TOTP
  provisioning auth mfa enroll totp

  # Scan QR code with authenticator app
  # Then verify with 6-digit code
  provisioning auth mfa verify --code 123456

  # Enroll in WebAuthn
  provisioning auth mfa enroll webauthn

(_ansi default_dimmed)💡 MFA enrollment requires active authentication session
   Use 'provisioning auth login' first if not authenticated(_ansi reset)
"
}
