/**
 * Synor Compiler SDK Types
 *
 * Smart contract compilation, optimization, and ABI generation.
 */

/* ============================================================================
 * Enumerations
 * ============================================================================ */

/** Optimization level for WASM compilation */
export enum OptimizationLevel {
  /** No optimization */
  None = 'none',
  /** Basic optimizations (stripping only) */
  Basic = 'basic',
  /** Optimize for size (-Os equivalent) */
  Size = 'size',
  /** Aggressive optimization (-O3 -Os equivalent) */
  Aggressive = 'aggressive',
}

/* ============================================================================
 * Configuration Types
 * ============================================================================ */

/** Options for stripping WASM sections */
export interface StripOptions {
  /** Strip debug sections (.debug_*) */
  stripDebug: boolean;
  /** Strip producer sections */
  stripProducers: boolean;
  /** Strip name sections */
  stripNames: boolean;
  /** Strip custom sections (all non-standard sections) */
  stripCustom: boolean;
  /** Specific custom sections to preserve */
  preserveSections: string[];
  /** Strip unused functions */
  stripUnused: boolean;
}

/** Compiler configuration */
export interface CompilerConfig {
  /** API key for authentication */
  apiKey: string;
  /** Compiler service endpoint */
  endpoint?: string;
  /** Request timeout in milliseconds */
  timeout?: number;
  /** Maximum retry attempts */
  retries?: number;
  /** Enable debug logging */
  debug?: boolean;
  /** Optimization level */
  optimizationLevel?: OptimizationLevel;
  /** Strip options */
  stripOptions?: Partial<StripOptions>;
  /** Maximum contract size in bytes */
  maxContractSize?: number;
  /** Whether to use wasm-opt */
  useWasmOpt?: boolean;
  /** Whether to validate against VM requirements */
  validate?: boolean;
  /** Whether to extract metadata */
  extractMetadata?: boolean;
  /** Whether to generate ABI */
  generateAbi?: boolean;
}

/* ============================================================================
 * Compilation Types
 * ============================================================================ */

/** Compilation request */
export interface CompilationRequest {
  /** WASM bytecode (base64 encoded) */
  wasm: string;
  /** Optimization level */
  optimizationLevel?: OptimizationLevel;
  /** Strip options */
  stripOptions?: Partial<StripOptions>;
  /** Whether to use wasm-opt */
  useWasmOpt?: boolean;
  /** Whether to validate */
  validate?: boolean;
  /** Whether to extract metadata */
  extractMetadata?: boolean;
  /** Whether to generate ABI */
  generateAbi?: boolean;
}

/** Compilation result */
export interface CompilationResult {
  /** Contract ID (hash of optimized code) */
  contractId: string;
  /** Optimized WASM bytecode (base64 encoded) */
  code: string;
  /** Code hash */
  codeHash: string;
  /** Original code size in bytes */
  originalSize: number;
  /** Optimized code size in bytes */
  optimizedSize: number;
  /** Size reduction percentage */
  sizeReduction: number;
  /** Contract metadata */
  metadata?: ContractMetadata;
  /** Contract ABI */
  abi?: ContractAbi;
  /** Estimated deployment gas */
  estimatedDeployGas: number;
  /** Validation result */
  validation: ValidationResult;
  /** Compilation warnings */
  warnings: string[];
}

/** Validation result */
export interface ValidationResult {
  /** Whether validation passed */
  valid: boolean;
  /** Validation errors */
  errors: ValidationError[];
  /** Validation warnings */
  warnings: string[];
  /** Number of exports */
  exportCount: number;
  /** Number of imports */
  importCount: number;
  /** Number of functions */
  functionCount: number;
  /** Memory pages (min, max) */
  memoryPages: [number, number | null];
}

/** Validation error */
export interface ValidationError {
  /** Error code */
  code: string;
  /** Error message */
  message: string;
  /** Location in WASM (if applicable) */
  location?: string;
}

/* ============================================================================
 * Metadata Types
 * ============================================================================ */

/** Contract metadata */
export interface ContractMetadata {
  /** Contract name */
  name?: string;
  /** Contract version */
  version?: string;
  /** Contract authors */
  authors: string[];
  /** Contract description */
  description?: string;
  /** Contract license */
  license?: string;
  /** Repository URL */
  repository?: string;
  /** Build timestamp */
  buildTimestamp?: number;
  /** Rust version used */
  rustVersion?: string;
  /** Synor SDK version */
  sdkVersion?: string;
  /** Custom metadata */
  custom: Record<string, string>;
}

