#!/usr/bin/env python3
"""
Build .env file for RADKit FastMCP Server.

This script reads RADKit certificate files from your local identity directory,
base64-encodes them, and creates a .env file for the FastMCP server.

Prerequisites:
- RADKit client must be enrolled (see enrollment instructions below)
- Certificate files must exist in ~/.radkit/identities/
"""

import base64
import os
import sys
from pathlib import Path
from getpass import getpass


def print_banner():
    """Print script banner."""
    print("=" * 70)
    print("RADKit FastMCP Server - Environment File Builder")
    print("=" * 70)
    print()


def print_enrollment_help():
    """Print enrollment instructions."""
    print("\n" + "=" * 70)
    print("CLIENT ENROLLMENT REQUIRED")
    print("=" * 70)
    print("""
Your RADKit client must be enrolled before you can use certificate authentication.

To enroll your client:

1. Create a Python script (enroll.py):

    from radkit_client.sync import Client

    with Client.create() as client:
        # Authenticate with SSO
        client.sso_login("your-email@cisco.com")

        # Enroll the client
        client.enroll_client()
        # You'll be prompted for a password to protect your private key

2. Run the enrollment script:

    python enroll.py

3. After enrollment, run this script again to build your .env file

For more information, see RADKit documentation on client enrollment.
""")
    print("=" * 70)


def get_identity_directory(identity: str, domain: str = "prod.radkit-cloud.cisco.com") -> Path:
    """
    Get the RADKit identity directory path.

    Args:
        identity: User email address
        domain: RADKit domain (default: prod.radkit-cloud.cisco.com)

    Returns:
        Path to identity directory
    """
    radkit_dir = Path.home() / ".radkit" / "identities" / domain / identity
    return radkit_dir


def check_certificate_files(identity_dir: Path) -> tuple[bool, list[str]]:
    """
    Check if all required certificate files exist.

    Args:
        identity_dir: Path to identity directory

    Returns:
        Tuple of (all_exist: bool, missing_files: list)
    """
    required_files = [
        "certificate.pem",
        "private_key_encrypted.pem",
        "chain.pem"
    ]

    missing = []
    for filename in required_files:
        filepath = identity_dir / filename
        if not filepath.exists():
            missing.append(filename)

    return len(missing) == 0, missing


def read_and_encode_file(filepath: Path) -> str:
    """
    Read a file and return its base64-encoded content.

    Args:
        filepath: Path to file to encode

    Returns:
        Base64-encoded string
    """
    try:
        with open(filepath, 'rb') as f:
            content = f.read()
        return base64.b64encode(content).decode('utf-8')
    except Exception as e:
        print(f"Error reading {filepath}: {e}")
        sys.exit(1)


def encode_password(password: str) -> str:
    """
    Base64-encode a password string.

    Args:
        password: Plain text password

    Returns:
        Base64-encoded password
    """
    return base64.b64encode(password.encode('utf-8')).decode('utf-8')


def build_env_file(
    identity: str,
    service_serial: str,
    cert_b64: str,
    key_b64: str,
    ca_b64: str,
    password_b64: str,
    output_file: str = ".env"
) -> None:
    """
    Build the .env file with encoded certificates.

    Args:
        identity: RADKit identity (email)
        service_serial: Default service serial
        cert_b64: Base64-encoded certificate
        key_b64: Base64-encoded private key
        ca_b64: Base64-encoded CA chain
        password_b64: Base64-encoded password
        output_file: Output filename (default: .env)
    """
    env_content = f"""# RADKit FastMCP Server Configuration
# Generated by scripts/build_env.py

# RADKit Identity (email)
RADKIT_IDENTITY={identity}

# Default Service Serial (device to connect to)
RADKIT_DEFAULT_SERVICE_SERIAL={service_serial}

# Certificate Authentication (Base64 Encoded)
RADKIT_CERT_B64={cert_b64}
RADKIT_KEY_B64={key_b64}
RADKIT_CA_B64={ca_b64}
RADKIT_KEY_PASSWORD_B64={password_b64}

# Future: Access Token Authentication (not yet implemented)
# RADKIT_ACCESS_TOKEN=<your_access_token>
"""

    try:
        with open(output_file, 'w') as f:
            f.write(env_content)
        print(f"\n✓ Environment file created: {output_file}")
    except Exception as e:
        print(f"\n✗ Error writing {output_file}: {e}")
        sys.exit(1)


