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

import * as fs from 'fs';
import {
  SynorCompiler,
  CompilerConfig,
  OptimizationLevel,
  StripOptions,
} from '../src/compiler';

async function main() {
  // Initialize client
  const config: CompilerConfig = {
    apiKey: process.env.SYNOR_API_KEY || 'your-api-key',
    endpoint: 'https://compiler.synor.io/v1',
    timeout: 60000,
    retries: 3,
    debug: false,
    defaultOptimizationLevel: OptimizationLevel.Size,
    maxContractSize: 256 * 1024,
    useWasmOpt: true,
    validate: true,
    extractMetadata: true,
    generateAbi: true,
  };

  const compiler = new SynorCompiler(config);

  try {
    // Check service health
    const healthy = await compiler.healthCheck();
    console.log(`Service healthy: ${healthy}\n`);

    // Example 1: Compile a contract
    await compileContractExample(compiler);

    // Example 2: Development vs Production compilation
    await compilationModesExample(compiler);

    // Example 3: ABI operations
    await abiExample(compiler);

    // Example 4: Contract analysis
    await analysisExample(compiler);

    // Example 5: Validation
    await validationExample(compiler);

    // Example 6: Security scanning
    await securityExample(compiler);
  } finally {
    compiler.close();
  }
}

/**
 * Basic contract compilation
 */
async function compileContractExample(compiler: SynorCompiler): Promise<void> {
  console.log('=== Contract Compilation ===');

  // In production, load from file:
  // const wasm = fs.readFileSync('my_contract.wasm');

  // For demonstration, create a minimal WASM module
  const wasm = createMinimalWasm();

  const result = await compiler.compile(wasm, {
    optimizationLevel: OptimizationLevel.Size,
    useWasmOpt: true,
    validate: true,
    extractMetadata: true,
    generateAbi: true,
    stripOptions: {
      stripDebug: true,
      stripProducers: true,
      stripNames: true,
      stripCustom: true,
      stripUnused: true,
      preserveSections: [],
    },
  });

  console.log('Compilation result:');
  console.log(`  Contract ID: ${result.contractId}`);
  console.log(`  Code hash: ${result.codeHash}`);
  console.log(`  Original size: ${result.originalSize} bytes`);
  console.log(`  Optimized size: ${result.optimizedSize} bytes`);
  console.log(`  Size reduction: ${result.sizeReduction.toFixed(1)}%`);
  console.log(`  Estimated deploy gas: ${result.estimatedDeployGas}`);

  if (result.metadata) {
    console.log('\nMetadata:');
    console.log(`  Name: ${result.metadata.name}`);
    console.log(`  Version: ${result.metadata.version}`);
    console.log(`  SDK Version: ${result.metadata.sdkVersion}`);
  }

  if (result.abi) {
    console.log('\nABI:');
    console.log(`  Functions: ${result.abi.functions?.length || 0}`);
    console.log(`  Events: ${result.abi.events?.length || 0}`);
    console.log(`  Errors: ${result.abi.errors?.length || 0}`);
  }

  console.log('');
}

/**
 * Development vs Production compilation modes
 */
async function compilationModesExample(compiler: SynorCompiler): Promise<void> {
  console.log('=== Compilation Modes ===');

  const wasm = createMinimalWasm();

  // Development mode: fast compilation, debugging support
  console.log('Development mode:');
  const devResult = await compiler.contracts.compileDev(wasm);
  console.log(`  Size: ${devResult.optimizedSize} bytes`);
  console.log(`  Optimization: none`);

  // Production mode: maximum optimization
  console.log('\nProduction mode:');
  const prodResult = await compiler.contracts.compileProduction(wasm);
  console.log(`  Size: ${prodResult.optimizedSize} bytes`);
  console.log(`  Optimization: aggressive`);
  console.log(`  Size savings: ${(devResult.optimizedSize - prodResult.optimizedSize)} bytes`);

  // Custom optimization levels
  console.log('\nOptimization levels:');
  const levels = [
    OptimizationLevel.None,
    OptimizationLevel.Basic,
    OptimizationLevel.Size,
    OptimizationLevel.Aggressive,
  ];

  for (const level of levels) {
    const result = await compiler.compile(wasm, { optimizationLevel: level });
    console.log(`  ${level}: ${result.optimizedSize} bytes`);
  }

  console.log('');
}