/* ============================================================================
 * ABI Types
 * ============================================================================ */

/** Contract ABI (Application Binary Interface) */
export interface ContractAbi {
  /** Contract name */
  name: string;
  /** ABI version */
  version: string;
  /** Functions */
  functions: FunctionAbi[];
  /** Events */
  events: EventAbi[];
  /** Errors */
  errors: ErrorAbi[];
}

/** Function ABI */
export interface FunctionAbi {
  /** Function name */
  name: string;
  /** 4-byte selector (hex) */
  selector: string;
  /** Input parameters */
  inputs: ParamAbi[];
  /** Output parameters */
  outputs: ParamAbi[];
  /** Whether function is read-only (view) */
  view: boolean;
  /** Whether function is payable */
  payable: boolean;
  /** Function documentation */
  doc?: string;
}

/** Event ABI */
export interface EventAbi {
  /** Event name */
  name: string;
  /** Event topic (hex) */
  topic: string;
  /** Event parameters */
  params: ParamAbi[];
  /** Event documentation */
  doc?: string;
}

/** Error ABI */
export interface ErrorAbi {
  /** Error name */
  name: string;
  /** Error selector (hex) */
  selector: string;
  /** Error parameters */
  params: ParamAbi[];
  /** Error documentation */
  doc?: string;
}

/** Parameter ABI */
export interface ParamAbi {
  /** Parameter name */
  name: string;
  /** Parameter type */
  type: TypeInfo;
  /** Whether parameter is indexed (for events) */
  indexed: boolean;
}

/** Type information */
export type TypeInfo =
  | { kind: 'u8' }
  | { kind: 'u16' }
  | { kind: 'u32' }
  | { kind: 'u64' }
  | { kind: 'u128' }
  | { kind: 'i8' }
  | { kind: 'i16' }
  | { kind: 'i32' }
  | { kind: 'i64' }
  | { kind: 'i128' }
  | { kind: 'bool' }
  | { kind: 'string' }
  | { kind: 'bytes' }
  | { kind: 'fixedBytes'; size: number }
  | { kind: 'address' }
  | { kind: 'hash256' }
  | { kind: 'array'; element: TypeInfo }
  | { kind: 'fixedArray'; element: TypeInfo; size: number }
  | { kind: 'option'; inner: TypeInfo }
  | { kind: 'tuple'; elements: TypeInfo[] }
  | { kind: 'struct'; name: string; fields: Array<{ name: string; type: TypeInfo }> }
  | { kind: 'unknown'; name: string };

/* ============================================================================
 * Source Map Types
 * ============================================================================ */

/** Source map for debugging */
export interface SourceMap {
  /** Source file name */
  file: string;
  /** Mappings */
  mappings: SourceMapping[];
}

/** Source mapping entry */
export interface SourceMapping {
  /** WASM offset */
  wasmOffset: number;
  /** Source line */
  line: number;
  /** Source column */
  column: number;
  /** Function name */
  function?: string;
}

/* ============================================================================
 * Analysis Types
 * ============================================================================ */

/** Contract analysis result */
export interface ContractAnalysis {
  /** Code size breakdown */
  sizeBreakdown: SizeBreakdown;
  /** Function analysis */
  functions: FunctionAnalysis[];
  /** Import analysis */
  imports: ImportAnalysis[];
  /** Security analysis */
  security: SecurityAnalysis;
  /** Gas analysis */
  gasAnalysis: GasAnalysis;
}

/** Size breakdown */
export interface SizeBreakdown {
  /** Code section size */
  code: number;
  /** Data section size */
  data: number;
  /** Type section size */
  types: number;
  /** Function section size */
  functions: number;
  /** Memory section size */
  memory: number;
  /** Table section size */
  table: number;
  /** Export section size */
  exports: number;
  /** Import section size */
  imports: number;
  /** Custom sections size */
  custom: number;
  /** Total size */
  total: number;
}

/** Function analysis */
export interface FunctionAnalysis {
  /** Function name or index */
  name: string;
  /** Function size in bytes */
  size: number;
  /** Instruction count */
  instructionCount: number;
  /** Local variable count */
  localCount: number;
  /** Is exported */
  exported: boolean;
  /** Estimated gas cost */
  estimatedGas: number;
}

