#!/bin/bash
#
# NODE1 API Key Management
# Version: 1.0
# Last Updated: 2026-01-26
#
# Usage:
#   ./api-keys.sh create <name> [--admin]
#   ./api-keys.sh revoke <key_id>
#   ./api-keys.sh list
#   ./api-keys.sh rotate-health
#   ./api-keys.sh verify <key>
#

set -e

# Paths
KEYS_DIR="/opt/microdao-daarion/secrets"
KEYS_FILE="$KEYS_DIR/api-keys.conf"
HEALTH_TOKEN_FILE="$KEYS_DIR/health-token.conf"
NGINX_KEYS_MAP="$KEYS_DIR/nginx-api-keys.conf"
LOG_FILE="/var/log/microdao/api-keys.log"

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

# Initialize directories
init_dirs() {
    mkdir -p "$KEYS_DIR"
    mkdir -p "$(dirname $LOG_FILE)"
    chmod 700 "$KEYS_DIR"
    touch "$KEYS_FILE" "$HEALTH_TOKEN_FILE" "$NGINX_KEYS_MAP"
    chmod 600 "$KEYS_FILE" "$HEALTH_TOKEN_FILE" "$NGINX_KEYS_MAP"
}

# Log action (without exposing secrets)
log_action() {
    local action="$1"
    local key_id="$2"
    local details="$3"
    echo "$(date '+%Y-%m-%d %H:%M:%S') | $action | key_id=$key_id | $details" >> "$LOG_FILE"
}

# Generate random key
generate_key() {
    openssl rand -hex 32
}

# Generate key ID
generate_key_id() {
    local name="$1"
    local timestamp=$(date +%Y%m%d%H%M%S)
    local random=$(openssl rand -hex 4)
    echo "kid_${name}_${timestamp}_${random}"
}

# Create new API key
create_key() {
    local name="$1"
    local is_admin="${2:-false}"
    
    if [ -z "$name" ]; then
        echo -e "${RED}Error: Key name required${NC}"
        echo "Usage: $0 create <name> [--admin]"
        exit 1
    fi
    
    local key_id=$(generate_key_id "$name")
    local secret=$(generate_key)
    local api_key="sk-${secret}"
    local created_at=$(date -Iseconds)
    local scope="standard"
    [ "$is_admin" = "--admin" ] && scope="admin"
    
    # Save to keys file (key_id|name|scope|created_at|hash)
    local key_hash=$(echo -n "$api_key" | sha256sum | cut -d' ' -f1)
    echo "${key_id}|${name}|${scope}|${created_at}|${key_hash}" >> "$KEYS_FILE"
    
    # Update nginx map
    rebuild_nginx_map
    
    log_action "CREATE" "$key_id" "name=$name scope=$scope"
    
    echo -e "${GREEN}API Key Created${NC}"
    echo "================================"
    echo "Key ID:    $key_id"
    echo "Name:      $name"
    echo "Scope:     $scope"
    echo "API Key:   $api_key"
    echo "================================"
    echo -e "${YELLOW}WARNING: Save this key now. It cannot be retrieved later.${NC}"
}

# Revoke API key
revoke_key() {
    local key_id="$1"
    
    if [ -z "$key_id" ]; then
        echo -e "${RED}Error: Key ID required${NC}"
        echo "Usage: $0 revoke <key_id>"
        exit 1
    fi
    
    if ! grep -q "^${key_id}|" "$KEYS_FILE" 2>/dev/null; then
        echo -e "${RED}Error: Key ID not found${NC}"
        exit 1
    fi
    
    # Remove from keys file
    sed -i "/^${key_id}|/d" "$KEYS_FILE"
    
    # Rebuild nginx map
    rebuild_nginx_map
    
    log_action "REVOKE" "$key_id" "revoked"
    
    echo -e "${GREEN}Key revoked: $key_id${NC}"
    echo "Run 'nginx -s reload' to apply changes"
}

# List all keys (without secrets)
list_keys() {
    echo "API Keys"
    echo "========"
    echo ""
    printf "%-40s %-15s %-10s %s\n" "KEY_ID" "NAME" "SCOPE" "CREATED"
    printf "%-40s %-15s %-10s %s\n" "------" "----" "-----" "-------"
    
    if [ -f "$KEYS_FILE" ] && [ -s "$KEYS_FILE" ]; then
        while IFS='|' read -r key_id name scope created_at hash; do
            printf "%-40s %-15s %-10s %s\n" "$key_id" "$name" "$scope" "${created_at:0:19}"
        done < "$KEYS_FILE"
    else
        echo "(no keys)"
    fi
    
    echo ""
    echo "Total: $(wc -l < "$KEYS_FILE" 2>/dev/null || echo 0) keys"
}

