from typing import TypeVar
from pydantic import BaseModel, PrivateAttr

from .schemas import make_schema, FIELD_MAPPING, get_tablename
from .errors import ModelIntegrityError


class Model(BaseModel):
    __rowid__: int | None = PrivateAttr(default=None)
    __tablename__: str  # will default to the lowercase name of the subclass
    __schema__: str  # best effort will be made if it's missing
    # there's no support for constrains or foreign fields

    def __init_subclass__(cls, **kws) -> None:
        for field in cls.__fields__.values():
            if field.type_ not in FIELD_MAPPING:
                raise ModelIntegrityError(
                    f'Field "{field.name}" of model "{cls.__name__}" is of unsupported type "{field.type_}"'
                )

        if not hasattr(cls, "__schema__"):
            cls.__schema__ = make_schema(cls)

        if not hasattr(cls, "__tablename__"):
            tablename = get_tablename(cls)
            setattr(cls, "__tablename__", tablename)

        super().__init_subclass__(**kws)

    def __str__(self) -> str:
        return f"{self!r}"


M = TypeVar("M", bound=Model)
