#!/usr/bin/env python3
"""
Synor Compiler SDK Examples for Python

Demonstrates smart contract compilation and analysis:
- WASM contract compilation and optimization
- ABI extraction and encoding
- Contract analysis and security scanning
- Validation and verification
"""

import asyncio
import os
from synor_compiler import (
    SynorCompiler,
    CompilerConfig,
    OptimizationLevel,
    StripOptions,
)


async def main():
    """Main entry point."""
    # Initialize client
    config = CompilerConfig(
        api_key=os.environ.get("SYNOR_API_KEY", "your-api-key"),
        endpoint="https://compiler.synor.io/v1",
        timeout=60000,
        retries=3,
        debug=False,
        default_optimization_level=OptimizationLevel.SIZE,
        max_contract_size=256 * 1024,
        use_wasm_opt=True,
        validate=True,
        extract_metadata=True,
        generate_abi=True,
    )

    compiler = SynorCompiler(config)

    try:
        # Check service health
        healthy = await compiler.health_check()
        print(f"Service healthy: {healthy}\n")

        # Example 1: Compile a contract
        await compile_contract_example(compiler)

        # Example 2: Development vs Production
        await compilation_modes_example(compiler)

        # Example 3: ABI operations
        await abi_example(compiler)

        # Example 4: Contract analysis
        await analysis_example(compiler)

        # Example 5: Validation
        await validation_example(compiler)

        # Example 6: Security scanning
        await security_example(compiler)
    finally:
        await compiler.close()


def create_minimal_wasm() -> bytes:
    """Create a minimal valid WASM module for testing."""
    return bytes([
        0x00, 0x61, 0x73, 0x6d,  # Magic: \0asm
        0x01, 0x00, 0x00, 0x00,  # Version: 1
        # Type section
        0x01, 0x07, 0x01, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f,
        # Function section
        0x03, 0x02, 0x01, 0x00,
        # Export section
        0x07, 0x08, 0x01, 0x04, 0x61, 0x64, 0x64, 0x00, 0x00,
        # Code section
        0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b,
    ])


async def compile_contract_example(compiler: SynorCompiler):
    """Basic contract compilation."""
    print("=== Contract Compilation ===")

    wasm = create_minimal_wasm()

    result = await compiler.compile(
        wasm,
        optimization_level=OptimizationLevel.SIZE,
        use_wasm_opt=True,
        validate=True,
        extract_metadata=True,
        generate_abi=True,
        strip_options=StripOptions(
            strip_debug=True,
            strip_producers=True,
            strip_names=True,
            strip_custom=True,
            strip_unused=True,
            preserve_sections=[],
        ),
    )

    print("Compilation result:")
    print(f"  Contract ID: {result.contract_id}")
    print(f"  Code hash: {result.code_hash}")
    print(f"  Original size: {result.original_size} bytes")
    print(f"  Optimized size: {result.optimized_size} bytes")
    print(f"  Size reduction: {result.size_reduction:.1f}%")
    print(f"  Estimated deploy gas: {result.estimated_deploy_gas}")

    if result.metadata:
        print("\nMetadata:")
        print(f"  Name: {result.metadata.name}")
        print(f"  Version: {result.metadata.version}")
        print(f"  SDK Version: {result.metadata.sdk_version}")

    if result.abi:
        print("\nABI:")
        print(f"  Functions: {len(result.abi.functions or [])}")
        print(f"  Events: {len(result.abi.events or [])}")
        print(f"  Errors: {len(result.abi.errors or [])}")

    print()


async def compilation_modes_example(compiler: SynorCompiler):
    """Development vs Production compilation modes."""
    print("=== Compilation Modes ===")

    wasm = create_minimal_wasm()

    # Development mode: fast compilation, debugging support
    print("Development mode:")
    dev_result = await compiler.contracts.compile_dev(wasm)
    print(f"  Size: {dev_result.optimized_size} bytes")
    print(f"  Optimization: none")

    # Production mode: maximum optimization
    print("\nProduction mode:")
    prod_result = await compiler.contracts.compile_production(wasm)
    print(f"  Size: {prod_result.optimized_size} bytes")
    print(f"  Optimization: aggressive")
    print(f"  Size savings: {dev_result.optimized_size - prod_result.optimized_size} bytes")

    # Custom optimization levels
    print("\nOptimization levels:")
    levels = [
        OptimizationLevel.NONE,
        OptimizationLevel.BASIC,
        OptimizationLevel.SIZE,
        OptimizationLevel.AGGRESSIVE,
    ]

    for level in levels:
        result = await compiler.compile(wasm, optimization_level=level)
        print(f"  {level.value}: {result.optimized_size} bytes")

    print()


