from enum import Enum
from functools import wraps
from logging import Logger
from typing import Any, Callable, ClassVar, List, Optional, Set

from nostr_sdk import Event, Keys, Metadata, ProductData, StallData
from pydantic import BaseModel, ConfigDict, Field

def deprecated(
    reason: str, version: str = "2.0.0", alternative: Optional[str] = None
) -> Callable[[Callable[..., Any]], Callable[..., Any]]: ...

class Namespace(str, Enum):
    """
    Represents a namespace.
    """

    MERCHANT = "com.synvya.merchant"
    GAMER = "com.synvya.gamer"
    OTHER = "com.synvya.other"

    """Configuration for Pydantic models to use enum values directly."""
    model_config = ConfigDict(use_enum_values=True)

class ProfileType(str, Enum):
    """
    Represents a profile type.
    """

    MERCHANT_RETAIL = "retail"
    MERCHANT_RESTAURANT = "restaurant"
    MERCHANT_SERVICE = "service"
    MERCHANT_BUSINESS = "business"
    MERCHANT_ENTERTAINMENT = "entertainment"
    MERCHANT_OTHER = "other"
    GAMER_DADJOKE = "dad-joke-game"
    OTHER_OTHER = "other"

    """Configuration for Pydantic models to use enum values directly."""
    model_config = ConfigDict(use_enum_values=True)

class ProfileFilter(BaseModel):
    """
    Represents a profile filter.
    """

    namespace: str
    profile_type: ProfileType
    hashtags: List[str]

    def __init__(
        self,
        namespace: str,
        profile_type: ProfileType,
        hashtags: Optional[List[str]] = None,
    ) -> None: ...
    def to_json(self) -> str: ...
    @classmethod
    def from_json(cls, json_str: str) -> "ProfileFilter": ...
    @staticmethod
    def _normalize_hashtag(tag: str) -> str: ...

class Profile(BaseModel):
    """
    Nostr Profile class.
    Contains public key only.
    """

    PROFILE_URL_PREFIX: ClassVar[str]
    logger: ClassVar[Logger]

    public_key: str
    about: str
    banner: str
    bot: bool
    city: str
    country: str
    display_name: str
    email: str
    hashtags: List[str]
    locations: Set[str]
    name: str
    namespace: str
    nip05: str
    nip05_validated: bool
    picture: str
    phone: str
    profile_type: ProfileType
    profile_url: str
    state: str
    street: str
    website: str
    zip_code: str

    def __init__(self, public_key: str, **data: Any) -> None: ...
    def add_hashtag(self, hashtag: str) -> None: ...
    def add_location(self, location: str) -> None: ...
    def get_about(self) -> str: ...
    def get_banner(self) -> str: ...
    def get_city(self) -> str: ...
    def get_country(self) -> str: ...
    def get_display_name(self) -> str: ...
    def get_email(self) -> str: ...
    def get_hashtags(self) -> List[str]: ...
    def get_locations(self) -> set[str]: ...
    def get_name(self) -> str: ...
    def get_namespace(self) -> str: ...
    def get_nip05(self) -> str: ...
    def get_phone(self) -> str: ...
    def get_picture(self) -> str: ...
    def get_profile_type(self) -> ProfileType: ...
    def get_profile_url(self) -> str: ...
    def get_public_key(self, encoding: KeyEncoding = KeyEncoding.BECH32) -> str: ...
    def get_state(self) -> str: ...
    def get_street(self) -> str: ...
    def get_website(self) -> str: ...
    def get_zip_code(self) -> str: ...
    def is_bot(self) -> bool: ...
    def is_nip05_validated(self) -> bool: ...
    def matches_filter(self, profile_filter: ProfileFilter) -> bool: ...
    def set_about(self, about: str) -> None: ...
    def set_banner(self, banner: str) -> None: ...
    def set_bot(self, bot: bool) -> None: ...
    def set_city(self, city: str) -> None: ...
    def set_country(self, country: str) -> None: ...
    def set_display_name(self, display_name: str) -> None: ...
    def set_email(self, email: str) -> None: ...
    def set_name(self, name: str) -> None: ...
    def set_namespace(self, namespace: Namespace | str) -> None: ...
    def set_nip05(self, nip05: str) -> None: ...
    def set_phone(self, phone: str) -> None: ...
    def set_picture(self, picture: str) -> None: ...
    def set_profile_type(self, profile_type: ProfileType | str) -> None: ...
    def set_state(self, state: str) -> None: ...
    def set_street(self, street: str) -> None: ...
    def set_website(self, website: str) -> None: ...
    def set_zip_code(self, zip_code: str) -> None: ...
    def to_dict(self) -> dict: ...
    def to_json(self) -> str: ...
    def __eq__(self, other: object) -> bool: ...
    def __hash__(self) -> int: ...
    async def _fetch_nip05_metadata(self, nip05: str) -> dict: ...
    async def _validate_profile_nip05(self) -> bool: ...
    def _validate_url(self, url: str) -> str: ...
    @classmethod
    async def from_metadata(cls, metadata: Metadata, public_key: str) -> "Profile": ...
    @classmethod
    async def from_event(cls, event: Event) -> "Profile": ...
    @classmethod
    def from_json(cls, json_str: str) -> "Profile": ...
    @staticmethod
    def _normalize_hashtag(tag: str) -> str: ...

