"""Relationship inspection helpers for SQLModel models."""

from __future__ import annotations

from dataclasses import dataclass

from sqlalchemy import inspect as sa_inspect
from sqlalchemy.orm import RelationshipDirection
from sqlmodel import SQLModel


@dataclass(frozen=True)
class RelationInfo:
    """Normalized relationship metadata used by schema and mutation builders."""

    name: str
    parent_model: type[SQLModel]
    target_model: type[SQLModel]
    direction: RelationshipDirection
    uselist: bool
    secondary: object | None
    local_columns: tuple[str, ...]
    remote_columns: tuple[str, ...]
    sync_pairs: tuple[tuple[str, str], ...]
    secondary_sync_pairs: tuple[tuple[str, str], ...]
    local_remote_pairs: tuple[tuple[str, str], ...]
    link_model: type[SQLModel] | None

    @property
    def is_many_to_many(self) -> bool:
        return self.direction == RelationshipDirection.MANYTOMANY

    @property
    def is_many_to_one(self) -> bool:
        return self.direction == RelationshipDirection.MANYTOONE

    @property
    def is_one_to_many(self) -> bool:
        return self.direction == RelationshipDirection.ONETOMANY

    @property
    def is_to_many(self) -> bool:
        return self.uselist

    @property
    def is_to_one(self) -> bool:
        return not self.uselist


def _resolve_link_model(
    model: type[SQLModel],
    secondary: object | None,
) -> type[SQLModel] | None:
    if secondary is None:
        return None
    mapper = sa_inspect(model)
    for candidate in mapper.registry.mappers:
        if getattr(candidate, "local_table", None) is not secondary:
            continue
        cls = getattr(candidate, "class_", None)
        if isinstance(cls, type) and issubclass(cls, SQLModel):
            return cls
    return None


def inspect_relations(model: type[SQLModel]) -> dict[str, RelationInfo]:
    """Inspect mapped SQLAlchemy relationships for a SQLModel class."""
    try:
        mapper = sa_inspect(model)
    except Exception:
        return {}

    relations: dict[str, RelationInfo] = {}
    for name, rel in mapper.relationships.items():
        target = rel.mapper.class_
        if not isinstance(target, type) or not issubclass(target, SQLModel):
            continue

        relations[name] = RelationInfo(
            name=name,
            parent_model=model,
            target_model=target,
            direction=rel.direction,
            uselist=bool(rel.uselist),
            secondary=rel.secondary,
            local_columns=tuple(col.name for col in rel.local_columns),
            remote_columns=tuple(col.name for col in rel.remote_side),
            sync_pairs=tuple(
                (left.name, right.name) for left, right in rel.synchronize_pairs
            ),
            secondary_sync_pairs=tuple(
                (left.name, right.name) for left, right in rel.secondary_synchronize_pairs
            ),
            local_remote_pairs=tuple(
                (left.name, right.name) for left, right in rel.local_remote_pairs
            ),
            link_model=_resolve_link_model(model, rel.secondary),
        )

    return relations