async def abi_example(compiler: SynorCompiler):
    """ABI extraction and encoding."""
    print("=== ABI Operations ===")

    wasm = create_minimal_wasm()

    # Extract ABI from WASM
    abi = await compiler.abi.extract(wasm)
    print(f"Contract: {abi.name}")
    print(f"Version: {abi.version}")

    # List functions
    if abi.functions:
        print("\nFunctions:")
        for func in abi.functions:
            inputs = ", ".join(
                f"{i.name}: {i.type.type_name}" for i in (func.inputs or [])
            )
            outputs = ", ".join(o.type.type_name for o in (func.outputs or [])) or "void"
            modifiers = " ".join(
                filter(None, ["view" if func.view else "", "payable" if func.payable else ""])
            )
            print(f"  {func.name}({inputs}) -> {outputs} {modifiers}")
            print(f"    Selector: {func.selector}")

    # List events
    if abi.events:
        print("\nEvents:")
        for event in abi.events:
            params = ", ".join(
                f"{'indexed ' if p.indexed else ''}{p.name}: {p.type.type_name}"
                for p in (event.params or [])
            )
            print(f"  {event.name}({params})")
            print(f"    Topic: {event.topic}")

    # Encode a function call
    if abi.functions:
        func = abi.functions[0]
        encoded = await compiler.abi.encode_call(func, ["arg1", "arg2"])
        print(f"\nEncoded call to {func.name}: {encoded}")

        # Decode a result
        decoded = await compiler.abi.decode_result(func, encoded)
        print(f"Decoded result: {decoded}")

    print()


async def analysis_example(compiler: SynorCompiler):
    """Contract analysis."""
    print("=== Contract Analysis ===")

    wasm = create_minimal_wasm()

    # Full analysis
    analysis = await compiler.analysis.analyze(wasm)

    # Size breakdown
    if analysis.size_breakdown:
        print("Size breakdown:")
        print(f"  Code: {analysis.size_breakdown.code} bytes")
        print(f"  Data: {analysis.size_breakdown.data} bytes")
        print(f"  Functions: {analysis.size_breakdown.functions} bytes")
        print(f"  Memory: {analysis.size_breakdown.memory} bytes")
        print(f"  Exports: {analysis.size_breakdown.exports} bytes")
        print(f"  Imports: {analysis.size_breakdown.imports} bytes")
        print(f"  Total: {analysis.size_breakdown.total} bytes")

    # Function analysis
    if analysis.functions:
        print("\nFunction analysis:")
        for func in analysis.functions[:5]:
            print(f"  {func.name}:")
            print(f"    Size: {func.size} bytes")
            print(f"    Instructions: {func.instruction_count}")
            print(f"    Locals: {func.local_count}")
            print(f"    Exported: {func.exported}")
            print(f"    Estimated gas: {func.estimated_gas}")

    # Import analysis
    if analysis.imports:
        print("\nImports:")
        for imp in analysis.imports:
            print(f"  {imp.module}.{imp.name} ({imp.kind})")

    # Gas analysis
    if analysis.gas_analysis:
        print("\nGas analysis:")
        print(f"  Deployment: {analysis.gas_analysis.deployment_gas}")
        print(f"  Memory init: {analysis.gas_analysis.memory_init_gas}")
        print(f"  Data section: {analysis.gas_analysis.data_section_gas}")

    # Extract metadata
    metadata = await compiler.analysis.extract_metadata(wasm)
    print("\nContract metadata:")
    print(f"  Name: {metadata.name}")
    print(f"  Version: {metadata.version}")
    print(f"  Build timestamp: {metadata.build_timestamp}")

    # Estimate deployment gas
    gas = await compiler.analysis.estimate_deploy_gas(wasm)
    print(f"\nEstimated deployment gas: {gas}")

    print()


async def validation_example(compiler: SynorCompiler):
    """Contract validation."""
    print("=== Contract Validation ===")

    wasm = create_minimal_wasm()

    # Full validation
    result = await compiler.validation.validate(wasm)
    print(f"Valid: {result.valid}")
    print(f"Exports: {result.export_count}")
    print(f"Imports: {result.import_count}")
    print(f"Functions: {result.function_count}")
    print(f"Memory pages: {result.memory_pages}")

    if result.errors:
        print("\nValidation errors:")
        for error in result.errors:
            print(f"  [{error.code}] {error.message}")
            if error.location:
                print(f"    at {error.location}")

    if result.warnings:
        print("\nWarnings:")
        for warning in result.warnings:
            print(f"  {warning}")

    # Quick validation
    is_valid = await compiler.validation.is_valid(wasm)
    print(f"\nQuick validation: {is_valid}")

    # Get validation errors only
    errors = await compiler.validation.get_errors(wasm)
    print(f"Error count: {len(errors)}")

    # Validate required exports
    has_required = await compiler.validation.validate_exports(
        wasm, ["init", "execute", "query"]
    )
    print(f"Has required exports: {has_required}")

    # Validate memory constraints
    memory_valid = await compiler.validation.validate_memory(wasm, 16)
    print(f"Memory within 16 pages: {memory_valid}")

    print()


async def security_example(compiler: SynorCompiler):
    """Security scanning."""
    print("=== Security Scanning ===")

    wasm = create_minimal_wasm()

    security = await compiler.analysis.security_scan(wasm)

    print(f"Security score: {security.score}/100")

    if security.issues:
        print("\nSecurity issues:")
        severity_icons = {
            "critical": "🔴",
            "high": "🟠",
            "medium": "🟡",
            "low": "🟢",
        }
        for issue in security.issues:
            icon = severity_icons.get(issue.severity, "⚪")
            print(f"{icon} [{issue.severity.upper()}] {issue.type}")
            print(f"   {issue.description}")
            if issue.location:
                print(f"   at {issue.location}")
    else:
        print("No security issues found!")

    if security.recommendations:
        print("\nRecommendations:")
        for rec in security.recommendations:
            print(f"  • {rec}")

    print()


if __name__ == "__main__":
    asyncio.run(main())
