// Synor ZK SDK Types for JavaScript/TypeScript
//
// Zero-Knowledge proof systems for ZK-Rollups and privacy.

/**
 * Proof system backends
 */
export enum ProofSystem {
  /** Groth16 - smallest proofs (~192 bytes), fastest verification */
  Groth16 = 'groth16',
  /** PLONK - universal trusted setup, medium proofs (~512 bytes) */
  Plonk = 'plonk',
  /** STARK - no trusted setup, largest proofs (~50KB) */
  Stark = 'stark',
}

/**
 * Circuit types for different operations
 */
export enum CircuitType {
  /** Single transfer between accounts */
  Transfer = 'transfer',
  /** Batch of multiple transfers */
  Batch = 'batch',
  /** Deposit from L1 to L2 */
  Deposit = 'deposit',
  /** Withdrawal from L2 to L1 */
  Withdraw = 'withdraw',
}

/**
 * Rollup state
 */
export enum RollupState {
  /** Rollup is accepting transactions */
  Active = 'active',
  /** Rollup is paused */
  Paused = 'paused',
  /** Rollup is finalizing */
  Finalizing = 'finalizing',
  /** Rollup has been finalized */
  Finalized = 'finalized',
}

/**
 * Proof status
 */
export enum ProofStatus {
  /** Proof is being generated */
  Generating = 'generating',
  /** Proof generation completed */
  Completed = 'completed',
  /** Proof generation failed */
  Failed = 'failed',
  /** Proof has been verified */
  Verified = 'verified',
}

/**
 * Zero-knowledge proof
 */
export interface Proof {
  /** Unique proof identifier */
  id: string;
  /** Proof system used */
  system: ProofSystem;
  /** Circuit type */
  circuitType: CircuitType;
  /** Serialized proof data (base64) */
  data: string;
  /** Public inputs (base64 encoded) */
  publicInputs: string[];
  /** Proof size in bytes */
  size: number;
  /** Generation time in milliseconds */
  generationTimeMs: number;
  /** Timestamp when proof was created */
  createdAt: number;
}

/**
 * Verification key for a circuit
 */
export interface VerificationKey {
  /** Circuit identifier */
  circuitId: string;
  /** Circuit type */
  circuitType: CircuitType;
  /** Proof system */
  system: ProofSystem;
  /** Serialized verification key (base64) */
  data: string;
  /** Key size in bytes */
  size: number;
}

/**
 * Proving key for generating proofs
 */
export interface ProvingKey {
  /** Circuit identifier */
  circuitId: string;
  /** Circuit type */
  circuitType: CircuitType;
  /** Proof system */
  system: ProofSystem;
  /** Serialized proving key (base64) */
  data: string;
  /** Key size in bytes */
  size: number;
}

/**
 * Circuit configuration
 */
export interface CircuitConfig {
  /** Circuit type */
  type: CircuitType;
  /** Maximum batch size for batch circuits */
  maxBatchSize?: number;
  /** State tree depth */
  treeDepth?: number;
  /** Whether to verify signatures in circuit */
  verifySignatures?: boolean;
  /** Custom constraints */
  customConstraints?: Record<string, unknown>;
}

/**
 * State tree node
 */
export interface StateNode {
  /** Node hash */
  hash: string;
  /** Left child hash (if internal node) */
  left?: string;
  /** Right child hash (if internal node) */
  right?: string;
  /** Account data (if leaf node) */
  account?: AccountState;
}

/**
 * Account state in the rollup
 */
export interface AccountState {
  /** Account address */
  address: string;
  /** Account balance */
  balance: string;
  /** Account nonce */
  nonce: number;
  /** Public key hash */
  pubkeyHash: string;
}

/**
 * Transfer operation
 */
export interface Transfer {
  /** Sender address */
  from: string;
  /** Recipient address */
  to: string;
  /** Amount to transfer */
  amount: string;
  /** Fee */
  fee: string;
  /** Nonce */
  nonce: number;
  /** Signature */
  signature?: string;
}

/**
 * Deposit operation (L1 -> L2)
 */
export interface Deposit {
  /** L1 transaction hash */
  l1TxHash: string;
  /** Recipient address on L2 */
  recipient: string;
  /** Amount deposited */
  amount: string;
  /** Token address (or native if null) */
  token?: string;
}

/**
 * Withdrawal operation (L2 -> L1)
 */
export interface Withdrawal {
  /** Sender address on L2 */
  sender: string;
  /** Recipient address on L1 */
  recipient: string;
  /** Amount to withdraw */
  amount: string;
  /** Token address (or native if null) */
  token?: string;
  /** Nonce */
  nonce: number;
  /** Signature */
  signature?: string;
}

