package io.synor.bridge;

import java.util.List;

/**
 * Bridge SDK Types for Java.
 */
public class Types {
    // Organizational class
}

// ==================== Enums ====================

enum ChainId { synor, ethereum, polygon, arbitrum, optimism, bsc, avalanche, solana, cosmos }
enum AssetType { native, erc20, erc721, erc1155 }
enum TransferStatus { pending, locked, confirming, minting, completed, failed, refunded }
enum TransferDirection { lock_mint, burn_unlock }

// ==================== Config ====================

class BridgeConfig {
    private final String apiKey;
    private final String endpoint;
    private final int timeoutSecs;
    private final int retries;
    private final boolean debug;

    public BridgeConfig(String apiKey) {
        this(apiKey, "https://bridge.synor.io/v1", 60, 3, false);
    }

    public BridgeConfig(String apiKey, String endpoint, int timeoutSecs, int retries, boolean debug) {
        this.apiKey = apiKey;
        this.endpoint = endpoint;
        this.timeoutSecs = timeoutSecs;
        this.retries = retries;
        this.debug = debug;
    }

    public String getApiKey() { return apiKey; }
    public String getEndpoint() { return endpoint; }
    public int getTimeoutSecs() { return timeoutSecs; }
    public int getRetries() { return retries; }
    public boolean isDebug() { return debug; }
}

// ==================== Chain & Asset Types ====================

class NativeCurrency {
    private String name;
    private String symbol;
    private int decimals;

    public String getName() { return name; }
    public String getSymbol() { return symbol; }
    public int getDecimals() { return decimals; }
}

class Chain {
    private ChainId id;
    private String name;
    private long chainId;
    private String rpcUrl;
    private String explorerUrl;
    private NativeCurrency nativeCurrency;
    private int confirmations;
    private int estimatedBlockTime;
    private boolean supported;

    public ChainId getId() { return id; }
    public String getName() { return name; }
    public long getChainId() { return chainId; }
    public String getRpcUrl() { return rpcUrl; }
    public String getExplorerUrl() { return explorerUrl; }
    public NativeCurrency getNativeCurrency() { return nativeCurrency; }
    public int getConfirmations() { return confirmations; }
    public int getEstimatedBlockTime() { return estimatedBlockTime; }
    public boolean isSupported() { return supported; }
}

class Asset {
    private String id;
    private String symbol;
    private String name;
    private AssetType type;
    private ChainId chain;
    private String contractAddress;
    private int decimals;
    private String logoUrl;
    private boolean verified;

    public String getId() { return id; }
    public String getSymbol() { return symbol; }
    public String getName() { return name; }
    public AssetType getType() { return type; }
    public ChainId getChain() { return chain; }
    public String getContractAddress() { return contractAddress; }
    public int getDecimals() { return decimals; }
    public String getLogoUrl() { return logoUrl; }
    public boolean isVerified() { return verified; }
}

class WrappedAsset {
    private Asset originalAsset;
    private Asset wrappedAsset;
    private ChainId chain;
    private String bridgeContract;

    public Asset getOriginalAsset() { return originalAsset; }
    public Asset getWrappedAsset() { return wrappedAsset; }
    public ChainId getChain() { return chain; }
    public String getBridgeContract() { return bridgeContract; }
}

// ==================== Transfer Types ====================

class ValidatorSignature {
    private String validator;
    private String signature;
    private long timestamp;

    public String getValidator() { return validator; }
    public String getSignature() { return signature; }
    public long getTimestamp() { return timestamp; }
}

class LockReceipt {
    private String id;
    private String txHash;
    private ChainId sourceChain;
    private ChainId targetChain;
    private Asset asset;
    private String amount;
    private String sender;
    private String recipient;
    private long lockTimestamp;
    private int confirmations;
    private int requiredConfirmations;

    public String getId() { return id; }
    public String getTxHash() { return txHash; }
    public ChainId getSourceChain() { return sourceChain; }
    public ChainId getTargetChain() { return targetChain; }
    public Asset getAsset() { return asset; }
    public String getAmount() { return amount; }
    public String getSender() { return sender; }
    public String getRecipient() { return recipient; }
    public long getLockTimestamp() { return lockTimestamp; }
    public int getConfirmations() { return confirmations; }
    public int getRequiredConfirmations() { return requiredConfirmations; }
}

