import pytest
from sqlalchemy.ext.asyncio import AsyncSession

from src.models import Base
from src.models.base import TimestampMixin, UUIDPrimaryKeyMixin
from src.models.project.git_repository import GitRepository
from src.models.project.project import Project
from src.models.user.ssh_key import SSHKey
from src.models.user.user import User
from src.models.user.user_config import UserConfig


@pytest.mark.integration
def test_base_metadata_collects_declared_tables() -> None:
    assert isinstance(Base.metadata.tables, dict)


@pytest.mark.integration
def test_shared_mixins_define_expected_columns() -> None:
    assert "id" in UUIDPrimaryKeyMixin.__dict__
    assert "created_at" in TimestampMixin.__dict__
    assert "updated_at" in TimestampMixin.__dict__


@pytest.mark.integration
def test_expected_tables_are_registered() -> None:
    assert set(Base.metadata.tables) == {
        "config_profile_includes",
        "config_profiles",
        "git_repositories",
        "health_checks",
        "instance_events",
        "notifications",
        "projects",
        "ssh_keys",
        "terminal_sessions",
        "tool_definition_manifests",
        "tool_instances",
        "tool_types",
        "user_configs",
        "users",
        "workspaces",
    }


@pytest.mark.integration
def test_user_table_has_required_columns() -> None:
    columns = User.__table__.columns

    assert set(columns.keys()) == {
        "id",
        "email",
        "name",
        "authentik_id",
        "avatar_url",
        "created_at",
        "updated_at",
    }
    assert columns["email"].unique is True
    assert columns["authentik_id"].unique is True
    assert columns["avatar_url"].nullable is True


@pytest.mark.integration
def test_project_relationships_point_to_owner_and_default_ssh_key() -> None:
    owner_fk = next(iter(Project.__table__.c.owner_id.foreign_keys))
    ssh_fk = next(iter(Project.__table__.c.default_ssh_key_id.foreign_keys))

    assert owner_fk.target_fullname == "users.id"
    assert ssh_fk.target_fullname == "ssh_keys.id"
    assert Project.owner.property.mapper.class_ is User
    assert Project.default_ssh_key.property.mapper.class_ is SSHKey


@pytest.mark.integration
def test_repository_and_user_config_relationships_are_registered() -> None:
    project_fk = next(iter(GitRepository.__table__.c.project_id.foreign_keys))
    owner_fk = next(iter(GitRepository.__table__.c.owner_id.foreign_keys))
    user_config_fk = next(iter(UserConfig.__table__.c.user_id.foreign_keys))

    assert project_fk.target_fullname == "projects.id"
    assert owner_fk.target_fullname == "users.id"
    assert user_config_fk.target_fullname == "users.id"
    assert GitRepository.project.property.mapper.class_ is Project
    assert GitRepository.owner.property.mapper.class_ is User
    assert UserConfig.user.property.mapper.class_ is User


@pytest.mark.asyncio
@pytest.mark.integration
async def test_async_session_can_insert_and_load_user(db_session: AsyncSession) -> None:
    user = User(
        email="dev@headquarter.local",
        name="Dev User",
        authentik_id="dev-user",
        avatar_url=None,
    )

    db_session.add(user)
    await db_session.commit()
    await db_session.refresh(user)

    loaded_user = await db_session.get(User, user.id)

    assert loaded_user is not None
    assert loaded_user.email == "dev@headquarter.local"
