import uuid
from datetime import datetime
from typing import Optional
from sqlalchemy import UniqueConstraint

from sqlmodel import Field, Relationship
from pydantic_factories import ModelFactory, Use
from faker import Faker
from api.db.models.base import BaseModel, BaseTable


class StudentBase(BaseModel):
    name: str = Field(index=True, nullable=False)
    sandbox_id: uuid.UUID = None

    # faber line of business data for student degree credentials
    degree: Optional[str] = Field(default=None, nullable=True)
    age: Optional[int] = Field(default=None, nullable=True)
    student_id: Optional[str] = Field(default=None, nullable=True)
    date: Optional[datetime] = Field(default=None, nullable=True)

    # track invitation information
    # this is for this LOB to track this entity in Traction
    invitation_state: Optional[str] = Field(default=None, nullable=True)
    connection_id: Optional[uuid.UUID] = Field(default=None)

    # for matching this student with their traction tenant
    # this would not be in this LOB data at all!!!
    # the entity/person/business that this record represents
    # would be tracking this in their system/data
    wallet_id: Optional[uuid.UUID] = None
    alias: Optional[str] = Field(default=None, nullable=True)


class Student(StudentBase, BaseTable, table=True):
    __table_args__ = (UniqueConstraint("name", "sandbox_id"),)

    sandbox: Optional["Sandbox"] = Relationship(back_populates="students")  # noqa: F821

    sandbox_id: uuid.UUID = Field(foreign_key="sandbox.id")
    wallet_id: uuid.UUID = Field(default=None, nullable=True)


class StudentCreate(StudentBase):
    pass


class StudentRead(StudentBase):
    id: uuid.UUID
    created_at: datetime
    updated_at: datetime
    degree: Optional[str] = None
    age: Optional[int] = None
    student_id: Optional[str] = None
    date: Optional[datetime] = None


class StudentUpdate(StudentBase):
    name: Optional[str] = None


# FACTORIES


class StudentCreateFactory(ModelFactory):
    __model__ = StudentCreate

    name = Use(Faker().name)
    degree = None
    age = None
    student_id = None
    date = None
    wallet_id = None
    alias = None
    invitation_state = None
    connection_id = None

sqlalchemy.UniqueConstraint faker.Faker sqlmodel.Relationship sqlmodel.Field
[((325, 358), 'sqlmodel.Field', 'Field', ([], {'index': '(True)', 'nullable': '(False)'}), '(index=True, nullable=False)\n', (330, 358), False, 'from sqlmodel import Field, Relationship\n'), ((486, 520), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'nullable': '(True)'}), '(default=None, nullable=True)\n', (491, 520), False, 'from sqlmodel import Field, Relationship\n'), ((546, 580), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'nullable': '(True)'}), '(default=None, nullable=True)\n', (551, 580), False, 'from sqlmodel import Field, Relationship\n'), ((613, 647), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'nullable': '(True)'}), '(default=None, nullable=True)\n', (618, 647), False, 'from sqlmodel import Field, Relationship\n'), ((679, 713), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'nullable': '(True)'}), '(default=None, nullable=True)\n', (684, 713), False, 'from sqlmodel import Field, Relationship\n'), ((848, 882), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'nullable': '(True)'}), '(default=None, nullable=True)\n', (853, 882), False, 'from sqlmodel import Field, Relationship\n'), ((924, 943), 'sqlmodel.Field', 'Field', ([], {'default': 'None'}), '(default=None)\n', (929, 943), False, 'from sqlmodel import Field, Relationship\n'), ((1235, 1269), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'nullable': '(True)'}), '(default=None, nullable=True)\n', (1240, 1269), False, 'from sqlmodel import Field, Relationship\n'), ((1422, 1461), 'sqlmodel.Relationship', 'Relationship', ([], {'back_populates': '"""students"""'}), "(back_populates='students')\n", (1434, 1461), False, 'from sqlmodel import Field, Relationship\n'), ((1505, 1536), 'sqlmodel.Field', 'Field', ([], {'foreign_key': '"""sandbox.id"""'}), "(foreign_key='sandbox.id')\n", (1510, 1536), False, 'from sqlmodel import Field, Relationship\n'), ((1564, 1598), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'nullable': '(True)'}), '(default=None, nullable=True)\n', (1569, 1598), False, 'from sqlmodel import Field, Relationship\n'), ((1345, 1383), 'sqlalchemy.UniqueConstraint', 'UniqueConstraint', (['"""name"""', '"""sandbox_id"""'], {}), "('name', 'sandbox_id')\n", (1361, 1383), False, 'from sqlalchemy import UniqueConstraint\n'), ((2053, 2060), 'faker.Faker', 'Faker', ([], {}), '()\n', (2058, 2060), False, 'from faker import Faker\n')]