# Verify a key (returns key_id if valid)
verify_key() {
    local api_key="$1"
    
    if [ -z "$api_key" ]; then
        echo -e "${RED}Error: API key required${NC}"
        exit 1
    fi
    
    local key_hash=$(echo -n "$api_key" | sha256sum | cut -d' ' -f1)
    
    while IFS='|' read -r key_id name scope created_at stored_hash; do
        if [ "$key_hash" = "$stored_hash" ]; then
            echo -e "${GREEN}Valid${NC}"
            echo "Key ID: $key_id"
            echo "Name:   $name"
            echo "Scope:  $scope"
            log_action "VERIFY" "$key_id" "valid"
            exit 0
        fi
    done < "$KEYS_FILE"
    
    echo -e "${RED}Invalid key${NC}"
    log_action "VERIFY" "unknown" "invalid"
    exit 1
}

# Rotate health token
rotate_health_token() {
    local new_token=$(generate_key)
    local old_token=""
    
    # Read old token if exists
    if [ -f "$HEALTH_TOKEN_FILE" ] && [ -s "$HEALTH_TOKEN_FILE" ]; then
        old_token=$(grep "^current=" "$HEALTH_TOKEN_FILE" | cut -d'=' -f2)
    fi
    
    # Write new config (current + previous for grace period)
    cat > "$HEALTH_TOKEN_FILE" << EOF
# Health Token Configuration
# Generated: $(date -Iseconds)
# Previous token valid for 24h after rotation
current=$new_token
previous=$old_token
rotated_at=$(date -Iseconds)
EOF
    
    chmod 600 "$HEALTH_TOKEN_FILE"
    
    # Update nginx include
    cat > "$KEYS_DIR/nginx-health-token.conf" << EOF
# Auto-generated health token map
# Do not edit manually
map \$http_x_health_token \$health_token_valid {
    default 0;
    "$new_token" 1;
EOF
    
    # Add previous token if exists (grace period)
    if [ -n "$old_token" ]; then
        echo "    \"$old_token\" 1;  # previous (grace period)" >> "$KEYS_DIR/nginx-health-token.conf"
    fi
    
    echo "}" >> "$KEYS_DIR/nginx-health-token.conf"
    chmod 600 "$KEYS_DIR/nginx-health-token.conf"
    
    log_action "ROTATE_HEALTH" "-" "token rotated"
    
    echo -e "${GREEN}Health Token Rotated${NC}"
    echo "================================"
    echo "New Token: $new_token"
    echo "================================"
    echo -e "${YELLOW}Update your monitoring systems with the new token.${NC}"
    echo "Previous token remains valid for grace period."
    echo "Run 'nginx -s reload' to apply changes"
}

# Rebuild nginx API keys map
rebuild_nginx_map() {
    cat > "$NGINX_KEYS_MAP" << 'HEADER'
# Auto-generated API keys map
# Do not edit manually - use api-keys.sh
# Format: key hash -> "key_id:scope"

map $api_key_hash $api_key_info {
    default "";
HEADER
    
    while IFS='|' read -r key_id name scope created_at hash; do
        echo "    \"$hash\" \"$key_id:$scope\";" >> "$NGINX_KEYS_MAP"
    done < "$KEYS_FILE"
    
    echo "}" >> "$NGINX_KEYS_MAP"
    chmod 600 "$NGINX_KEYS_MAP"
}

# Show usage
usage() {
    echo "NODE1 API Key Management"
    echo ""
    echo "Usage:"
    echo "  $0 create <name> [--admin]    Create new API key"
    echo "  $0 revoke <key_id>            Revoke API key"
    echo "  $0 list                       List all keys"
    echo "  $0 verify <api_key>           Verify API key"
    echo "  $0 rotate-health              Rotate health check token"
    echo ""
    echo "Examples:"
    echo "  $0 create monitoring"
    echo "  $0 create admin-user --admin"
    echo "  $0 revoke kid_monitoring_20260126_abc123"
}

# Main
init_dirs

case "${1:-}" in
    create)
        create_key "$2" "$3"
        ;;
    revoke)
        revoke_key "$2"
        ;;
    list)
        list_keys
        ;;
    verify)
        verify_key "$2"
        ;;
    rotate-health)
        rotate_health_token
        ;;
    *)
        usage
        ;;
esac
