"""
Type inference verification for mypy.

This file is NOT run as tests - it's only for mypy to check.
Run with: just mypy

The assert_type() calls will make mypy verify the inferred types match our expectations.
If types don't match, mypy will error!
"""

from typing_extensions import assert_type

from attrs import define

from mantle.db import Query
from tests.models import SimpleBookmark, User


@define
class SimpleBookmarkAttrs:
    url: str
    comment: str
    favourite: bool


@define
class TeamAttrs:
    name: str


@define
class UserAttrs:
    username: str
    team: TeamAttrs


def check_query_all_type_inference() -> None:
    """Verify Query.all() returns correctly typed list."""
    query = Query(SimpleBookmark.objects.all(), SimpleBookmarkAttrs)

    # Verify query is typed as Query[SimpleBookmarkAttrs]
    assert_type(query, Query[SimpleBookmarkAttrs])

    # Verify all() returns list[SimpleBookmarkAttrs]
    bookmarks = query.all()
    assert_type(bookmarks, list[SimpleBookmarkAttrs])

    # Verify list indexing returns SimpleBookmarkAttrs
    first = bookmarks[0]
    assert_type(first, SimpleBookmarkAttrs)

    # Verify field access has correct types
    url = first.url
    assert_type(url, str)

    favourite = first.favourite
    assert_type(favourite, bool)


def check_query_get_type_inference() -> None:
    """Verify Query.get() returns correctly typed single instance."""
    query = Query(
        SimpleBookmark.objects.filter(url="https://example.com"), SimpleBookmarkAttrs
    )

    # Verify get() returns SimpleBookmarkAttrs
    bookmark = query.get()
    assert_type(bookmark, SimpleBookmarkAttrs)

    # Verify field access
    url = bookmark.url
    assert_type(url, str)


def check_nested_type_inference() -> None:
    """Verify nested attrs types are correctly inferred."""
    query = Query(User.objects.all(), UserAttrs)
    assert_type(query, Query[UserAttrs])

    users = query.all()
    assert_type(users, list[UserAttrs])

    user = users[0]
    assert_type(user, UserAttrs)

    # Verify nested access
    team = user.team
    assert_type(team, TeamAttrs)

    team_name = user.team.name
    assert_type(team_name, str)


def check_filtered_queryset_type_inference() -> None:
    """Verify filtered querysets maintain correct types."""
    query = Query(SimpleBookmark.objects.filter(favourite=True), SimpleBookmarkAttrs)

    favourite_bookmarks = query.all()
    assert_type(favourite_bookmarks, list[SimpleBookmarkAttrs])


def check_different_shape_classes() -> None:
    """Verify different shape classes result in different types."""
    bookmark_query = Query(SimpleBookmark.objects.all(), SimpleBookmarkAttrs)
    assert_type(bookmark_query, Query[SimpleBookmarkAttrs])

    user_query = Query(User.objects.all(), UserAttrs)
    assert_type(user_query, Query[UserAttrs])

    bookmarks = bookmark_query.all()
    assert_type(bookmarks, list[SimpleBookmarkAttrs])

    users = user_query.all()
    assert_type(users, list[UserAttrs])

    # Verify each item has correct type
    b = bookmarks[0]
    assert_type(b, SimpleBookmarkAttrs)

    u = users[0]
    assert_type(u, UserAttrs)
