using System.Text.Json.Serialization;

namespace Synor.Privacy
{
    // ==================== Confidential Transactions ====================

    public record ConfidentialTxInput
    {
        [JsonPropertyName("commitment")]
        public required string Commitment { get; init; }

        [JsonPropertyName("blinding_factor")]
        public required string BlindingFactor { get; init; }

        [JsonPropertyName("value")]
        public required string Value { get; init; }

        [JsonPropertyName("key_image")]
        public string? KeyImage { get; init; }
    }

    public record ConfidentialTxOutput
    {
        [JsonPropertyName("commitment")]
        public required string Commitment { get; init; }

        [JsonPropertyName("blinding_factor")]
        public required string BlindingFactor { get; init; }

        [JsonPropertyName("value")]
        public required string Value { get; init; }

        [JsonPropertyName("recipient_public_key")]
        public required string RecipientPublicKey { get; init; }

        [JsonPropertyName("range_proof")]
        public string? RangeProof { get; init; }
    }

    public record ConfidentialTransaction
    {
        [JsonPropertyName("id")]
        public required string Id { get; init; }

        [JsonPropertyName("inputs")]
        public required ConfidentialTxInput[] Inputs { get; init; }

        [JsonPropertyName("outputs")]
        public required ConfidentialTxOutput[] Outputs { get; init; }

        [JsonPropertyName("fee")]
        public required string Fee { get; init; }

        [JsonPropertyName("excess")]
        public required string Excess { get; init; }

        [JsonPropertyName("excess_sig")]
        public required string ExcessSig { get; init; }

        [JsonPropertyName("kernel_offset")]
        public string? KernelOffset { get; init; }
    }

    // ==================== Commitments ====================

    public record Commitment
    {
        [JsonPropertyName("commitment")]
        public required string CommitmentValue { get; init; }

        [JsonPropertyName("blinding_factor")]
        public required string BlindingFactor { get; init; }
    }

    public record RangeProof
    {
        [JsonPropertyName("proof")]
        public required string Proof { get; init; }

        [JsonPropertyName("commitment")]
        public required string Commitment { get; init; }

        [JsonPropertyName("min_value")]
        public long MinValue { get; init; }

        [JsonPropertyName("max_value")]
        public long MaxValue { get; init; }
    }

    // ==================== Ring Signatures ====================

    public record RingSignature
    {
        [JsonPropertyName("c0")]
        public required string C0 { get; init; }

        [JsonPropertyName("s")]
        public required string[] S { get; init; }

        [JsonPropertyName("key_image")]
        public required string KeyImage { get; init; }

        [JsonPropertyName("ring")]
        public required string[] Ring { get; init; }
    }

    // ==================== Stealth Addresses ====================

    public record StealthKeyPair
    {
        [JsonPropertyName("spend_public_key")]
        public required string SpendPublicKey { get; init; }

        [JsonPropertyName("spend_private_key")]
        public required string SpendPrivateKey { get; init; }

        [JsonPropertyName("view_public_key")]
        public required string ViewPublicKey { get; init; }

        [JsonPropertyName("view_private_key")]
        public required string ViewPrivateKey { get; init; }
    }

    public record StealthAddress
    {
        [JsonPropertyName("address")]
        public required string Address { get; init; }

        [JsonPropertyName("ephemeral_public_key")]
        public required string EphemeralPublicKey { get; init; }

        [JsonPropertyName("tx_public_key")]
        public string? TxPublicKey { get; init; }
    }

    public record StealthOutput
    {
        [JsonPropertyName("tx_hash")]
        public required string TxHash { get; init; }

        [JsonPropertyName("output_index")]
        public int OutputIndex { get; init; }

        [JsonPropertyName("stealth_address")]
        public required string StealthAddress { get; init; }

        [JsonPropertyName("amount")]
        public required string Amount { get; init; }

        [JsonPropertyName("block_height")]
        public long BlockHeight { get; init; }
    }
}
