from typing import TYPE_CHECKING, Optional
from uuid import UUID

from sqlalchemy.orm import joinedload
from sqlalchemy.schema import Column, ForeignKey
from sqlmodel import Field, Relationship
from sqlmodel.sql.sqltypes import GUID

from joj.horse.models.base import ORMUtils
from joj.horse.utils.base import is_uuid

if TYPE_CHECKING:
    from joj.horse.models import Problem, ProblemSet


class ProblemProblemSetLink(ORMUtils, table=True):  # type: ignore[call-arg]
    __tablename__ = "problem_problem_set_links"

    problem_id: UUID = Field(
        sa_column=Column(
            GUID, ForeignKey("problems.id", ondelete="CASCADE"), primary_key=True
        ),
    )
    problem_set_id: UUID = Field(
        sa_column=Column(
            GUID, ForeignKey("problem_sets.id", ondelete="CASCADE"), primary_key=True
        ),
    )
    position: int = Field(
        index=True, nullable=False, sa_column_kwargs={"server_default": "0"}
    )

    problem: "Problem" = Relationship(back_populates="problem_problem_set_links")
    problem_set: "ProblemSet" = Relationship(back_populates="problem_problem_set_links")

    @classmethod
    async def find_by_problem_set_and_problem(
        cls, problem_set: str, problem: str
    ) -> Optional["ProblemProblemSetLink"]:
        # this is buggy, do not use!
        # not sure how much it's better than three queries (maybe even worse)

        from joj.horse import models

        statement = cls.sql_select().options(
            joinedload(cls.problem_set, innerjoin=True),
            joinedload(cls.problem, innerjoin=True),
        )
        if is_uuid(problem_set):
            statement = statement.where(cls.problem_set_id == problem_set)
        else:
            statement = statement.where(models.ProblemSet.url == problem_set)
        if is_uuid(problem):
            statement = statement.where(cls.problem_id == problem)
        else:
            statement = statement.where(models.Problem.url == problem)
        from loguru import logger

        logger.info(statement)
        result = await cls.session_exec(statement)
        logger.info(result.all())
        return result.one_or_none()

loguru.logger.info sqlmodel.Relationship sqlalchemy.schema.ForeignKey sqlalchemy.orm.joinedload joj.horse.utils.base.is_uuid sqlmodel.Field
[((856, 931), 'sqlmodel.Field', 'Field', ([], {'index': '(True)', 'nullable': '(False)', 'sa_column_kwargs': "{'server_default': '0'}"}), "(index=True, nullable=False, sa_column_kwargs={'server_default': '0'})\n", (861, 931), False, 'from sqlmodel import Field, Relationship\n'), ((972, 1028), 'sqlmodel.Relationship', 'Relationship', ([], {'back_populates': '"""problem_problem_set_links"""'}), "(back_populates='problem_problem_set_links')\n", (984, 1028), False, 'from sqlmodel import Field, Relationship\n'), ((1061, 1117), 'sqlmodel.Relationship', 'Relationship', ([], {'back_populates': '"""problem_problem_set_links"""'}), "(back_populates='problem_problem_set_links')\n", (1073, 1117), False, 'from sqlmodel import Field, Relationship\n'), ((1602, 1622), 'joj.horse.utils.base.is_uuid', 'is_uuid', (['problem_set'], {}), '(problem_set)\n', (1609, 1622), False, 'from joj.horse.utils.base import is_uuid\n'), ((1802, 1818), 'joj.horse.utils.base.is_uuid', 'is_uuid', (['problem'], {}), '(problem)\n', (1809, 1818), False, 'from joj.horse.utils.base import is_uuid\n'), ((2015, 2037), 'loguru.logger.info', 'logger.info', (['statement'], {}), '(statement)\n', (2026, 2037), False, 'from loguru import logger\n'), ((1483, 1526), 'sqlalchemy.orm.joinedload', 'joinedload', (['cls.problem_set'], {'innerjoin': '(True)'}), '(cls.problem_set, innerjoin=True)\n', (1493, 1526), False, 'from sqlalchemy.orm import joinedload\n'), ((1540, 1579), 'sqlalchemy.orm.joinedload', 'joinedload', (['cls.problem'], {'innerjoin': '(True)'}), '(cls.problem, innerjoin=True)\n', (1550, 1579), False, 'from sqlalchemy.orm import joinedload\n'), ((592, 637), 'sqlalchemy.schema.ForeignKey', 'ForeignKey', (['"""problems.id"""'], {'ondelete': '"""CASCADE"""'}), "('problems.id', ondelete='CASCADE')\n", (602, 637), False, 'from sqlalchemy.schema import Column, ForeignKey\n'), ((751, 800), 'sqlalchemy.schema.ForeignKey', 'ForeignKey', (['"""problem_sets.id"""'], {'ondelete': '"""CASCADE"""'}), "('problem_sets.id', ondelete='CASCADE')\n", (761, 800), False, 'from sqlalchemy.schema import Column, ForeignKey\n')]