class LockProof {
    private LockReceipt lockReceipt;
    private List<String> merkleProof;
    private String blockHeader;
    private List<ValidatorSignature> signatures;

    public LockReceipt getLockReceipt() { return lockReceipt; }
    public List<String> getMerkleProof() { return merkleProof; }
    public String getBlockHeader() { return blockHeader; }
    public List<ValidatorSignature> getSignatures() { return signatures; }
}

class BurnReceipt {
    private String id;
    private String txHash;
    private ChainId sourceChain;
    private ChainId targetChain;
    private Asset wrappedAsset;
    private Asset originalAsset;
    private String amount;
    private String sender;
    private String recipient;
    private long burnTimestamp;
    private int confirmations;
    private int requiredConfirmations;

    public String getId() { return id; }
    public String getTxHash() { return txHash; }
    public ChainId getSourceChain() { return sourceChain; }
    public ChainId getTargetChain() { return targetChain; }
    public Asset getWrappedAsset() { return wrappedAsset; }
    public Asset getOriginalAsset() { return originalAsset; }
    public String getAmount() { return amount; }
    public String getSender() { return sender; }
    public String getRecipient() { return recipient; }
    public long getBurnTimestamp() { return burnTimestamp; }
    public int getConfirmations() { return confirmations; }
    public int getRequiredConfirmations() { return requiredConfirmations; }
}

class BurnProof {
    private BurnReceipt burnReceipt;
    private List<String> merkleProof;
    private String blockHeader;
    private List<ValidatorSignature> signatures;

    public BurnReceipt getBurnReceipt() { return burnReceipt; }
    public List<String> getMerkleProof() { return merkleProof; }
    public String getBlockHeader() { return blockHeader; }
    public List<ValidatorSignature> getSignatures() { return signatures; }
}

class Transfer {
    private String id;
    private TransferDirection direction;
    private TransferStatus status;
    private ChainId sourceChain;
    private ChainId targetChain;
    private Asset asset;
    private String amount;
    private String sender;
    private String recipient;
    private String sourceTxHash;
    private String targetTxHash;
    private String fee;
    private Asset feeAsset;
    private long createdAt;
    private long updatedAt;
    private Long completedAt;
    private String errorMessage;

    public String getId() { return id; }
    public TransferDirection getDirection() { return direction; }
    public TransferStatus getStatus() { return status; }
    public ChainId getSourceChain() { return sourceChain; }
    public ChainId getTargetChain() { return targetChain; }
    public Asset getAsset() { return asset; }
    public String getAmount() { return amount; }
    public String getSender() { return sender; }
    public String getRecipient() { return recipient; }
    public String getSourceTxHash() { return sourceTxHash; }
    public String getTargetTxHash() { return targetTxHash; }
    public String getFee() { return fee; }
    public Asset getFeeAsset() { return feeAsset; }
    public long getCreatedAt() { return createdAt; }
    public long getUpdatedAt() { return updatedAt; }
    public Long getCompletedAt() { return completedAt; }
    public String getErrorMessage() { return errorMessage; }
}

// ==================== Fee Types ====================

class FeeEstimate {
    private String bridgeFee;
    private String gasFeeSource;
    private String gasFeeTarget;
    private String totalFee;
    private Asset feeAsset;
    private int estimatedTime;
    private String exchangeRate;

    public String getBridgeFee() { return bridgeFee; }
    public String getGasFeeSource() { return gasFeeSource; }
    public String getGasFeeTarget() { return gasFeeTarget; }
    public String getTotalFee() { return totalFee; }
    public Asset getFeeAsset() { return feeAsset; }
    public int getEstimatedTime() { return estimatedTime; }
    public String getExchangeRate() { return exchangeRate; }
}

class ExchangeRate {
    private Asset fromAsset;
    private Asset toAsset;
    private String rate;
    private String inverseRate;
    private long lastUpdated;
    private String source;

    public Asset getFromAsset() { return fromAsset; }
    public Asset getToAsset() { return toAsset; }
    public String getRate() { return rate; }
    public String getInverseRate() { return inverseRate; }
    public long getLastUpdated() { return lastUpdated; }
    public String getSource() { return source; }
}

