import uuid
from typing import List
from typing import Optional

from sqlalchemy.engine import Engine
from sqlmodel import Field
from sqlmodel import Relationship
from sqlmodel import Session
from sqlmodel import SQLModel
from sqlmodel import create_engine

_engine: Optional[Engine] = None


class FileTagAssociation(SQLModel, table=True):
    file_id: Optional[uuid.UUID] = Field(
        default=None, foreign_key="file.id", primary_key=True
    )
    tag_id: Optional[uuid.UUID] = Field(
        default=None, foreign_key="tag.id", primary_key=True
    )


class File(SQLModel, table=True):
    id: Optional[uuid.UUID] = Field(default_factory=uuid.uuid4, primary_key=True)
    name: str
    path: str

    tags: List["Tag"] = Relationship(
        back_populates="files", link_model=FileTagAssociation
    )


class Tag(SQLModel, table=True):
    id: Optional[uuid.UUID] = Field(default_factory=uuid.uuid4, primary_key=True)
    category: Optional[str]
    value: str

    files: List[File] = Relationship(
        back_populates="tags", link_model=FileTagAssociation
    )


def init(url: str) -> None:
    global _engine
    _engine = create_engine(url)

    SQLModel.metadata.create_all(_engine)


def get_engine() -> Engine:
    """Get the global database engine."""
    if _engine is None:  # pragma: no cover
        raise ValueError("Engine must be initialized with `db.init()`")
    return _engine


def get_session() -> Session:
    """Create a new database session to use as a context manager."""
    return Session(get_engine())

sqlmodel.SQLModel.metadata.create_all sqlmodel.Relationship sqlmodel.Field sqlmodel.create_engine
[((376, 436), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'foreign_key': '"""file.id"""', 'primary_key': '(True)'}), "(default=None, foreign_key='file.id', primary_key=True)\n", (381, 436), False, 'from sqlmodel import Field\n'), ((485, 544), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'foreign_key': '"""tag.id"""', 'primary_key': '(True)'}), "(default=None, foreign_key='tag.id', primary_key=True)\n", (490, 544), False, 'from sqlmodel import Field\n'), ((625, 676), 'sqlmodel.Field', 'Field', ([], {'default_factory': 'uuid.uuid4', 'primary_key': '(True)'}), '(default_factory=uuid.uuid4, primary_key=True)\n', (630, 676), False, 'from sqlmodel import Field\n'), ((730, 797), 'sqlmodel.Relationship', 'Relationship', ([], {'back_populates': '"""files"""', 'link_model': 'FileTagAssociation'}), "(back_populates='files', link_model=FileTagAssociation)\n", (742, 797), False, 'from sqlmodel import Relationship\n'), ((877, 928), 'sqlmodel.Field', 'Field', ([], {'default_factory': 'uuid.uuid4', 'primary_key': '(True)'}), '(default_factory=uuid.uuid4, primary_key=True)\n', (882, 928), False, 'from sqlmodel import Field\n'), ((997, 1063), 'sqlmodel.Relationship', 'Relationship', ([], {'back_populates': '"""tags"""', 'link_model': 'FileTagAssociation'}), "(back_populates='tags', link_model=FileTagAssociation)\n", (1009, 1063), False, 'from sqlmodel import Relationship\n'), ((1141, 1159), 'sqlmodel.create_engine', 'create_engine', (['url'], {}), '(url)\n', (1154, 1159), False, 'from sqlmodel import create_engine\n'), ((1165, 1202), 'sqlmodel.SQLModel.metadata.create_all', 'SQLModel.metadata.create_all', (['_engine'], {}), '(_engine)\n', (1193, 1202), False, 'from sqlmodel import SQLModel\n')]