#!/usr/bin/env bash
# minisign signing script for token lists
# Signs token list files for integrity verification

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TOKEN_LISTS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
LISTS_DIR="$TOKEN_LISTS_DIR/lists"
TOKEN_LIST_FILE="$LISTS_DIR/dbis-138.tokenlist.json"
PUBLIC_KEY_FILE="$TOKEN_LISTS_DIR/minisign.pub"
SIGNATURE_FILE="${TOKEN_LIST_FILE}.sig"

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

log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }

# Check if minisign is available
if ! command -v minisign &> /dev/null; then
    log_error "minisign is required but not installed"
    log_info "Installation:"
    log_info "  macOS: brew install minisign"
    log_info "  Ubuntu/Debian: apt-get install minisign"
    log_info "  From source: https://github.com/jedisct1/minisign"
    exit 1
fi

# Generate keypair (only if keys don't exist)
generate_keypair() {
    local private_key_file="${MINISIGN_PRIVATE_KEY_FILE:-$TOKEN_LISTS_DIR/minisign.key}"
    
    if [[ -f "$private_key_file" ]]; then
        log_warn "Private key already exists: $private_key_file"
        log_info "Skipping key generation"
        return 0
    fi
    
    log_info "Generating minisign keypair..."
    log_info "Private key will be saved to: $private_key_file"
    log_info "Public key will be saved to: $PUBLIC_KEY_FILE"
    log_warn "Keep the private key secure and never commit it to the repository!"
    
    # Generate keypair (minisign will prompt for password)
    if minisign -G -s "$private_key_file" -p "$PUBLIC_KEY_FILE"; then
        log_success "Keypair generated successfully"
        log_info ""
        log_info "Next steps:"
        log_info "1. Store the private key securely (e.g., password manager, secure vault)"
        log_info "2. Add private key to GitHub Secrets as MINISIGN_PRIVATE_KEY"
        log_info "3. Commit the public key: git add $PUBLIC_KEY_FILE"
        log_info "4. Set MINISIGN_PRIVATE_KEY_FILE environment variable if using custom path"
    else
        log_error "Failed to generate keypair"
        exit 1
    fi
}

# Sign token list
sign_list() {
    local private_key_file="${MINISIGN_PRIVATE_KEY_FILE:-$TOKEN_LISTS_DIR/minisign.key}"
    local private_key_content="${MINISIGN_PRIVATE_KEY:-}"
    
    if [[ ! -f "$TOKEN_LIST_FILE" ]]; then
        log_error "Token list file not found: $TOKEN_LIST_FILE"
        exit 1
    fi
    
    log_info "Signing token list: $TOKEN_LIST_FILE"
    
    # Check if private key exists or is provided via environment
    if [[ -n "$private_key_content" ]]; then
        # Use private key from environment variable
        log_info "Using private key from MINISIGN_PRIVATE_KEY environment variable"
        echo "$private_key_content" | minisign -S -s /dev/stdin -m "$TOKEN_LIST_FILE" -x "$SIGNATURE_FILE" || {
            log_error "Failed to sign token list"
            exit 1
        }
    elif [[ -f "$private_key_file" ]]; then
        # Use private key file
        minisign -S -s "$private_key_file" -m "$TOKEN_LIST_FILE" -x "$SIGNATURE_FILE" || {
            log_error "Failed to sign token list"
            exit 1
        }
    else
        log_error "Private key not found"
        log_info "Provide private key via:"
        log_info "  1. File: Set MINISIGN_PRIVATE_KEY_FILE environment variable"
        log_info "  2. Environment: Set MINISIGN_PRIVATE_KEY environment variable"
        log_info "  3. Generate new: Run '$0 --generate-key'"
        exit 1
    fi
    
    log_success "Token list signed successfully"
    log_info "Signature file: $SIGNATURE_FILE"
    
    # Display signature info
    if [[ -f "$SIGNATURE_FILE" ]]; then
        log_info ""
        log_info "Signature preview:"
        head -n 2 "$SIGNATURE_FILE" | head -c 100
        echo "..."
        log_info ""
    fi
}

# Verify signature
verify_signature() {
    if [[ ! -f "$TOKEN_LIST_FILE" ]]; then
        log_error "Token list file not found: $TOKEN_LIST_FILE"
        exit 1
    fi
    
    if [[ ! -f "$SIGNATURE_FILE" ]]; then
        log_error "Signature file not found: $SIGNATURE_FILE"
        exit 1
    fi
    
    if [[ ! -f "$PUBLIC_KEY_FILE" ]]; then
        log_error "Public key file not found: $PUBLIC_KEY_FILE"
        log_info "Public key should be at: $PUBLIC_KEY_FILE"
        exit 1
    fi
    
    log_info "Verifying signature..."
    
    if minisign -V -p "$PUBLIC_KEY_FILE" -m "$TOKEN_LIST_FILE" -x "$SIGNATURE_FILE"; then
        log_success "Signature verification passed!"
        return 0
    else
        log_error "Signature verification failed!"
        return 1
    fi
}

# Main
main() {
    local command="${1:-sign}"
    
    case "$command" in
        --generate-key|-g)
            generate_keypair
            ;;
        --sign|-s)
            sign_list
            ;;
        --verify|-v)
            verify_signature
            ;;
        sign)
            sign_list
            ;;
        verify)
            verify_signature
            ;;
        *)
            echo "Usage: $0 [command]"
            echo ""
            echo "Commands:"
            echo "  sign, -s          Sign the token list (default)"
            echo "  verify, -v        Verify the signature"
            echo "  --generate-key, -g  Generate a new keypair"
            echo ""
            echo "Environment variables:"
            echo "  MINISIGN_PRIVATE_KEY_FILE    Path to private key file"
            echo "  MINISIGN_PRIVATE_KEY         Private key content (for CI/CD)"
            exit 1
            ;;
    esac
}

main "${1:-sign}"

