"""Data types for social-value — all frozen, all immutable."""

from __future__ import annotations

import time
from dataclasses import dataclass, field


MAX_MEMO_LENGTH = 280

VALID_NETWORKS = ("mainnet", "testnet")


class SecretStr:
    """A string that redacts itself in repr/str to prevent secret leakage."""

    __slots__ = ("_value",)

    def __init__(self, value: str) -> None:
        object.__setattr__(self, "_value", value)

    def get_secret_value(self) -> str:
        """Explicitly retrieve the secret. Use intentionally."""
        return self._value

    def __repr__(self) -> str:
        return "SecretStr('***')"

    def __str__(self) -> str:
        return "***"

    def __bool__(self) -> bool:
        return bool(self._value)

    def __len__(self) -> int:
        return len(self._value)

    def __eq__(self, other: object) -> bool:
        if isinstance(other, SecretStr):
            return self._value == other._value
        return NotImplemented

    def __setattr__(self, name: str, value: object) -> None:
        raise AttributeError("SecretStr is immutable")


def _validate_amount_sat(amount_sat: int, field_name: str = "amount_sat") -> None:
    """Validate that an amount is a positive integer."""
    if not isinstance(amount_sat, int):
        raise TypeError(f"{field_name} must be an integer, got {type(amount_sat).__name__}")
    if amount_sat <= 0:
        raise ValueError(f"{field_name} must be positive, got {amount_sat}")


def _validate_destination(destination: str) -> None:
    """Validate that a destination is a non-empty string."""
    if not isinstance(destination, str) or not destination.strip():
        raise ValueError("destination must be a non-empty string")


@dataclass(frozen=True)
class WalletState:
    """Current state of the social-value wallet."""

    balance_sat: int
    pending_send_sat: int = 0
    pending_receive_sat: int = 0

    @property
    def available_sat(self) -> int:
        """Spendable balance (confirmed minus pending outbound)."""
        return self.balance_sat - self.pending_send_sat


@dataclass(frozen=True)
class FeeEstimate:
    """Estimated fees for a transaction."""

    action: str
    amount_sat: int
    fee_sat: int
    fee_pct: float

    @property
    def total_sat(self) -> int:
        """Total cost including fees."""
        return self.amount_sat + self.fee_sat


@dataclass(frozen=True)
class TransferResult:
    """Result of a transfer operation."""

    success: bool
    amount_sat: int
    fee_sat: int
    destination: str
    memo: str = ""
    payment_id: str = ""
    timestamp: float = field(default_factory=time.time)


@dataclass(frozen=True)
class PaymentRecord:
    """A historical payment for tracking."""

    payment_id: str
    direction: str  # "send" or "receive"
    amount_sat: int
    fee_sat: int
    destination: str
    memo: str = ""
    timestamp: float = field(default_factory=time.time)

    def __post_init__(self) -> None:
        if self.direction not in ("send", "receive"):
            raise ValueError(f"direction must be 'send' or 'receive', got '{self.direction}'")
        if self.amount_sat < 0:
            raise ValueError(f"amount_sat must be non-negative, got {self.amount_sat}")


@dataclass(frozen=True)
class BatchTransferItem:
    """A single item in a batch transfer."""

    destination: str
    amount_sat: int
    memo: str = ""

    def __post_init__(self) -> None:
        _validate_amount_sat(self.amount_sat)
        _validate_destination(self.destination)
        if len(self.memo) > MAX_MEMO_LENGTH:
            raise ValueError(f"memo exceeds {MAX_MEMO_LENGTH} chars")