/**
 * ABI extraction and encoding
 */
async function abiExample(compiler: SynorCompiler): Promise<void> {
  console.log('=== ABI Operations ===');

  const wasm = createMinimalWasm();

  // Extract ABI from WASM
  const abi = await compiler.abi.extract(wasm);
  console.log(`Contract: ${abi.name}`);
  console.log(`Version: ${abi.version}`);

  // List functions
  if (abi.functions && abi.functions.length > 0) {
    console.log('\nFunctions:');
    for (const func of abi.functions) {
      const inputs = func.inputs?.map(i => `${i.name}: ${i.type.typeName}`).join(', ') || '';
      const outputs = func.outputs?.map(o => o.type.typeName).join(', ') || 'void';
      const modifiers = [
        func.view ? 'view' : '',
        func.payable ? 'payable' : '',
      ].filter(Boolean).join(' ');
      console.log(`  ${func.name}(${inputs}) -> ${outputs} ${modifiers}`);
      console.log(`    Selector: ${func.selector}`);
    }
  }

  // List events
  if (abi.events && abi.events.length > 0) {
    console.log('\nEvents:');
    for (const event of abi.events) {
      const params = event.params?.map(p => {
        const indexed = p.indexed ? 'indexed ' : '';
        return `${indexed}${p.name}: ${p.type.typeName}`;
      }).join(', ') || '';
      console.log(`  ${event.name}(${params})`);
      console.log(`    Topic: ${event.topic}`);
    }
  }

  // Encode a function call
  if (abi.functions && abi.functions.length > 0) {
    const func = abi.functions[0];
    const encoded = await compiler.abi.encodeCall(func, ['arg1', 'arg2']);
    console.log(`\nEncoded call to ${func.name}: ${encoded}`);

    // Decode a result
    const decoded = await compiler.abi.decodeResult(func, encoded);
    console.log(`Decoded result: ${JSON.stringify(decoded)}`);
  }

  console.log('');
}

/**
 * Contract analysis
 */
async function analysisExample(compiler: SynorCompiler): Promise<void> {
  console.log('=== Contract Analysis ===');

  const wasm = createMinimalWasm();

  // Full analysis
  const analysis = await compiler.analysis.analyze(wasm);

  // Size breakdown
  if (analysis.sizeBreakdown) {
    console.log('Size breakdown:');
    console.log(`  Code: ${analysis.sizeBreakdown.code} bytes`);
    console.log(`  Data: ${analysis.sizeBreakdown.data} bytes`);
    console.log(`  Functions: ${analysis.sizeBreakdown.functions} bytes`);
    console.log(`  Memory: ${analysis.sizeBreakdown.memory} bytes`);
    console.log(`  Exports: ${analysis.sizeBreakdown.exports} bytes`);
    console.log(`  Imports: ${analysis.sizeBreakdown.imports} bytes`);
    console.log(`  Total: ${analysis.sizeBreakdown.total} bytes`);
  }

  // Function analysis
  if (analysis.functions && analysis.functions.length > 0) {
    console.log('\nFunction analysis:');
    for (const func of analysis.functions.slice(0, 5)) {
      console.log(`  ${func.name}:`);
      console.log(`    Size: ${func.size} bytes`);
      console.log(`    Instructions: ${func.instructionCount}`);
      console.log(`    Locals: ${func.localCount}`);
      console.log(`    Exported: ${func.exported}`);
      console.log(`    Estimated gas: ${func.estimatedGas}`);
    }
  }

  // Import analysis
  if (analysis.imports && analysis.imports.length > 0) {
    console.log('\nImports:');
    for (const imp of analysis.imports) {
      console.log(`  ${imp.module}.${imp.name} (${imp.kind})`);
    }
  }

  // Gas analysis
  if (analysis.gasAnalysis) {
    console.log('\nGas analysis:');
    console.log(`  Deployment: ${analysis.gasAnalysis.deploymentGas}`);
    console.log(`  Memory init: ${analysis.gasAnalysis.memoryInitGas}`);
    console.log(`  Data section: ${analysis.gasAnalysis.dataSectionGas}`);
  }

  // Extract metadata
  const metadata = await compiler.analysis.extractMetadata(wasm);
  console.log('\nContract metadata:');
  console.log(`  Name: ${metadata.name}`);
  console.log(`  Version: ${metadata.version}`);
  console.log(`  Build timestamp: ${metadata.buildTimestamp}`);

  // Estimate deployment gas
  const gas = await compiler.analysis.estimateDeployGas(wasm);
  console.log(`\nEstimated deployment gas: ${gas}`);

  console.log('');
}

