namespace Synor.Sdk.Bridge;

public record BridgeConfig
{
    public required string ApiKey { get; init; }
    public string Endpoint { get; init; } = "https://bridge.synor.io/v1";
    public TimeSpan Timeout { get; init; } = TimeSpan.FromSeconds(60);
    public int Retries { get; init; } = 3;
    public bool Debug { get; init; } = false;
}

public enum ChainId { Synor, Ethereum, Polygon, Arbitrum, Optimism, Bsc, Avalanche, Solana, Cosmos }
public enum AssetType { Native, Erc20, Erc721, Erc1155 }
public enum TransferStatus { Pending, Locked, Confirming, Minting, Completed, Failed, Refunded }
public enum TransferDirection { LockMint, BurnUnlock }

public record NativeCurrency { public required string Name { get; init; } public required string Symbol { get; init; } public int Decimals { get; init; } }

public record Chain
{
    public ChainId Id { get; init; }
    public required string Name { get; init; }
    public long ChainIdNumber { get; init; }
    public required string RpcUrl { get; init; }
    public required string ExplorerUrl { get; init; }
    public required NativeCurrency NativeCurrency { get; init; }
    public int Confirmations { get; init; }
    public int EstimatedBlockTime { get; init; }
    public bool Supported { get; init; }
}

public record Asset
{
    public required string Id { get; init; }
    public required string Symbol { get; init; }
    public required string Name { get; init; }
    public AssetType Type { get; init; }
    public ChainId Chain { get; init; }
    public string? ContractAddress { get; init; }
    public int Decimals { get; init; }
    public string? LogoUrl { get; init; }
    public bool Verified { get; init; }
}

public record WrappedAsset
{
    public required Asset OriginalAsset { get; init; }
    public required Asset WrappedAssetData { get; init; }
    public ChainId Chain { get; init; }
    public required string BridgeContract { get; init; }
}

public record ValidatorSignature { public required string Validator { get; init; } public required string Signature { get; init; } public long Timestamp { get; init; } }

public record LockReceipt
{
    public required string Id { get; init; }
    public required string TxHash { get; init; }
    public ChainId SourceChain { get; init; }
    public ChainId TargetChain { get; init; }
    public required Asset Asset { get; init; }
    public required string Amount { get; init; }
    public required string Sender { get; init; }
    public required string Recipient { get; init; }
    public long LockTimestamp { get; init; }
    public int Confirmations { get; init; }
    public int RequiredConfirmations { get; init; }
}

public record LockProof
{
    public required LockReceipt LockReceipt { get; init; }
    public required List<string> MerkleProof { get; init; }
    public required string BlockHeader { get; init; }
    public required List<ValidatorSignature> Signatures { get; init; }
}

public record BurnReceipt
{
    public required string Id { get; init; }
    public required string TxHash { get; init; }
    public ChainId SourceChain { get; init; }
    public ChainId TargetChain { get; init; }
    public required Asset WrappedAsset { get; init; }
    public required Asset OriginalAsset { get; init; }
    public required string Amount { get; init; }
    public required string Sender { get; init; }
    public required string Recipient { get; init; }
    public long BurnTimestamp { get; init; }
    public int Confirmations { get; init; }
    public int RequiredConfirmations { get; init; }
}

public record BurnProof
{
    public required BurnReceipt BurnReceipt { get; init; }
    public required List<string> MerkleProof { get; init; }
    public required string BlockHeader { get; init; }
    public required List<ValidatorSignature> Signatures { get; init; }
}

public record Transfer
{
    public required string Id { get; init; }
    public TransferDirection Direction { get; init; }
    public TransferStatus Status { get; init; }
    public ChainId SourceChain { get; init; }
    public ChainId TargetChain { get; init; }
    public required Asset Asset { get; init; }
    public required string Amount { get; init; }
    public required string Sender { get; init; }
    public required string Recipient { get; init; }
    public string? SourceTxHash { get; init; }
    public string? TargetTxHash { get; init; }
    public required string Fee { get; init; }
    public required Asset FeeAsset { get; init; }
    public long CreatedAt { get; init; }
    public long UpdatedAt { get; init; }
    public long? CompletedAt { get; init; }
    public string? ErrorMessage { get; init; }
}

public record TransferFilter
{
    public TransferStatus? Status { get; init; }
    public ChainId? SourceChain { get; init; }
    public ChainId? TargetChain { get; init; }
    public int? Limit { get; init; }
    public int? Offset { get; init; }
}

public record FeeEstimate
{
    public required string BridgeFee { get; init; }
    public required string GasFeeSource { get; init; }
    public required string GasFeeTarget { get; init; }
    public required string TotalFee { get; init; }
    public required Asset FeeAsset { get; init; }
    public int EstimatedTime { get; init; }
    public string? ExchangeRate { get; init; }
}

public record ExchangeRate
{
    public required Asset FromAsset { get; init; }
    public required Asset ToAsset { get; init; }
    public required string Rate { get; init; }
    public required string InverseRate { get; init; }
    public long LastUpdated { get; init; }
    public required string Source { get; init; }
}

public record SignedTransaction
{
    public required string TxHash { get; init; }
    public ChainId Chain { get; init; }
    public required string From { get; init; }
    public required string To { get; init; }
    public required string Value { get; init; }
    public required string Data { get; init; }
    public required string GasLimit { get; init; }
    public string? GasPrice { get; init; }
    public string? MaxFeePerGas { get; init; }
    public string? MaxPriorityFeePerGas { get; init; }
    public int Nonce { get; init; }
    public required string Signature { get; init; }
}

public record LockOptions { public string? Recipient { get; init; } public long? Deadline { get; init; } public double? Slippage { get; init; } }
public record MintOptions { public string? GasLimit { get; init; } public string? MaxFeePerGas { get; init; } public string? MaxPriorityFeePerGas { get; init; } }
public record BurnOptions { public string? Recipient { get; init; } public long? Deadline { get; init; } }
public record UnlockOptions { public string? GasLimit { get; init; } public string? GasPrice { get; init; } }

internal record ChainsResponse { public List<Chain>? Chains { get; init; } }
internal record AssetsResponse { public List<Asset>? Assets { get; init; } }
internal record TransfersResponse { public List<Transfer>? Transfers { get; init; } }
internal record BridgeHealthResponse { public required string Status { get; init; } }

public class BridgeException : Exception
{
    public string? Code { get; }
    public int StatusCode { get; }
    public bool IsConfirmationsPending => Code == "CONFIRMATIONS_PENDING";
    public BridgeException(string message, string? code = null, int statusCode = 0) : base(message) { Code = code; StatusCode = statusCode; }
}
