from __future__ import annotations

from enum import IntEnum
from typing import List, Optional, Union

from pydantic import BaseModel, Field, RootModel


class Item1(RootModel[str]):
    root: str = Field(..., max_length=3)


class Item2(RootModel[int]):
    root: int


class Item(RootModel[Union[Item1, Item2]]):
    root: Union[Item1, Item2]


class Item3(BaseModel):
    id: Optional[int] = None


class Level(IntEnum):
    integer_1 = 1
    integer_2 = 2


class LengthOrNumber1(RootModel[str]):
    root: str = Field(..., min_length=2)


class LengthOrNumber2(RootModel[int]):
    root: int


class LengthOrNumber(RootModel[Union[LengthOrNumber1, LengthOrNumber2]]):
    root: Union[LengthOrNumber1, LengthOrNumber2]


class PatternOrNumber1(RootModel[str]):
    root: str = Field(..., pattern='^a')


class PatternOrNumber2(RootModel[int]):
    root: int


class PatternOrNumber(RootModel[Union[PatternOrNumber1, PatternOrNumber2]]):
    root: Union[PatternOrNumber1, PatternOrNumber2]


class BoundedNumber1(RootModel[int]):
    root: int = Field(..., ge=2)


class BoundedNumber2(RootModel[float]):
    root: float = Field(..., ge=2.0)


class BoundedNumber(RootModel[Union[BoundedNumber1, BoundedNumber2]]):
    root: Union[BoundedNumber1, BoundedNumber2]


class ShortOrNull1(RootModel[str]):
    root: str = Field(..., max_length=3)


class ShortOrNull2(RootModel[None]):
    root: None


class ShortOrNull(RootModel[Union[ShortOrNull1, ShortOrNull2]]):
    root: Union[ShortOrNull1, ShortOrNull2]


class ShortOrItem1(RootModel[str]):
    root: str = Field(..., max_length=3)


class ShortOrItem(RootModel[Union[ShortOrItem1, Item3]]):
    root: Union[ShortOrItem1, Item3]


class LevelOrText1(RootModel[str]):
    root: str = Field(..., min_length=2)


class LevelOrText(RootModel[Union[Level, LevelOrText1]]):
    root: Union[Level, LevelOrText1]


class PatternOfBounded(RootModel[BoundedNumber]):
    root: BoundedNumber


class Model(BaseModel):
    length: Optional[LengthOrNumber] = None
    pattern: Optional[PatternOrNumber] = None
    bound: Optional[BoundedNumber] = None
    short: Optional[ShortOrNull] = None
    item: Optional[ShortOrItem] = None
    level: Optional[LevelOrText] = None
    held: Optional[PatternOfBounded] = None
    items: Optional[List[Item]] = None
