/**
 * Synor Compiler SDK Examples for C++
 *
 * Demonstrates smart contract compilation and analysis:
 * - WASM contract compilation and optimization
 * - ABI extraction and encoding
 * - Contract analysis and security scanning
 * - Validation and verification
 */

#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <synor/compiler.hpp>

using namespace synor::compiler;

// Helper function to create a minimal valid WASM module for testing
std::vector<uint8_t> create_minimal_wasm() {
    return {
        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
    };
}

void compile_contract_example(SynorCompiler& compiler) {
    std::cout << "=== Contract Compilation ===" << std::endl;

    auto wasm = create_minimal_wasm();

    auto result = compiler.compile(wasm, {
        .optimization_level = OptimizationLevel::Size,
        .use_wasm_opt = true,
        .validate = true,
        .extract_metadata = true,
        .generate_abi = true,
        .strip_options = {
            .strip_debug = true,
            .strip_producers = true,
            .strip_names = true,
            .strip_custom = true,
            .strip_unused = true,
            .preserve_sections = {}
        }
    });

    std::cout << "Compilation result:" << std::endl;
    std::cout << "  Contract ID: " << result.contract_id() << std::endl;
    std::cout << "  Code hash: " << result.code_hash() << std::endl;
    std::cout << "  Original size: " << result.original_size() << " bytes" << std::endl;
    std::cout << "  Optimized size: " << result.optimized_size() << " bytes" << std::endl;
    std::cout << "  Size reduction: " << std::fixed << std::setprecision(1) << result.size_reduction() << "%" << std::endl;
    std::cout << "  Estimated deploy gas: " << result.estimated_deploy_gas() << std::endl;

    if (result.metadata()) {
        std::cout << "\nMetadata:" << std::endl;
        std::cout << "  Name: " << result.metadata()->name() << std::endl;
        std::cout << "  Version: " << result.metadata()->version() << std::endl;
        std::cout << "  SDK Version: " << result.metadata()->sdk_version() << std::endl;
    }

    if (result.abi()) {
        std::cout << "\nABI:" << std::endl;
        std::cout << "  Functions: " << result.abi()->functions().size() << std::endl;
        std::cout << "  Events: " << result.abi()->events().size() << std::endl;
        std::cout << "  Errors: " << result.abi()->errors().size() << std::endl;
    }

    std::cout << std::endl;
}

void compilation_modes_example(SynorCompiler& compiler) {
    std::cout << "=== Compilation Modes ===" << std::endl;

    auto wasm = create_minimal_wasm();

    // Development mode: fast compilation, debugging support
    std::cout << "Development mode:" << std::endl;
    auto dev_result = compiler.contracts().compile_dev(wasm);
    std::cout << "  Size: " << dev_result.optimized_size() << " bytes" << std::endl;
    std::cout << "  Optimization: none" << std::endl;

    // Production mode: maximum optimization
    std::cout << "\nProduction mode:" << std::endl;
    auto prod_result = compiler.contracts().compile_production(wasm);
    std::cout << "  Size: " << prod_result.optimized_size() << " bytes" << std::endl;
    std::cout << "  Optimization: aggressive" << std::endl;
    std::cout << "  Size savings: " << (dev_result.optimized_size() - prod_result.optimized_size()) << " bytes" << std::endl;

    // Custom optimization levels
    std::cout << "\nOptimization levels:" << std::endl;
    std::vector<std::pair<OptimizationLevel, std::string>> levels = {
        {OptimizationLevel::None, "NONE"},
        {OptimizationLevel::Basic, "BASIC"},
        {OptimizationLevel::Size, "SIZE"},
        {OptimizationLevel::Aggressive, "AGGRESSIVE"}
    };

    for (const auto& [level, name] : levels) {
        auto result = compiler.compile(wasm, {.optimization_level = level});
        std::cout << "  " << name << ": " << result.optimized_size() << " bytes" << std::endl;
    }

    std::cout << std::endl;
}

