from __future__ import annotations

import re
from dataclasses import dataclass
from decimal import Decimal
from enum import Enum


class Currency(str, Enum):
    USD = "usd"
    EUR = "eur"
    USDC = "usdc"
    USDT = "usdt"
    EURC = "eurc"


class Network(str, Enum):
    ACH = "ach"
    WIRE = "wire"
    SEPA = "sepa"
    ETHEREUM = "ethereum"
    POLYGON = "polygon"
    SOLANA = "sol"
    BASE = "base"
    ARBITRUM = "arbitrum"
    TRON = "tron"
    AVALANCHE = "avalanche"
    OPTIMISM = "optimism"


class ErrorCategory(str, Enum):
    AUTH = "auth"
    VALIDATION = "validation"
    NOT_FOUND = "not_found"
    CONFLICT = "conflict"
    RATE_LIMIT = "rate_limit"
    UPSTREAM_UNAVAILABLE = "upstream_unavailable"
    UNKNOWN = "unknown"


_PREFIX_PATTERN = re.compile(r"^[a-zA-Z]+_[a-f0-9]{32}$")


def _validate_prefixed_id(value: str, prefix: str) -> str:
    if not value.startswith(f"{prefix}_"):
        raise ValueError(f"ID must start with '{prefix}_', got: {value}")
    if not _PREFIX_PATTERN.match(value):
        raise ValueError(f"Invalid ID format: {value}")
    return value


@dataclass(frozen=True)
class CustomerId:
    value: str

    def __post_init__(self) -> None:
        _validate_prefixed_id(self.value, "customer")


@dataclass(frozen=True)
class BankAccountId:
    value: str

    def __post_init__(self) -> None:
        _validate_prefixed_id(self.value, "bankAccount")


@dataclass(frozen=True)
class WalletId:
    value: str

    def __post_init__(self) -> None:
        _validate_prefixed_id(self.value, "wallet")


@dataclass(frozen=True)
class TransferId:
    value: str

    def __post_init__(self) -> None:
        _validate_prefixed_id(self.value, "transfer")


@dataclass(frozen=True)
class BusinessRepId:
    value: str

    def __post_init__(self) -> None:
        _validate_prefixed_id(self.value, "businessRep")


@dataclass(frozen=True)
class VirtualAccountId:
    value: str

    def __post_init__(self) -> None:
        _validate_prefixed_id(self.value, "virtualAccount")


@dataclass(frozen=True)
class OffloaderWalletId:
    value: str

    def __post_init__(self) -> None:
        _validate_prefixed_id(self.value, "offloaderWallet")


@dataclass(frozen=True)
class WebhookId:
    value: str

    def __post_init__(self) -> None:
        _validate_prefixed_id(self.value, "webhook")


@dataclass(frozen=True)
class EventId:
    value: str

    def __post_init__(self) -> None:
        _validate_prefixed_id(self.value, "event")


@dataclass(frozen=True)
class PayoutId:
    value: str

    def __post_init__(self) -> None:
        _validate_prefixed_id(self.value, "payout")


class CctpChain(str, Enum):
    SEI = "sei"
    NOBLE = "noble"


@dataclass(frozen=True)
class Amount:
    value: Decimal
    currency: Currency

    def __post_init__(self) -> None:
        if self.value <= 0:
            raise ValueError(f"Amount must be positive, got: {self.value}")


@dataclass(frozen=True)
class ApiError(Exception):
    category: ErrorCategory
    message: str
    status_code: int
    details: dict | None = None
    correlation_id: str | None = None

    def __str__(self) -> str:
        return f"[{self.category.value}] {self.status_code}: {self.message}"