def main():
    """Main function to build .env file."""
    print_banner()

    # Get user input
    print("Please provide the following information:\n")

    identity = input("RADKit Identity (email) [e.g., user@cisco.com]: ").strip()
    if not identity:
        print("Error: Identity is required")
        sys.exit(1)

    service_serial = input("Default Service Serial [e.g., tkj9-0881-7p1j]: ").strip()
    if not service_serial:
        print("Error: Service serial is required")
        sys.exit(1)

    domain = input("RADKit Domain [prod.radkit-cloud.cisco.com]: ").strip()
    if not domain:
        domain = "prod.radkit-cloud.cisco.com"

    # Check if identity directory exists
    identity_dir = get_identity_directory(identity, domain)

    print(f"\nLooking for certificates in:")
    print(f"  {identity_dir}")

    if not identity_dir.exists():
        print(f"\n✗ Error: Identity directory does not exist!")
        print(f"  Directory: {identity_dir}")
        print_enrollment_help()
        sys.exit(1)

    # Check if certificate files exist
    all_exist, missing_files = check_certificate_files(identity_dir)

    if not all_exist:
        print(f"\n✗ Error: Missing certificate files:")
        for filename in missing_files:
            print(f"  - {filename}")
        print_enrollment_help()
        sys.exit(1)

    print("✓ All certificate files found")

    # Get password
    print("\nEnter the password for your private key:")
    password = getpass("Password: ")

    if not password:
        print("Error: Password is required")
        sys.exit(1)

    # Confirm password
    password_confirm = getpass("Confirm password: ")

    if password != password_confirm:
        print("Error: Passwords do not match")
        sys.exit(1)

    # Read and encode certificate files
    print("\nEncoding certificate files...")

    cert_path = identity_dir / "certificate.pem"
    key_path = identity_dir / "private_key_encrypted.pem"
    ca_path = identity_dir / "chain.pem"

    cert_b64 = read_and_encode_file(cert_path)
    print(f"  ✓ Encoded certificate.pem ({len(cert_b64)} chars)")

    key_b64 = read_and_encode_file(key_path)
    print(f"  ✓ Encoded private_key_encrypted.pem ({len(key_b64)} chars)")

    ca_b64 = read_and_encode_file(ca_path)
    print(f"  ✓ Encoded chain.pem ({len(ca_b64)} chars)")

    password_b64 = encode_password(password)
    print(f"  ✓ Encoded password ({len(password_b64)} chars)")

    # Ask for output file
    print("\nWhere should the environment file be saved?")
    output_file = input("Output file [.env]: ").strip()
    if not output_file:
        output_file = ".env"

    # Build .env file
    build_env_file(
        identity=identity,
        service_serial=service_serial,
        cert_b64=cert_b64,
        key_b64=key_b64,
        ca_b64=ca_b64,
        password_b64=password_b64,
        output_file=output_file
    )

    print("\n" + "=" * 70)
    print("SUCCESS!")
    print("=" * 70)
    print(f"""
Environment file created: {output_file}

Next steps:
1. Verify the file contents (but don't share it - it contains credentials!)
2. Test the server:
   .venv/bin/python tests/test_integration.py

3. Run the server:
   fastmcp dev src/radkit_fastmcp/server.py

Security reminder:
- Keep {output_file} secure and never commit it to git
- The .gitignore file is configured to exclude .env files
- For production, use secure secret management (Kubernetes secrets, etc.)
""")
    print("=" * 70)


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\nOperation cancelled by user")
        sys.exit(1)
    except Exception as e:
        print(f"\n\n✗ Unexpected error: {e}")
        import traceback
        traceback.print_exc()
        sys.exit(1)
