import re
from collections.abc import Hashable, Mapping, Sequence
from typing import Annotated, TypeVar

import annotated_types
from pydantic import NonNegativeInt

from .collections import Immutable
from .typing import Re

__all__ = (
    "AlphaClosed",
    "AlphaOpen",
    "DateString",
    "DateStringFlex",
    "DateStringFlex",
    "H",
    "Immutable",
    "JsonArray",
    "JsonContainer",
    "JsonObject",
    "JsonValue",
    "Natural",
    "NegativeScore",
    "PolarityScore",
    "Positive",
    "PositiveScore",
    "Stars",
    "T",
    "TimestampISO",
    "Timestamp_",
)

T = TypeVar("T")
H = TypeVar("H", bound=Hashable)

type Natural = NonNegativeInt
type Stars = Annotated[float, annotated_types.Ge(1.0), annotated_types.Le(5.0)]
type Positive = Annotated[float, annotated_types.Gt(0)]
type PositiveScore = Annotated[float, annotated_types.Ge(0.0), annotated_types.Le(5.0)]
type NegativeScore = Annotated[float, annotated_types.Ge(-5.0), annotated_types.Le(0.0)]
type AlphaClosed = Annotated[float, annotated_types.Ge(0.0), annotated_types.Le(1.0)]
type AlphaOpen = Annotated[float, annotated_types.Gt(0.0), annotated_types.Lt(1.0)]
type PolarityScore = Annotated[float, annotated_types.Ge(-1.0), annotated_types.Le(1.0)]
type DateString = Annotated[str, Re(pattern=re.compile(r"^[12]\d{3}-\d{2}-\d{2}$"))]
type DateStringFlex = Annotated[str, Re(pattern=re.compile(r"^[12]\d{3}-\d{1,2}-\d{1,2}$"))]
type TimestampISO = Annotated[
    str, Re(pattern=re.compile(r"^[12]\d{3}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}"))
]
type Timestamp_ = Annotated[
    str, Re(pattern=re.compile(r"^[12]\d{3}-\d{2}-\d{2}_\d{2}:\d{2}:\d{2}"))
]

type JsonValue = int | float | str | bool | None
type JsonArray = Sequence[JsonValue | JsonObject]
type JsonObject = Mapping[str, JsonValue | JsonObject | JsonArray]
type JsonContainer = JsonArray | JsonObject
