"""Shared endpoint test models, policies, and route helpers."""

from __future__ import annotations

from fastapi import APIRouter
from fastapi.routing import APIRoute
from pydantic import BaseModel
from sqlmodel import Field, Relationship, SQLModel

from auen.types import SelectQuery, User


class EndpointCovAuthor(SQLModel, table=True):
    __tablename__ = "endpoint_cov_author"
    id: int | None = Field(default=None, primary_key=True)
    name: str
    bio: str | None = None


class EndpointCovBook(SQLModel, table=True):
    __tablename__ = "endpoint_cov_book"
    id: int | None = Field(default=None, primary_key=True)
    title: str
    isbn: str
    author_id: int | None = Field(default=None, foreign_key="endpoint_cov_author.id")
    author: EndpointCovAuthor = Relationship()


class EndpointCovOther(SQLModel, table=True):
    __tablename__ = "endpoint_cov_other"
    id: int | None = Field(default=None, primary_key=True)
    label: str


class EndpointCovAllowAll:
    def can_create(self, user: User, obj_in: BaseModel) -> bool:
        return True

    def can_read(self, user: User, db_obj: SQLModel) -> bool:
        return True

    def can_update(self, user: User, db_obj: SQLModel, obj_in: BaseModel) -> bool:
        return True

    def can_delete(self, user: User, db_obj: SQLModel) -> bool:
        return True

    def filter_list_query(
        self, user: User, query: SelectQuery[SQLModel]
    ) -> SelectQuery[SQLModel]:
        return query


class EndpointCovDenyCreate(EndpointCovAllowAll):
    def can_create(self, user: User, obj_in: BaseModel) -> bool:
        return False


class EndpointCovDenyUpdate(EndpointCovAllowAll):
    def can_update(self, user: User, db_obj: SQLModel, obj_in: BaseModel) -> bool:
        return False


class EndpointCovRelationPolicyDenyCreate(EndpointCovAllowAll):
    def can_create(self, user: User, obj_in: BaseModel) -> bool:
        return False


class EndpointCovRelationPolicyDenyUpdate(EndpointCovAllowAll):
    def can_update(self, user: User, db_obj: SQLModel, obj_in: BaseModel) -> bool:
        return False


def get_route(router: APIRouter, path: str, method: str) -> APIRoute:
    prefix = router.prefix or ""
    full_path = f"{prefix}{path}"
    for route in router.routes:
        if (
            isinstance(route, APIRoute)
            and route.path == full_path
            and method in route.methods
        ):
            return route
    msg = f"Route {method} {full_path} not found"
    raise AssertionError(msg)
