/**
 * 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
 */

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Synor.Compiler;

namespace Synor.Examples;

public class CompilerExample
{
    private readonly SynorCompiler _compiler;

    public CompilerExample(SynorCompiler compiler)
    {
        _compiler = compiler;
    }

    /// <summary>
    /// Creates a minimal valid WASM module for testing
    /// </summary>
    private static byte[] CreateMinimalWasm()
    {
        return new byte[]
        {
            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, (byte)'a', (byte)'d', (byte)'d', 0x00, 0x00,
            // Code section
            0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b
        };
    }

    public async Task RunCompileContractExample()
    {
        Console.WriteLine("=== Contract Compilation ===");

        var wasm = CreateMinimalWasm();

        var result = await _compiler.CompileAsync(wasm, new CompileOptions
        {
            OptimizationLevel = OptimizationLevel.Size,
            UseWasmOpt = true,
            Validate = true,
            ExtractMetadata = true,
            GenerateAbi = true,
            StripOptions = new StripOptions
            {
                StripDebug = true,
                StripProducers = true,
                StripNames = true,
                StripCustom = true,
                StripUnused = true,
                PreserveSections = new List<string>()
            }
        });

        Console.WriteLine("Compilation result:");
        Console.WriteLine($"  Contract ID: {result.ContractId}");
        Console.WriteLine($"  Code hash: {result.CodeHash}");
        Console.WriteLine($"  Original size: {result.OriginalSize} bytes");
        Console.WriteLine($"  Optimized size: {result.OptimizedSize} bytes");
        Console.WriteLine($"  Size reduction: {result.SizeReduction:F1}%");
        Console.WriteLine($"  Estimated deploy gas: {result.EstimatedDeployGas}");

        if (result.Metadata != null)
        {
            Console.WriteLine("\nMetadata:");
            Console.WriteLine($"  Name: {result.Metadata.Name}");
            Console.WriteLine($"  Version: {result.Metadata.Version}");
            Console.WriteLine($"  SDK Version: {result.Metadata.SdkVersion}");
        }

        if (result.Abi != null)
        {
            Console.WriteLine("\nABI:");
            Console.WriteLine($"  Functions: {result.Abi.Functions.Count}");
            Console.WriteLine($"  Events: {result.Abi.Events.Count}");
            Console.WriteLine($"  Errors: {result.Abi.Errors.Count}");
        }
        Console.WriteLine();
    }

    public async Task RunCompilationModesExample()
    {
        Console.WriteLine("=== Compilation Modes ===");

        var wasm = CreateMinimalWasm();

        // Development mode: fast compilation, debugging support
        Console.WriteLine("Development mode:");
        var devResult = await _compiler.Contracts.CompileDevAsync(wasm);
        Console.WriteLine($"  Size: {devResult.OptimizedSize} bytes");
        Console.WriteLine("  Optimization: none");

        // Production mode: maximum optimization
        Console.WriteLine("\nProduction mode:");
        var prodResult = await _compiler.Contracts.CompileProductionAsync(wasm);
        Console.WriteLine($"  Size: {prodResult.OptimizedSize} bytes");
        Console.WriteLine("  Optimization: aggressive");
        Console.WriteLine($"  Size savings: {devResult.OptimizedSize - prodResult.OptimizedSize} bytes");

        // Custom optimization levels
        Console.WriteLine("\nOptimization levels:");
        var levels = new (OptimizationLevel Level, string Name)[]
        {
            (OptimizationLevel.None, "NONE"),
            (OptimizationLevel.Basic, "BASIC"),
            (OptimizationLevel.Size, "SIZE"),
            (OptimizationLevel.Aggressive, "AGGRESSIVE")
        };

        foreach (var (level, name) in levels)
        {
            var result = await _compiler.CompileAsync(wasm, new CompileOptions
            {
                OptimizationLevel = level
            });
            Console.WriteLine($"  {name}: {result.OptimizedSize} bytes");
        }
        Console.WriteLine();
    }