/**
 * Contract validation
 */
async function validationExample(compiler: SynorCompiler): Promise<void> {
  console.log('=== Contract Validation ===');

  const wasm = createMinimalWasm();

  // Full validation
  const result = await compiler.validation.validate(wasm);
  console.log(`Valid: ${result.valid}`);
  console.log(`Exports: ${result.exportCount}`);
  console.log(`Imports: ${result.importCount}`);
  console.log(`Functions: ${result.functionCount}`);
  console.log(`Memory pages: ${result.memoryPages}`);

  if (result.errors && result.errors.length > 0) {
    console.log('\nValidation errors:');
    for (const error of result.errors) {
      console.log(`  [${error.code}] ${error.message}`);
      if (error.location) {
        console.log(`    at ${error.location}`);
      }
    }
  }

  if (result.warnings && result.warnings.length > 0) {
    console.log('\nWarnings:');
    for (const warning of result.warnings) {
      console.log(`  ${warning}`);
    }
  }

  // Quick validation
  const isValid = await compiler.validation.isValid(wasm);
  console.log(`\nQuick validation: ${isValid}`);

  // Get validation errors only
  const errors = await compiler.validation.getErrors(wasm);
  console.log(`Error count: ${errors.length}`);

  // Validate required exports
  const hasRequiredExports = await compiler.validation.validateExports(
    wasm,
    ['init', 'execute', 'query']
  );
  console.log(`Has required exports: ${hasRequiredExports}`);

  // Validate memory constraints
  const memoryValid = await compiler.validation.validateMemory(wasm, 16);
  console.log(`Memory within 16 pages: ${memoryValid}`);

  console.log('');
}

/**
 * Security scanning
 */
async function securityExample(compiler: SynorCompiler): Promise<void> {
  console.log('=== Security Scanning ===');

  const wasm = createMinimalWasm();

  const security = await compiler.analysis.securityScan(wasm);

  console.log(`Security score: ${security.score}/100`);

  if (security.issues && security.issues.length > 0) {
    console.log('\nSecurity issues:');
    for (const issue of security.issues) {
      const severityIcon = {
        'critical': '🔴',
        'high': '🟠',
        'medium': '🟡',
        'low': '🟢',
      }[issue.severity] || '⚪';

      console.log(`${severityIcon} [${issue.severity.toUpperCase()}] ${issue.type}`);
      console.log(`   ${issue.description}`);
      if (issue.location) {
        console.log(`   at ${issue.location}`);
      }
    }
  } else {
    console.log('No security issues found!');
  }

  if (security.recommendations && security.recommendations.length > 0) {
    console.log('\nRecommendations:');
    for (const rec of security.recommendations) {
      console.log(`  • ${rec}`);
    }
  }

  console.log('');
}

/**
 * Create a minimal valid WASM module for testing
 */
function createMinimalWasm(): Buffer {
  // Minimal WASM module with magic number and version
  return Buffer.from([
    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,
  ]);
}

// Run examples
main().catch(console.error);
