from typing import Optional, List

from sqlalchemy import String
from sqlalchemy.sql.schema import Column
from sqlmodel import SQLModel, Field, Relationship


class CustomerProductLink(SQLModel, table=True):
    customer_id: Optional[int] = Field(
        default=None, foreign_key='customer.id', primary_key=True
    )
    product_id: Optional[int] = Field(
        default=None, foreign_key='product.id', primary_key=True
    )


class AddressBase(SQLModel):
    street_name: str
    house_number: str
    city: str
    zip_code: str


class Address(AddressBase, table=True):
    id: int = Field(default=None, primary_key=True)
    customers: List['Customer'] = Relationship(back_populates='address')


class AddressOut(AddressBase):
    pass


class AddressIn(AddressBase):
    pass


class CustomerBase(SQLModel):
    first_name: str
    last_name: str
    birth_date: str
    gender: str
    mobile_number: str
    email: str


class Customer(CustomerBase, table=True):
    id: int = Field(default=None, primary_key=True)
    address_id: Optional[int] = Field(default=None, foreign_key='address.id')
    address: Optional[Address] = Relationship(back_populates='customers',
                                              sa_relationship_kwargs={'lazy': 'selectin'})
    mobile_number: str = Field(sa_column=Column('mobile_number', String, unique=True))
    email: str = Field(sa_column=Column('email', String, unique=True))

    products: List['Product'] = Relationship(back_populates='customers', link_model=CustomerProductLink,
                                             sa_relationship_kwargs={'lazy': 'selectin'})


class CustomerOut(CustomerBase):
    id: int
    address: Optional[AddressOut]


class CustomerIn(CustomerBase):
    address: Optional[AddressIn]


class ProductBase(SQLModel):
    name: Optional[str] = None


class Product(ProductBase, table=True):
    id: int = Field(default=None, primary_key=True)
    name: str = Field(sa_column=Column('name', String, unique=True))

    customers: List[Customer] = Relationship(back_populates='products', link_model=CustomerProductLink)


class ProductOut(ProductBase):
    id: int
    name: str


class ProductIn(ProductBase):
    name: str


class ProductUpdate(ProductBase):
    product_id: int

sqlmodel.Relationship sqlalchemy.sql.schema.Column sqlmodel.Field
[((241, 305), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'foreign_key': '"""customer.id"""', 'primary_key': '(True)'}), "(default=None, foreign_key='customer.id', primary_key=True)\n", (246, 305), False, 'from sqlmodel import SQLModel, Field, Relationship\n'), ((352, 415), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'foreign_key': '"""product.id"""', 'primary_key': '(True)'}), "(default=None, foreign_key='product.id', primary_key=True)\n", (357, 415), False, 'from sqlmodel import SQLModel, Field, Relationship\n'), ((592, 629), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'primary_key': '(True)'}), '(default=None, primary_key=True)\n', (597, 629), False, 'from sqlmodel import SQLModel, Field, Relationship\n'), ((664, 702), 'sqlmodel.Relationship', 'Relationship', ([], {'back_populates': '"""address"""'}), "(back_populates='address')\n", (676, 702), False, 'from sqlmodel import SQLModel, Field, Relationship\n'), ((989, 1026), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'primary_key': '(True)'}), '(default=None, primary_key=True)\n', (994, 1026), False, 'from sqlmodel import SQLModel, Field, Relationship\n'), ((1059, 1104), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'foreign_key': '"""address.id"""'}), "(default=None, foreign_key='address.id')\n", (1064, 1104), False, 'from sqlmodel import SQLModel, Field, Relationship\n'), ((1138, 1227), 'sqlmodel.Relationship', 'Relationship', ([], {'back_populates': '"""customers"""', 'sa_relationship_kwargs': "{'lazy': 'selectin'}"}), "(back_populates='customers', sa_relationship_kwargs={'lazy':\n    'selectin'})\n", (1150, 1227), False, 'from sqlmodel import SQLModel, Field, Relationship\n'), ((1461, 1582), 'sqlmodel.Relationship', 'Relationship', ([], {'back_populates': '"""customers"""', 'link_model': 'CustomerProductLink', 'sa_relationship_kwargs': "{'lazy': 'selectin'}"}), "(back_populates='customers', link_model=CustomerProductLink,\n    sa_relationship_kwargs={'lazy': 'selectin'})\n", (1473, 1582), False, 'from sqlmodel import SQLModel, Field, Relationship\n'), ((1890, 1927), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'primary_key': '(True)'}), '(default=None, primary_key=True)\n', (1895, 1927), False, 'from sqlmodel import SQLModel, Field, Relationship\n'), ((2030, 2101), 'sqlmodel.Relationship', 'Relationship', ([], {'back_populates': '"""products"""', 'link_model': 'CustomerProductLink'}), "(back_populates='products', link_model=CustomerProductLink)\n", (2042, 2101), False, 'from sqlmodel import SQLModel, Field, Relationship\n'), ((1311, 1355), 'sqlalchemy.sql.schema.Column', 'Column', (['"""mobile_number"""', 'String'], {'unique': '(True)'}), "('mobile_number', String, unique=True)\n", (1317, 1355), False, 'from sqlalchemy.sql.schema import Column\n'), ((1390, 1426), 'sqlalchemy.sql.schema.Column', 'Column', (['"""email"""', 'String'], {'unique': '(True)'}), "('email', String, unique=True)\n", (1396, 1426), False, 'from sqlalchemy.sql.schema import Column\n'), ((1960, 1995), 'sqlalchemy.sql.schema.Column', 'Column', (['"""name"""', 'String'], {'unique': '(True)'}), "('name', String, unique=True)\n", (1966, 1995), False, 'from sqlalchemy.sql.schema import Column\n')]