# frozen_string_literal: true

module SynorPrivacy
  # Configuration for the Privacy SDK.
  class Config
    attr_accessor :api_key, :endpoint, :timeout, :retries

    def initialize(api_key:, endpoint: "https://privacy.synor.io", timeout: 30, retries: 3)
      @api_key = api_key
      @endpoint = endpoint
      @timeout = timeout
      @retries = retries
    end
  end

  # Confidential transaction input.
  class ConfidentialTxInput
    attr_accessor :commitment, :blinding_factor, :value, :key_image

    def initialize(commitment:, blinding_factor:, value:, key_image: nil)
      @commitment = commitment
      @blinding_factor = blinding_factor
      @value = value
      @key_image = key_image
    end

    def to_h
      h = {
        commitment: @commitment,
        blinding_factor: @blinding_factor,
        value: @value
      }
      h[:key_image] = @key_image if @key_image
      h
    end
  end

  # Confidential transaction output.
  class ConfidentialTxOutput
    attr_accessor :commitment, :blinding_factor, :value, :recipient_public_key, :range_proof

    def initialize(commitment:, blinding_factor:, value:, recipient_public_key:, range_proof: nil)
      @commitment = commitment
      @blinding_factor = blinding_factor
      @value = value
      @recipient_public_key = recipient_public_key
      @range_proof = range_proof
    end

    def to_h
      h = {
        commitment: @commitment,
        blinding_factor: @blinding_factor,
        value: @value,
        recipient_public_key: @recipient_public_key
      }
      h[:range_proof] = @range_proof if @range_proof
      h
    end
  end

  # Confidential transaction.
  class ConfidentialTransaction
    attr_accessor :id, :inputs, :outputs, :fee, :excess, :excess_sig, :kernel_offset

    def initialize(id:, inputs:, outputs:, fee:, excess:, excess_sig:, kernel_offset: nil)
      @id = id
      @inputs = inputs
      @outputs = outputs
      @fee = fee
      @excess = excess
      @excess_sig = excess_sig
      @kernel_offset = kernel_offset
    end

    def to_h
      h = {
        id: @id,
        inputs: @inputs.map(&:to_h),
        outputs: @outputs.map(&:to_h),
        fee: @fee,
        excess: @excess,
        excess_sig: @excess_sig
      }
      h[:kernel_offset] = @kernel_offset if @kernel_offset
      h
    end
  end

  # Pedersen commitment.
  class Commitment
    attr_accessor :commitment, :blinding_factor

    def initialize(commitment:, blinding_factor:)
      @commitment = commitment
      @blinding_factor = blinding_factor
    end

    def to_h
      { commitment: @commitment, blinding_factor: @blinding_factor }
    end
  end

  # Bulletproof range proof.
  class RangeProof
    attr_accessor :proof, :commitment, :min_value, :max_value

    def initialize(proof:, commitment:, min_value:, max_value:)
      @proof = proof
      @commitment = commitment
      @min_value = min_value
      @max_value = max_value
    end

    def to_h
      {
        proof: @proof,
        commitment: @commitment,
        min_value: @min_value,
        max_value: @max_value
      }
    end
  end

  # Ring signature for anonymous signing.
  class RingSignature
    attr_accessor :c0, :s, :key_image, :ring

    def initialize(c0:, s:, key_image:, ring:)
      @c0 = c0
      @s = s
      @key_image = key_image
      @ring = ring
    end

    def to_h
      { c0: @c0, s: @s, key_image: @key_image, ring: @ring }
    end
  end

  # Stealth address key pair.
  class StealthKeyPair
    attr_accessor :spend_public_key, :spend_private_key, :view_public_key, :view_private_key

    def initialize(spend_public_key:, spend_private_key:, view_public_key:, view_private_key:)
      @spend_public_key = spend_public_key
      @spend_private_key = spend_private_key
      @view_public_key = view_public_key
      @view_private_key = view_private_key
    end
  end

  # Derived stealth address.
  class StealthAddress
    attr_accessor :address, :ephemeral_public_key, :tx_public_key

    def initialize(address:, ephemeral_public_key:, tx_public_key: nil)
      @address = address
      @ephemeral_public_key = ephemeral_public_key
      @tx_public_key = tx_public_key
    end
  end

  # Scanned stealth output.
  class StealthOutput
    attr_accessor :tx_hash, :output_index, :stealth_address, :amount, :block_height

    def initialize(tx_hash:, output_index:, stealth_address:, amount:, block_height:)
      @tx_hash = tx_hash
      @output_index = output_index
      @stealth_address = stealth_address
      @amount = amount
      @block_height = block_height
    end
  end

  # Client closed error.
  class ClientClosedError < StandardError; end

  # HTTP error.
  class HttpError < StandardError
    attr_reader :status_code, :code

    def initialize(message, status_code: nil, code: nil)
      super(message)
      @status_code = status_code
      @code = code
    end
  end
end