/**
 * Rollup batch
 */
export interface Batch {
  /** Batch number */
  batchNumber: number;
  /** Previous state root */
  prevStateRoot: string;
  /** New state root after batch */
  newStateRoot: string;
  /** Transfers in this batch */
  transfers: Transfer[];
  /** Deposits in this batch */
  deposits: Deposit[];
  /** Withdrawals in this batch */
  withdrawals: Withdrawal[];
  /** Batch proof (once generated) */
  proof?: Proof;
  /** Timestamp */
  timestamp: number;
}

/**
 * Rollup statistics
 */
export interface RollupStats {
  /** Current batch number */
  currentBatch: number;
  /** Total transactions processed */
  totalTransactions: number;
  /** Total proofs generated */
  totalProofs: number;
  /** Average proof generation time (ms) */
  avgProofTimeMs: number;
  /** Current state root */
  stateRoot: string;
  /** Number of accounts */
  accountCount: number;
  /** Total value locked */
  tvl: string;
}

/**
 * Proof generation request
 */
export interface ProofRequest {
  /** Circuit type */
  circuitType: CircuitType;
  /** Public inputs */
  publicInputs: string[];
  /** Private inputs (witness) */
  privateInputs: string[];
  /** Proof system to use */
  system?: ProofSystem;
}

/**
 * Proof verification result
 */
export interface VerificationResult {
  /** Whether the proof is valid */
  valid: boolean;
  /** Verification time in milliseconds */
  verificationTimeMs: number;
  /** Error message if invalid */
  error?: string;
}

/**
 * Setup ceremony contribution
 */
export interface CeremonyContribution {
  /** Contributor identifier */
  contributorId: string;
  /** Contribution hash */
  hash: string;
  /** Timestamp */
  timestamp: number;
  /** Verification status */
  verified: boolean;
}

/**
 * Trusted setup ceremony
 */
export interface TrustedSetup {
  /** Ceremony identifier */
  id: string;
  /** Circuit type */
  circuitType: CircuitType;
  /** Proof system */
  system: ProofSystem;
  /** Number of contributions */
  contributionCount: number;
  /** Latest contribution hash */
  latestHash: string;
  /** Whether ceremony is complete */
  complete: boolean;
  /** Contributions */
  contributions: CeremonyContribution[];
}

/**
 * Merkle proof for state inclusion
 */
export interface MerkleProof {
  /** Leaf value */
  leaf: string;
  /** Path from leaf to root (sibling hashes) */
  path: string[];
  /** Path indices (0 = left, 1 = right) */
  indices: number[];
  /** Root hash */
  root: string;
}

/**
 * ZK SDK configuration
 */
export interface ZkConfig {
  /** API key for authentication */
  apiKey: string;
  /** API endpoint */
  endpoint?: string;
  /** WebSocket endpoint for subscriptions */
  wsEndpoint?: string;
  /** Request timeout in milliseconds */
  timeout?: number;
  /** Number of retries for failed requests */
  retries?: number;
  /** Default proof system */
  defaultProofSystem?: ProofSystem;
  /** Enable debug logging */
  debug?: boolean;
}

/**
 * ZK SDK error
 */
export class ZkError extends Error {
  constructor(
    message: string,
    public readonly code?: string,
    public readonly status?: number
  ) {
    super(message);
    this.name = 'ZkError';
  }
}

/**
 * Default configuration values
 */
export const DEFAULT_CONFIG = {
  endpoint: 'https://zk.synor.io/v1',
  wsEndpoint: 'wss://zk.synor.io/v1/ws',
  timeout: 60000, // ZK proofs can take longer
  retries: 3,
  defaultProofSystem: ProofSystem.Groth16,
  debug: false,
} as const;

/**
 * Proof system characteristics
 */
export const PROOF_SYSTEM_INFO = {
  [ProofSystem.Groth16]: {
    name: 'Groth16',
    proofSize: 192,
    verificationTimeMs: 10,
    trustedSetup: true,
    universal: false,
  },
  [ProofSystem.Plonk]: {
    name: 'PLONK',
    proofSize: 512,
    verificationTimeMs: 15,
    trustedSetup: true,
    universal: true,
  },
  [ProofSystem.Stark]: {
    name: 'STARK',
    proofSize: 50000,
    verificationTimeMs: 30,
    trustedSetup: false,
    universal: true,
  },
} as const;

/**
 * Constants
 */
export const MAX_BATCH_SIZE = 1000;
export const STATE_TREE_DEPTH = 32;
export const PROOF_EXPIRY_BLOCKS = 100;