    public async Task RunAbiExample()
    {
        Console.WriteLine("=== ABI Operations ===");

        var wasm = CreateMinimalWasm();

        // Extract ABI from WASM
        var abi = await _compiler.Abi.ExtractAsync(wasm);
        Console.WriteLine($"Contract: {abi.Name}");
        Console.WriteLine($"Version: {abi.Version}");

        // List functions
        if (abi.Functions.Count > 0)
        {
            Console.WriteLine("\nFunctions:");
            foreach (var func in abi.Functions)
            {
                var inputs = string.Join(", ", func.Inputs.ConvertAll(p => $"{p.Name}: {p.Type.TypeName}"));
                var outputs = func.Outputs.Count == 0
                    ? "void"
                    : string.Join(", ", func.Outputs.ConvertAll(o => o.Type.TypeName));

                var modifiers = new List<string>();
                if (func.View) modifiers.Add("view");
                if (func.Payable) modifiers.Add("payable");
                var modifierStr = modifiers.Count > 0 ? string.Join(" ", modifiers) : "";

                Console.WriteLine($"  {func.Name}({inputs}) -> {outputs} {modifierStr}");
                Console.WriteLine($"    Selector: {func.Selector}");
            }
        }

        // List events
        if (abi.Events.Count > 0)
        {
            Console.WriteLine("\nEvents:");
            foreach (var evt in abi.Events)
            {
                var paramParts = new List<string>();
                foreach (var param in evt.Params)
                {
                    var prefix = param.Indexed ? "indexed " : "";
                    paramParts.Add($"{prefix}{param.Name}: {param.Type.TypeName}");
                }
                Console.WriteLine($"  {evt.Name}({string.Join(", ", paramParts)})");
                Console.WriteLine($"    Topic: {evt.Topic}");
            }
        }

        // Encode a function call
        if (abi.Functions.Count > 0)
        {
            var func = abi.Functions[0];
            var encoded = await _compiler.Abi.EncodeCallAsync(func, new[] { "arg1", "arg2" });
            Console.WriteLine($"\nEncoded call to {func.Name}: {encoded}");

            // Decode a result
            var decoded = await _compiler.Abi.DecodeResultAsync(func, encoded);
            Console.WriteLine($"Decoded result: {decoded}");
        }
        Console.WriteLine();
    }

    public async Task RunAnalysisExample()
    {
        Console.WriteLine("=== Contract Analysis ===");

        var wasm = CreateMinimalWasm();

        // Full analysis
        var analysis = await _compiler.Analysis.AnalyzeAsync(wasm);

        // Size breakdown
        if (analysis.SizeBreakdown != null)
        {
            var size = analysis.SizeBreakdown;
            Console.WriteLine("Size breakdown:");
            Console.WriteLine($"  Code: {size.Code} bytes");
            Console.WriteLine($"  Data: {size.Data} bytes");
            Console.WriteLine($"  Functions: {size.Functions} bytes");
            Console.WriteLine($"  Memory: {size.Memory} bytes");
            Console.WriteLine($"  Exports: {size.Exports} bytes");
            Console.WriteLine($"  Imports: {size.Imports} bytes");
            Console.WriteLine($"  Total: {size.Total} bytes");
        }

        // Function analysis
        if (analysis.Functions.Count > 0)
        {
            Console.WriteLine("\nFunction analysis:");
            foreach (var func in analysis.Functions.GetRange(0, Math.Min(analysis.Functions.Count, 5)))
            {
                Console.WriteLine($"  {func.Name}:");
                Console.WriteLine($"    Size: {func.Size} bytes");
                Console.WriteLine($"    Instructions: {func.InstructionCount}");
                Console.WriteLine($"    Locals: {func.LocalCount}");
                Console.WriteLine($"    Exported: {func.Exported}");
                Console.WriteLine($"    Estimated gas: {func.EstimatedGas}");
            }
        }

        // Import analysis
        if (analysis.Imports.Count > 0)
        {
            Console.WriteLine("\nImports:");
            foreach (var imp in analysis.Imports)
            {
                Console.WriteLine($"  {imp.Module}.{imp.Name} ({imp.Kind})");
            }
        }

        // Gas analysis
        if (analysis.GasAnalysis != null)
        {
            var gas = analysis.GasAnalysis;
            Console.WriteLine("\nGas analysis:");
            Console.WriteLine($"  Deployment: {gas.DeploymentGas}");
            Console.WriteLine($"  Memory init: {gas.MemoryInitGas}");
            Console.WriteLine($"  Data section: {gas.DataSectionGas}");
        }

        // Extract metadata
        var metadata = await _compiler.Analysis.ExtractMetadataAsync(wasm);
        Console.WriteLine("\nContract metadata:");
        Console.WriteLine($"  Name: {metadata.Name}");
        Console.WriteLine($"  Version: {metadata.Version}");
        Console.WriteLine($"  Build timestamp: {metadata.BuildTimestamp}");

        // Estimate deployment gas
        var gasEstimate = await _compiler.Analysis.EstimateDeployGasAsync(wasm);
        Console.WriteLine($"\nEstimated deployment gas: {gasEstimate}");
        Console.WriteLine();
    }

