from dataclasses import dataclass

from pydantic import BaseModel

from ui_router.execution.formatting import flag_formatter


class UserModel(BaseModel):
    name: str
    balance: float = 0.0


class ProfileModel(BaseModel):
    user: UserModel
    bio: str = ""


@dataclass
class Address:
    city: str
    zip_code: str


def test_simple_flags():
    assert flag_formatter.format("Hello {name}!", name="World") == "Hello World!"
    assert flag_formatter.format("{a} and {b}", a="1", b="2") == "1 and 2"


def test_no_placeholders():
    assert flag_formatter.format("plain text") == "plain text"


def test_dot_notation_pydantic():
    user = UserModel(name="Alice", balance=99.5)
    assert flag_formatter.format("{user.name}", user=user) == "Alice"


def test_nested_pydantic():
    profile = ProfileModel(user=UserModel(name="Bob"), bio="dev")
    assert flag_formatter.format("{profile.user.name}", profile=profile) == "Bob"


def test_dot_notation_dict():
    data = {"name": "Charlie", "email": "c@test.com"}
    assert flag_formatter.format("{data.name}", data=data) == "Charlie"


def test_nested_dict():
    data = {"profile": {"email": "d@test.com"}}
    assert flag_formatter.format("{data.profile.email}", data=data) == "d@test.com"


def test_dot_notation_dataclass():
    addr = Address(city="Moscow", zip_code="101000")
    assert flag_formatter.format("{addr.city}", addr=addr) == "Moscow"


def test_mixed_types():
    user = UserModel(name="Eve", balance=42.0)
    data = {"role": "admin"}
    result = flag_formatter.format("{user.name} is {data.role}", user=user, data=data)
    assert result == "Eve is admin"


def test_missing_top_level_key():
    result = flag_formatter.format("Hello {missing}!", name="World")
    assert result == "Hello {missing}!"


def test_missing_nested_attribute():
    user = UserModel(name="Alice")
    result = flag_formatter.format("{user.nonexistent}", user=user)
    assert result == "{user.nonexistent}"


def test_none_in_chain():
    data = {"user": None}
    result = flag_formatter.format("{data.user.name}", data=data)
    assert result == "{data.user.name}"


def test_format_spec():
    user = UserModel(name="Alice", balance=99.555)
    assert flag_formatter.format("{user.balance:.2f}", user=user) == "99.56"


def test_format_spec_simple():
    assert flag_formatter.format("{val:.1f}", val=3.14159) == "3.1"


def test_mixed_simple_and_dot():
    user = UserModel(name="Alice")
    result = flag_formatter.format("{greeting}, {user.name}!", greeting="Hi", user=user)
    assert result == "Hi, Alice!"


def test_dict_with_int_like_key():
    data = {"0": "first", "1": "second"}
    assert flag_formatter.format("{data.0}", data=data) == "first"