void abi_example(SynorCompiler& compiler) {
    std::cout << "=== ABI Operations ===" << std::endl;

    auto wasm = create_minimal_wasm();

    // Extract ABI from WASM
    auto abi = compiler.abi().extract(wasm);
    std::cout << "Contract: " << abi.name() << std::endl;
    std::cout << "Version: " << abi.version() << std::endl;

    // List functions
    if (!abi.functions().empty()) {
        std::cout << "\nFunctions:" << std::endl;
        for (const auto& func : abi.functions()) {
            std::string inputs;
            for (size_t i = 0; i < func.inputs().size(); ++i) {
                const auto& param = func.inputs()[i];
                if (i > 0) inputs += ", ";
                inputs += param.name() + ": " + param.type().type_name();
            }

            std::string outputs;
            if (func.outputs().empty()) {
                outputs = "void";
            } else {
                for (size_t i = 0; i < func.outputs().size(); ++i) {
                    if (i > 0) outputs += ", ";
                    outputs += func.outputs()[i].type().type_name();
                }
            }

            std::string modifiers;
            if (func.view()) modifiers += "view ";
            if (func.payable()) modifiers += "payable";

            std::cout << "  " << func.name() << "(" << inputs << ") -> " << outputs << " " << modifiers << std::endl;
            std::cout << "    Selector: " << func.selector() << std::endl;
        }
    }

    // List events
    if (!abi.events().empty()) {
        std::cout << "\nEvents:" << std::endl;
        for (const auto& event : abi.events()) {
            std::string params;
            for (size_t i = 0; i < event.params().size(); ++i) {
                const auto& param = event.params()[i];
                if (i > 0) params += ", ";
                if (param.indexed()) params += "indexed ";
                params += param.name() + ": " + param.type().type_name();
            }
            std::cout << "  " << event.name() << "(" << params << ")" << std::endl;
            std::cout << "    Topic: " << event.topic() << std::endl;
        }
    }

    // Encode a function call
    if (!abi.functions().empty()) {
        const auto& func = abi.functions().front();
        auto encoded = compiler.abi().encode_call(func, {"arg1", "arg2"});
        std::cout << "\nEncoded call to " << func.name() << ": " << encoded << std::endl;

        // Decode a result
        auto decoded = compiler.abi().decode_result(func, encoded);
        std::cout << "Decoded result: " << decoded << std::endl;
    }

    std::cout << std::endl;
}

void analysis_example(SynorCompiler& compiler) {
    std::cout << "=== Contract Analysis ===" << std::endl;

    auto wasm = create_minimal_wasm();

    // Full analysis
    auto analysis = compiler.analysis().analyze(wasm);

    // Size breakdown
    if (analysis.size_breakdown()) {
        const auto& size = *analysis.size_breakdown();
        std::cout << "Size breakdown:" << std::endl;
        std::cout << "  Code: " << size.code() << " bytes" << std::endl;
        std::cout << "  Data: " << size.data() << " bytes" << std::endl;
        std::cout << "  Functions: " << size.functions() << " bytes" << std::endl;
        std::cout << "  Memory: " << size.memory() << " bytes" << std::endl;
        std::cout << "  Exports: " << size.exports() << " bytes" << std::endl;
        std::cout << "  Imports: " << size.imports() << " bytes" << std::endl;
        std::cout << "  Total: " << size.total() << " bytes" << std::endl;
    }

    // Function analysis
    if (!analysis.functions().empty()) {
        std::cout << "\nFunction analysis:" << std::endl;
        for (size_t i = 0; i < std::min(analysis.functions().size(), size_t(5)); ++i) {
            const auto& func = analysis.functions()[i];
            std::cout << "  " << func.name() << ":" << std::endl;
            std::cout << "    Size: " << func.size() << " bytes" << std::endl;
            std::cout << "    Instructions: " << func.instruction_count() << std::endl;
            std::cout << "    Locals: " << func.local_count() << std::endl;
            std::cout << "    Exported: " << (func.exported() ? "true" : "false") << std::endl;
            std::cout << "    Estimated gas: " << func.estimated_gas() << std::endl;
        }
    }

    // Import analysis
    if (!analysis.imports().empty()) {
        std::cout << "\nImports:" << std::endl;
        for (const auto& imp : analysis.imports()) {
            std::cout << "  " << imp.module() << "." << imp.name() << " (" << imp.kind() << ")" << std::endl;
        }
    }

    // Gas analysis
    if (analysis.gas_analysis()) {
        const auto& gas = *analysis.gas_analysis();
        std::cout << "\nGas analysis:" << std::endl;
        std::cout << "  Deployment: " << gas.deployment_gas() << std::endl;
        std::cout << "  Memory init: " << gas.memory_init_gas() << std::endl;
        std::cout << "  Data section: " << gas.data_section_gas() << std::endl;
    }

    // Extract metadata
    auto metadata = compiler.analysis().extract_metadata(wasm);
    std::cout << "\nContract metadata:" << std::endl;
    std::cout << "  Name: " << metadata.name() << std::endl;
    std::cout << "  Version: " << metadata.version() << std::endl;
    std::cout << "  Build timestamp: " << metadata.build_timestamp() << std::endl;

    // Estimate deployment gas
    auto gas_estimate = compiler.analysis().estimate_deploy_gas(wasm);
    std::cout << "\nEstimated deployment gas: " << gas_estimate << std::endl;

    std::cout << std::endl;
}

