"""
Secure Oracle - Trusted Authority for Loggerheads

SECURITY MODEL:
- Oracle private key MUST be kept secure and NEVER committed to git
- Each deployment should use its own oracle keypair
- Oracle keypair loaded from environment variable or secure file
- Fallback to embedded key only for testing/demo purposes

Production Setup:
1. Generate oracle keypair: python -m loggerheads.oracle_secure --generate
2. Set environment: export ORACLE_KEYPAIR_PATH=/secure/path/oracle-keypair.json
3. Or store in config: ~/.loggerheads/oracle-keypair.json
"""

import os
import json
from pathlib import Path
from solders.keypair import Keypair
from typing import Optional

# NO HARDCODED KEYPAIRS - Oracle must be generated by admin


def get_oracle_keypair_path() -> Optional[Path]:
    """
    Find oracle keypair in order of precedence:
    1. ORACLE_KEYPAIR_JSON environment variable (JSON string for production)
    2. ORACLE_KEYPAIR_PATH environment variable (file path)
    3. ~/.loggerheads/oracle-keypair.json
    4. None (will prompt for setup)
    """
    # Check if keypair is provided as JSON in env var (for production deployment)
    if os.getenv('ORACLE_KEYPAIR_JSON'):
        return 'ENV_JSON'  # Special marker

    # Check environment variable for file path
    env_path = os.getenv('ORACLE_KEYPAIR_PATH')
    if env_path:
        path = Path(env_path).expanduser()
        if path.exists():
            return path
        else:
            print(f"⚠️  Warning: ORACLE_KEYPAIR_PATH set but file not found: {path}")

    # Check default config location
    default_path = Path.home() / '.loggerheads' / 'oracle-keypair.json'
    if default_path.exists():
        return default_path

    return None


def load_oracle_keypair_from_file(path) -> Keypair:
    """
    Load oracle keypair from file or environment variable.

    Args:
        path: Path to keypair file, or 'ENV_JSON' to read from ORACLE_KEYPAIR_JSON env var
    """
    try:
        if path == 'ENV_JSON':
            # Load from environment variable (for production deployment)
            keypair_json = os.getenv('ORACLE_KEYPAIR_JSON')
            if not keypair_json:
                raise RuntimeError("ORACLE_KEYPAIR_JSON environment variable not set")
            data = json.loads(keypair_json)
            return Keypair.from_bytes(bytes(data))
        else:
            # Load from file (for local development)
            with open(path, 'r') as f:
                data = json.load(f)
                return Keypair.from_bytes(bytes(data))
    except Exception as e:
        raise RuntimeError(f"Failed to load oracle keypair: {e}")


def get_oracle_keypair(allow_demo: bool = False) -> Keypair:
    """
    Returns the oracle keypair with security checks.

    Args:
        allow_demo: Deprecated - no longer used (always requires real keypair)

    Returns:
        Oracle keypair

    Raises:
        RuntimeError: If no oracle keypair found
    """
    keypair_path = get_oracle_keypair_path()

    if keypair_path:
        return load_oracle_keypair_from_file(keypair_path)

    # No keypair found - offer to generate
    print("\n" + "="*70)
    print("🔑 ORACLE KEYPAIR NOT FOUND")
    print("="*70)
    print("\nThe oracle is an independent service that verifies work.")
    print("For testing, you need an oracle keypair.")
    print("\nOptions:")
    print("  1. Generate new oracle keypair (for system operator)")
    print("  2. Use oracle keypair from system operator (for testers)")
    print("  3. Exit and set up manually")
    print()

    choice = input("Choose option (1/2/3): ").strip()

    if choice == "1":
        # Generate new oracle
        print("\n🔧 Generating oracle keypair...")
        keypair = generate_oracle_keypair()
        return keypair
    elif choice == "2":
        # Prompt for oracle keypair path
        print("\nYour system operator should have sent you oracle-keypair.json")
        print("Where is the file located?")
        path_input = input("Path to oracle-keypair.json: ").strip()

        if not path_input:
            raise RuntimeError("Oracle keypair path required!")

        path = Path(path_input).expanduser()
        if not path.exists():
            raise RuntimeError(f"File not found: {path}")

        # Copy to default location
        default_path = Path.home() / '.loggerheads' / 'oracle-keypair.json'
        default_path.parent.mkdir(parents=True, exist_ok=True)

        import shutil
        shutil.copy(path, default_path)
        print(f"\n✅ Oracle keypair copied to: {default_path}")

        return load_oracle_keypair_from_file(default_path)
    else:
        raise RuntimeError(
            "\n❌ Oracle keypair required\n\n"
            "To generate oracle keypair:\n"
            "  python3 -m loggerheads.oracle_secure --generate\n\n"
            "Or set environment variable:\n"
            "  export ORACLE_KEYPAIR_PATH=/path/to/oracle-keypair.json"
        )


def get_oracle_pubkey(allow_demo: bool = False) -> str:
    """
    Returns the oracle public key as a string.
    
    Args:
        allow_demo: If True, allows using demo oracle for testing.
    """
    return str(get_oracle_keypair(allow_demo=allow_demo).pubkey())


def generate_oracle_keypair(output_path: Optional[Path] = None) -> Keypair:
    """
    Generate a new oracle keypair and save to file.
    
    Args:
        output_path: Where to save keypair. Defaults to ~/.loggerheads/oracle-keypair.json
        
    Returns:
        Generated keypair
    """
    if output_path is None:
        output_path = Path.home() / '.loggerheads' / 'oracle-keypair.json'
    
    # Generate new keypair
    keypair = Keypair()
    
    # Ensure directory exists
    output_path.parent.mkdir(parents=True, exist_ok=True)
    
    # Save to file (secure permissions)
    keypair_bytes = bytes(keypair)
    with open(output_path, 'w') as f:
        json.dump(list(keypair_bytes), f)
    
    # Set secure file permissions (owner read/write only)
    os.chmod(output_path, 0o600)
    
    print(f"✅ Oracle keypair generated: {output_path}")
    print(f"🔑 Public key: {keypair.pubkey()}")
    print(f"\n⚠️  IMPORTANT: Keep this file secure and NEVER commit to git!")
    print(f"\nTo use this oracle:")
    print(f"  export ORACLE_KEYPAIR_PATH={output_path}")
    print(f"\nOr add to ~/.bashrc or ~/.zshrc for persistence")
    
    return keypair


if __name__ == "__main__":
    import sys
    
    if len(sys.argv) > 1 and sys.argv[1] == '--generate':
        # Generate new oracle keypair
        if len(sys.argv) > 2:
            output_path = Path(sys.argv[2])
        else:
            output_path = None
        generate_oracle_keypair(output_path)
    elif len(sys.argv) > 1 and sys.argv[1] == '--pubkey':
        # Show current oracle pubkey
        try:
            pubkey = get_oracle_pubkey(allow_demo=True)
            print(f"Current Oracle Public Key: {pubkey}")
        except Exception as e:
            print(f"Error: {e}")
            sys.exit(1)
    else:
        print("Loggerheads Oracle Key Management")
        print("\nUsage:")
        print("  python -m loggerheads.oracle_secure --generate [output_path]")
        print("  python -m loggerheads.oracle_secure --pubkey")
        print("\nExamples:")
        print("  # Generate in default location (~/.loggerheads/oracle-keypair.json)")
        print("  python -m loggerheads.oracle_secure --generate")
        print("\n  # Generate in custom location")
        print("  python -m loggerheads.oracle_secure --generate /secure/oracle-keypair.json")
        print("\n  # Show current oracle public key")
        print("  python -m loggerheads.oracle_secure --pubkey")