/** Import analysis */
export interface ImportAnalysis {
  /** Module name */
  module: string;
  /** Import name */
  name: string;
  /** Import kind */
  kind: 'function' | 'memory' | 'table' | 'global';
  /** Type signature (for functions) */
  signature?: string;
}

/** Security analysis */
export interface SecurityAnalysis {
  /** Security score (0-100) */
  score: number;
  /** Issues found */
  issues: SecurityIssue[];
  /** Recommendations */
  recommendations: string[];
}

/** Security issue */
export interface SecurityIssue {
  /** Severity level */
  severity: 'low' | 'medium' | 'high' | 'critical';
  /** Issue type */
  type: string;
  /** Issue description */
  description: string;
  /** Location in code */
  location?: string;
}

/** Gas analysis */
export interface GasAnalysis {
  /** Base deployment gas */
  deploymentGas: number;
  /** Per-function gas estimates */
  functionGas: Record<string, number>;
  /** Memory initialization gas */
  memoryInitGas: number;
  /** Data section gas */
  dataSectionGas: number;
}

/* ============================================================================
 * Error Types
 * ============================================================================ */

/** Compiler error codes */
export enum CompilerErrorCode {
  /** WASM parsing error */
  ParseError = 'PARSE_ERROR',
  /** Validation error */
  ValidationError = 'VALIDATION_ERROR',
  /** Optimization error */
  OptimizationError = 'OPTIMIZATION_ERROR',
  /** Contract too large */
  ContractTooLarge = 'CONTRACT_TOO_LARGE',
  /** Missing required export */
  MissingExport = 'MISSING_EXPORT',
  /** Invalid export signature */
  InvalidExportSignature = 'INVALID_EXPORT_SIGNATURE',
  /** IO error */
  IoError = 'IO_ERROR',
  /** Encoding error */
  EncodingError = 'ENCODING_ERROR',
  /** External tool error */
  ExternalToolError = 'EXTERNAL_TOOL_ERROR',
  /** Network error */
  NetworkError = 'NETWORK_ERROR',
  /** Authentication error */
  AuthError = 'AUTH_ERROR',
  /** Client closed */
  ClientClosed = 'CLIENT_CLOSED',
}

/** Compiler error */
export class CompilerError extends Error {
  constructor(
    message: string,
    public readonly code?: string,
    public readonly httpStatus?: number,
    public readonly details?: Record<string, unknown>
  ) {
    super(message);
    this.name = 'CompilerError';
  }
}

/* ============================================================================
 * Constants
 * ============================================================================ */

/** Maximum contract size (256 KB) */
export const MAX_CONTRACT_SIZE = 256 * 1024;

/** Maximum memory pages */
export const MAX_MEMORY_PAGES = 16;

/** Default strip options */
export const DEFAULT_STRIP_OPTIONS: StripOptions = {
  stripDebug: true,
  stripProducers: true,
  stripNames: true,
  stripCustom: true,
  preserveSections: [],
  stripUnused: true,
};

/** Default compiler config */
export const DEFAULT_COMPILER_CONFIG: Partial<CompilerConfig> = {
  endpoint: 'https://compiler.synor.io/v1',
  timeout: 60000,
  retries: 3,
  debug: false,
  optimizationLevel: OptimizationLevel.Size,
  useWasmOpt: true,
  validate: true,
  extractMetadata: true,
  generateAbi: true,
};

/* ============================================================================
 * Utility Types
 * ============================================================================ */

/** Get type name from TypeInfo */
export function getTypeName(type: TypeInfo): string {
  switch (type.kind) {
    case 'u8':
    case 'u16':
    case 'u32':
    case 'u64':
    case 'u128':
    case 'i8':
    case 'i16':
    case 'i32':
    case 'i64':
    case 'i128':
    case 'bool':
    case 'string':
    case 'bytes':
    case 'address':
    case 'hash256':
      return type.kind;
    case 'fixedBytes':
      return `bytes${type.size}`;
    case 'array':
      return `${getTypeName(type.element)}[]`;
    case 'fixedArray':
      return `${getTypeName(type.element)}[${type.size}]`;
    case 'option':
      return `${getTypeName(type.inner)}?`;
    case 'tuple':
      return `(${type.elements.map(getTypeName).join(', ')})`;
    case 'struct':
      return type.name;
    case 'unknown':
      return type.name;
  }
}