class KeyEncoding(str, Enum):
    """
    Enum representing the valid encoding formats for public or private keys.

    Attributes:
        BECH32 (str): Encodes the key using Bech32 format.
        HEX (str): Encodes the key using hexadecimal format.
    """

    BECH32 = "bech32"
    HEX = "hex"

    @classmethod
    def from_str(cls, value: str) -> "KeyEncoding": ...

class NostrKeys(BaseModel):
    """
    NostrKeys is a class that contains a public and private key
    in bech32 format.
    """

    keys: Keys

    def __init__(self, private_key: Optional[str] = None) -> None: ...
    def get_public_key(self, encoding: KeyEncoding = KeyEncoding.BECH32) -> str: ...
    def get_private_key(self, encoding: KeyEncoding = KeyEncoding.BECH32) -> str: ...
    def to_json(self, encoding: KeyEncoding = KeyEncoding.BECH32) -> str: ...
    def __str__(self) -> str: ...
    @classmethod
    def from_private_key(cls, private_key: str) -> "NostrKeys": ...
    @classmethod
    def derive_public_key(
        cls, private_key: str, encoding: KeyEncoding = KeyEncoding.BECH32
    ) -> str: ...

class ProductShippingCost(BaseModel):
    psc_id: str
    psc_cost: float

    def __init__(self, psc_id: str, psc_cost: float) -> None: ...
    def get_id(self) -> str: ...
    def get_cost(self) -> float: ...
    def set_id(self, psc_id: str) -> None: ...
    def set_cost(self, psc_cost: float) -> None: ...
    def to_dict(self) -> dict: ...
    def to_json(self) -> str: ...
    def __str__(self) -> str: ...

class StallShippingMethod(BaseModel):
    """
    Represents a shipping method for a stall.
    """

    ssm_id: str
    ssm_cost: float
    ssm_name: str
    ssm_regions: List[str]

    def __init__(
        self,
        ssm_id: str,
        ssm_cost: float,
        ssm_name: str,
        ssm_regions: Optional[List[str]] = None,
    ) -> None: ...
    def get_id(self) -> str: ...
    def get_cost(self) -> float: ...
    def get_name(self) -> str: ...
    def get_regions(self) -> List[str]: ...
    def set_id(self, ssm_id: str) -> None: ...
    def set_cost(self, ssm_cost: float) -> None: ...
    def set_name(self, ssm_name: str) -> None: ...
    def set_regions(self, ssm_regions: List[str]) -> None: ...
    def to_dict(self) -> dict: ...
    def to_json(self) -> str: ...
    def __str__(self) -> str: ...

class Product(BaseModel):
    id: str
    stall_id: str
    name: str
    description: str
    images: List[str]
    currency: str
    price: float
    quantity: int
    shipping: List[ProductShippingCost]
    categories: List[str]
    specs: List[List[str]]
    seller: str

    @classmethod
    def from_product_data(cls, product_data: ProductData) -> "Product": ...
    @classmethod
    def from_json(cls, json_str: str) -> "Product": ...
    def get_seller(self) -> str: ...
    def set_seller(self, seller: str) -> None: ...
    def to_product_data(self) -> ProductData: ...
    def to_dict(self) -> dict: ...
    def to_json(self) -> str: ...
    def __eq__(self, other: object) -> bool: ...

class Stall(BaseModel):
    id: str
    name: str
    description: str
    currency: str
    shipping: List[StallShippingMethod]
    geohash: Optional[str]

    # @classmethod
    # def from_stall_data(cls, stall_data: StallData) -> "MerchantStall": ...
    @classmethod
    def from_json(cls, stall_content: str) -> "Stall": ...
    def get_geohash(self) -> str: ...
    def set_geohash(self, geohash: str) -> None: ...
    def to_dict(self) -> dict: ...
    def to_json(self) -> str: ...
    def to_stall_data(self) -> StallData: ...

class Delegation(BaseModel):
    author: str
    conditions: str
    sig: str
    tag: list[str]
    created_at: int
    expires_at: int
    allowed_kinds: Set[int]

    @classmethod
    def parse(cls, raw: str | dict) -> "Delegation": ...
    def validate_event(self, event: Event) -> None: ...
    @property
    def delegation_tag(self) -> list[str]: ...
