"""Synor RPC SDK Types."""

from dataclasses import dataclass, field
from enum import Enum
from typing import Optional, Callable


class Network(str, Enum):
    """Network type."""
    MAINNET = "mainnet"
    TESTNET = "testnet"


class Priority(str, Enum):
    """Transaction priority."""
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    URGENT = "urgent"


class TransactionStatus(str, Enum):
    """Transaction status."""
    PENDING = "pending"
    CONFIRMED = "confirmed"
    FAILED = "failed"
    REPLACED = "replaced"


class SubscriptionType(str, Enum):
    """Subscription type."""
    BLOCKS = "blocks"
    TRANSACTIONS = "transactions"
    ADDRESS = "address"
    MEMPOOL = "mempool"


@dataclass
class RpcConfig:
    """RPC SDK configuration."""
    api_key: str
    endpoint: str = "https://rpc.synor.cc/api/v1"
    ws_endpoint: str = "wss://rpc.synor.cc/ws"
    network: Network = Network.MAINNET
    timeout: float = 30.0
    debug: bool = False


@dataclass
class BlockHeader:
    """Block header."""
    hash: str
    height: int
    version: int
    previous_hash: str
    merkle_root: str
    timestamp: int
    difficulty: str
    nonce: int


@dataclass
class Block(BlockHeader):
    """Full block with transactions."""
    transactions: list[str] = field(default_factory=list)
    size: int = 0
    weight: int = 0
    tx_count: int = 0


@dataclass
class TxInput:
    """Transaction input."""
    txid: str
    vout: int
    script_sig: str
    sequence: int


@dataclass
class ScriptPubKey:
    """Script pubkey."""
    asm: str
    hex: str
    type: str
    addresses: list[str] = field(default_factory=list)


@dataclass
class TxOutput:
    """Transaction output."""
    value: str
    n: int
    script_pub_key: ScriptPubKey


@dataclass
class Transaction:
    """Transaction."""
    txid: str
    confirmations: int
    status: TransactionStatus
    size: int
    fee: str
    inputs: list[TxInput] = field(default_factory=list)
    outputs: list[TxOutput] = field(default_factory=list)
    block_hash: Optional[str] = None
    block_height: Optional[int] = None
    timestamp: Optional[int] = None
    raw: Optional[str] = None


@dataclass
class FeeEstimate:
    """Fee estimation result."""
    priority: Priority
    fee_rate: str
    estimated_blocks: int


@dataclass
class ChainInfo:
    """Chain information."""
    chain: str
    network: str
    height: int
    best_block_hash: str
    difficulty: str
    median_time: int
    chain_work: str
    syncing: bool
    sync_progress: float


@dataclass
class MempoolInfo:
    """Mempool information."""
    size: int
    bytes: int
    usage: int
    max_mempool: int
    min_fee: str


@dataclass
class UTXO:
    """Unspent Transaction Output."""
    txid: str
    vout: int
    amount: str
    address: str
    confirmations: int
    script_pub_key: Optional[str] = None


@dataclass
class Balance:
    """Balance information."""
    confirmed: str
    unconfirmed: str
    total: str


@dataclass
class Subscription:
    """WebSocket subscription."""
    id: str
    type: SubscriptionType
    created_at: int
    unsubscribe: Callable[[], None]