void validation_example(SynorCompiler& compiler) {
    std::cout << "=== Contract Validation ===" << std::endl;

    auto wasm = create_minimal_wasm();

    // Full validation
    auto result = compiler.validation().validate(wasm);
    std::cout << "Valid: " << (result.valid() ? "true" : "false") << std::endl;
    std::cout << "Exports: " << result.export_count() << std::endl;
    std::cout << "Imports: " << result.import_count() << std::endl;
    std::cout << "Functions: " << result.function_count() << std::endl;
    std::cout << "Memory pages: " << result.memory_pages() << std::endl;

    if (!result.errors().empty()) {
        std::cout << "\nValidation errors:" << std::endl;
        for (const auto& error : result.errors()) {
            std::cout << "  [" << error.code() << "] " << error.message() << std::endl;
            if (!error.location().empty()) {
                std::cout << "    at " << error.location() << std::endl;
            }
        }
    }

    if (!result.warnings().empty()) {
        std::cout << "\nWarnings:" << std::endl;
        for (const auto& warning : result.warnings()) {
            std::cout << "  " << warning << std::endl;
        }
    }

    // Quick validation
    bool is_valid = compiler.validation().is_valid(wasm);
    std::cout << "\nQuick validation: " << (is_valid ? "true" : "false") << std::endl;

    // Get validation errors only
    auto errors = compiler.validation().get_errors(wasm);
    std::cout << "Error count: " << errors.size() << std::endl;

    // Validate required exports
    bool has_required = compiler.validation().validate_exports(wasm, {"init", "execute", "query"});
    std::cout << "Has required exports: " << (has_required ? "true" : "false") << std::endl;

    // Validate memory constraints
    bool memory_valid = compiler.validation().validate_memory(wasm, 16);
    std::cout << "Memory within 16 pages: " << (memory_valid ? "true" : "false") << std::endl;

    std::cout << std::endl;
}

void security_example(SynorCompiler& compiler) {
    std::cout << "=== Security Scanning ===" << std::endl;

    auto wasm = create_minimal_wasm();

    auto security = compiler.analysis().security_scan(wasm);

    std::cout << "Security score: " << security.score() << "/100" << std::endl;

    if (!security.issues().empty()) {
        std::cout << "\nSecurity issues:" << std::endl;
        for (const auto& issue : security.issues()) {
            std::string icon;
            std::string severity = issue.severity();
            if (severity == "critical") icon = "[CRIT]";
            else if (severity == "high") icon = "[HIGH]";
            else if (severity == "medium") icon = "[MED]";
            else if (severity == "low") icon = "[LOW]";
            else icon = "[???]";

            std::cout << icon << " [" << issue.severity() << "] " << issue.type() << std::endl;
            std::cout << "   " << issue.description() << std::endl;
            if (!issue.location().empty()) {
                std::cout << "   at " << issue.location() << std::endl;
            }
        }
    } else {
        std::cout << "No security issues found!" << std::endl;
    }

    if (!security.recommendations().empty()) {
        std::cout << "\nRecommendations:" << std::endl;
        for (const auto& rec : security.recommendations()) {
            std::cout << "  • " << rec << std::endl;
        }
    }

    std::cout << std::endl;
}

int main(int argc, char** argv) {
    // Initialize client
    const char* api_key = std::getenv("SYNOR_API_KEY");
    CompilerConfig config{
        .api_key = api_key ? api_key : "your-api-key",
        .endpoint = "https://compiler.synor.io/v1",
        .timeout = std::chrono::seconds(60),
        .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
    };

    SynorCompiler compiler(config);

    try {
        // Check service health
        bool healthy = compiler.health_check();
        std::cout << "Service healthy: " << (healthy ? "true" : "false") << std::endl << std::endl;

        // Run examples
        compile_contract_example(compiler);
        compilation_modes_example(compiler);
        abi_example(compiler);
        analysis_example(compiler);
        validation_example(compiler);
        security_example(compiler);
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}