class SignedTransaction {
    private String txHash;
    private ChainId chain;
    private String from;
    private String to;
    private String value;
    private String data;
    private String gasLimit;
    private String gasPrice;
    private String maxFeePerGas;
    private String maxPriorityFeePerGas;
    private int nonce;
    private String signature;

    public String getTxHash() { return txHash; }
    public ChainId getChain() { return chain; }
    public String getFrom() { return from; }
    public String getTo() { return to; }
    public String getValue() { return value; }
    public String getData() { return data; }
    public String getGasLimit() { return gasLimit; }
    public String getGasPrice() { return gasPrice; }
    public String getMaxFeePerGas() { return maxFeePerGas; }
    public String getMaxPriorityFeePerGas() { return maxPriorityFeePerGas; }
    public int getNonce() { return nonce; }
    public String getSignature() { return signature; }
}

// ==================== Options & Filter ====================

class LockOptions {
    private String recipient;
    private Long deadline;
    private Double slippage;

    public String getRecipient() { return recipient; }
    public Long getDeadline() { return deadline; }
    public Double getSlippage() { return slippage; }
    public void setRecipient(String recipient) { this.recipient = recipient; }
    public void setDeadline(Long deadline) { this.deadline = deadline; }
    public void setSlippage(Double slippage) { this.slippage = slippage; }
}

class MintOptions {
    private String gasLimit;
    private String maxFeePerGas;
    private String maxPriorityFeePerGas;

    public String getGasLimit() { return gasLimit; }
    public String getMaxFeePerGas() { return maxFeePerGas; }
    public String getMaxPriorityFeePerGas() { return maxPriorityFeePerGas; }
    public void setGasLimit(String gasLimit) { this.gasLimit = gasLimit; }
    public void setMaxFeePerGas(String maxFeePerGas) { this.maxFeePerGas = maxFeePerGas; }
    public void setMaxPriorityFeePerGas(String v) { this.maxPriorityFeePerGas = v; }
}

class BurnOptions {
    private String recipient;
    private Long deadline;

    public String getRecipient() { return recipient; }
    public Long getDeadline() { return deadline; }
    public void setRecipient(String recipient) { this.recipient = recipient; }
    public void setDeadline(Long deadline) { this.deadline = deadline; }
}

class UnlockOptions {
    private String gasLimit;
    private String gasPrice;

    public String getGasLimit() { return gasLimit; }
    public String getGasPrice() { return gasPrice; }
    public void setGasLimit(String gasLimit) { this.gasLimit = gasLimit; }
    public void setGasPrice(String gasPrice) { this.gasPrice = gasPrice; }
}

class TransferFilter {
    private TransferStatus status;
    private ChainId sourceChain;
    private ChainId targetChain;
    private String asset;
    private String sender;
    private String recipient;
    private Integer limit;
    private Integer offset;

    public TransferStatus getStatus() { return status; }
    public ChainId getSourceChain() { return sourceChain; }
    public ChainId getTargetChain() { return targetChain; }
    public String getAsset() { return asset; }
    public String getSender() { return sender; }
    public String getRecipient() { return recipient; }
    public Integer getLimit() { return limit; }
    public Integer getOffset() { return offset; }

    public void setStatus(TransferStatus status) { this.status = status; }
    public void setSourceChain(ChainId sourceChain) { this.sourceChain = sourceChain; }
    public void setTargetChain(ChainId targetChain) { this.targetChain = targetChain; }
    public void setAsset(String asset) { this.asset = asset; }
    public void setSender(String sender) { this.sender = sender; }
    public void setRecipient(String recipient) { this.recipient = recipient; }
    public void setLimit(Integer limit) { this.limit = limit; }
    public void setOffset(Integer offset) { this.offset = offset; }
}

// ==================== Error ====================

class BridgeException extends RuntimeException {
    private final String code;
    private final int statusCode;

    public BridgeException(String message) {
        super(message);
        this.code = null;
        this.statusCode = 0;
    }

    public BridgeException(String message, String code, int statusCode) {
        super(message);
        this.code = code;
        this.statusCode = statusCode;
    }

    public String getCode() { return code; }
    public int getStatusCode() { return statusCode; }
}
