from typing import Optional, List
from sqlmodel import SQLModel, Field, Relationship
from functools import partial

DynamicRelationship = partial(Relationship, sa_relationship_kwargs={"lazy": "dynamic"})  # change default lazy loading to dynamic


class SDEIcon(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)

    description: Optional[str] = None
    iconFile: str

    categories: List['SDECategory'] = DynamicRelationship(back_populates="icon")
    groups: List['SDEGroup'] = DynamicRelationship(back_populates="icon")
    marketgroups: List['SDEMarketGroup'] = DynamicRelationship(back_populates="icon")
    types: List['SDEType'] = DynamicRelationship(back_populates="icon")


class SDECategory(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)

    icon_id: Optional[int] = Field(default=None, foreign_key="sdeicon.id")
    icon: Optional[SDEIcon] = Relationship(back_populates="categories")

    name: str
    published: bool

    groups: List['SDEGroup'] = DynamicRelationship(back_populates="category")


class SDEGroup(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)

    anchorable: bool
    anchored: bool

    category_id: Optional[int] = Field(default=None, foreign_key="sdecategory.id")
    category: Optional[SDECategory] = Relationship(back_populates="groups")

    fittableNonSingletion: bool

    icon_id: Optional[int] = Field(default=None, foreign_key="sdeicon.id")
    icon: Optional[SDEIcon] = Relationship(back_populates="groups")

    name: str
    published: bool
    useBasePrice: bool

    types: List['SDEType'] = DynamicRelationship(back_populates="group")


class SDEMarketGroup(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)

    description: Optional[str] = None
    hasTypes: bool

    icon_id: Optional[int] = Field(default=None, foreign_key="sdeicon.id")
    icon: Optional[SDEIcon] = Relationship(back_populates="marketgroups")

    name: str

    parent_marketgroup_id: Optional[int] = Field(default=None, foreign_key="sdemarketgroup.id")
    parent_marketgroup: Optional['SDEMarketGroup'] = Relationship(back_populates="children_marketgroups",
                                                                  sa_relationship_kwargs={"remote_side": 'SDEMarketGroup.id'})  # workaround for self reference: https://github.com/tiangolo/sqlmodel/issues/127#issuecomment-1224135123
    children_marketgroups: List['SDEMarketGroup'] = DynamicRelationship(back_populates="parent_marketgroup")

    types: List['SDEType'] = DynamicRelationship(back_populates="marketgroup")


class SDEType(SQLModel, table=True):
    id: int = Field(primary_key=True)

    group_id: Optional[int] = Field(default=None, foreign_key="sdegroup.id")
    group: Optional[SDEGroup] = Relationship(back_populates="types")

    marketgroup_id: Optional[int] = Field(default=None, foreign_key="sdemarketgroup.id")
    marketgroup: Optional[SDEMarketGroup] = Relationship(back_populates="types")

    name: str
    published: bool = False
    description: Optional[str] = None
    basePrice: Optional[float] = None

    icon_id: Optional[int] = Field(default=None, foreign_key="sdeicon.id")
    icon: Optional[SDEIcon] = Relationship(back_populates="types")

    volume: Optional[float] = None
    portionSize: int

    materials: List['SDETypeMaterial'] = DynamicRelationship(back_populates="type",
                                                      sa_relationship_kwargs={"lazy": "dynamic", "foreign_keys": '[SDETypeMaterial.type_id]'})  # https://github.com/tiangolo/sqlmodel/issues/10#issuecomment-1537445078
    material_of: List['SDETypeMaterial'] = DynamicRelationship(back_populates="material_type",
                                                        sa_relationship_kwargs={"lazy": "dynamic", "foreign_keys": '[SDETypeMaterial.material_type_id]'})  # https://github.com/tiangolo/sqlmodel/issues/10#issuecomment-1537445078


class SDETypeMaterial(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)

    type_id: Optional[int] = Field(default=None, foreign_key="sdetype.id")
    type: Optional[SDEType] = Relationship(back_populates="materials",
                                           sa_relationship_kwargs={"primaryjoin": 'SDETypeMaterial.type_id==SDEType.id',
                                                                'lazy': 'joined'})  # workaround: https://github.com/tiangolo/sqlmodel/issues/10#issuecomment-1002835506

    material_type_id: Optional[int] = Field(default=None, foreign_key="sdetype.id")
    material_type: Optional[SDEType] = Relationship(back_populates="material_of",
                                                    sa_relationship_kwargs={"primaryjoin": 'SDETypeMaterial.material_type_id==SDEType.id',
                                                                         'lazy': 'joined'})  # workaround: https://github.com/tiangolo/sqlmodel/issues/10#issuecomment-1002835506

    quantity: int