    public async Task RunValidationExample()
    {
        Console.WriteLine("=== Contract Validation ===");

        var wasm = CreateMinimalWasm();

        // Full validation
        var result = await _compiler.Validation.ValidateAsync(wasm);
        Console.WriteLine($"Valid: {result.Valid}");
        Console.WriteLine($"Exports: {result.ExportCount}");
        Console.WriteLine($"Imports: {result.ImportCount}");
        Console.WriteLine($"Functions: {result.FunctionCount}");
        Console.WriteLine($"Memory pages: {result.MemoryPages}");

        if (result.Errors.Count > 0)
        {
            Console.WriteLine("\nValidation errors:");
            foreach (var error in result.Errors)
            {
                Console.WriteLine($"  [{error.Code}] {error.Message}");
                if (!string.IsNullOrEmpty(error.Location))
                {
                    Console.WriteLine($"    at {error.Location}");
                }
            }
        }

        if (result.Warnings.Count > 0)
        {
            Console.WriteLine("\nWarnings:");
            foreach (var warning in result.Warnings)
            {
                Console.WriteLine($"  {warning}");
            }
        }

        // Quick validation
        var isValid = await _compiler.Validation.IsValidAsync(wasm);
        Console.WriteLine($"\nQuick validation: {isValid}");

        // Get validation errors only
        var errors = await _compiler.Validation.GetErrorsAsync(wasm);
        Console.WriteLine($"Error count: {errors.Count}");

        // Validate required exports
        var hasRequired = await _compiler.Validation.ValidateExportsAsync(wasm, new[] { "init", "execute", "query" });
        Console.WriteLine($"Has required exports: {hasRequired}");

        // Validate memory constraints
        var memoryValid = await _compiler.Validation.ValidateMemoryAsync(wasm, 16);
        Console.WriteLine($"Memory within 16 pages: {memoryValid}");
        Console.WriteLine();
    }

    public async Task RunSecurityExample()
    {
        Console.WriteLine("=== Security Scanning ===");

        var wasm = CreateMinimalWasm();

        var security = await _compiler.Analysis.SecurityScanAsync(wasm);

        Console.WriteLine($"Security score: {security.Score}/100");

        if (security.Issues.Count > 0)
        {
            Console.WriteLine("\nSecurity issues:");
            foreach (var issue in security.Issues)
            {
                var icon = issue.Severity switch
                {
                    "critical" => "[CRIT]",
                    "high" => "[HIGH]",
                    "medium" => "[MED]",
                    "low" => "[LOW]",
                    _ => "[???]"
                };

                Console.WriteLine($"{icon} [{issue.Severity}] {issue.Type}");
                Console.WriteLine($"   {issue.Description}");
                if (!string.IsNullOrEmpty(issue.Location))
                {
                    Console.WriteLine($"   at {issue.Location}");
                }
            }
        }
        else
        {
            Console.WriteLine("No security issues found!");
        }

        if (security.Recommendations.Count > 0)
        {
            Console.WriteLine("\nRecommendations:");
            foreach (var rec in security.Recommendations)
            {
                Console.WriteLine($"  • {rec}");
            }
        }
        Console.WriteLine();
    }

    public static async Task Main(string[] args)
    {
        // Initialize client
        var apiKey = Environment.GetEnvironmentVariable("SYNOR_API_KEY") ?? "your-api-key";
        var config = new CompilerConfig
        {
            ApiKey = apiKey,
            Endpoint = "https://compiler.synor.io/v1",
            Timeout = TimeSpan.FromSeconds(60),
            Retries = 3,
            Debug = false,
            DefaultOptimizationLevel = OptimizationLevel.Size,
            MaxContractSize = 256 * 1024,
            UseWasmOpt = true,
            Validate = true,
            ExtractMetadata = true,
            GenerateAbi = true
        };

        var compiler = new SynorCompiler(config);
        var example = new CompilerExample(compiler);

        try
        {
            // Check service health
            var healthy = await compiler.HealthCheckAsync();
            Console.WriteLine($"Service healthy: {healthy}\n");

            // Run examples
            await example.RunCompileContractExample();
            await example.RunCompilationModesExample();
            await example.RunAbiExample();
            await example.RunAnalysisExample();
            await example.RunValidationExample();
            await example.RunSecurityExample();
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine($"Error: {ex.Message}");
            Environment.Exit(1);
        }
    }
}
