from datetime import datetime
from typing import TYPE_CHECKING, List, Optional
from uuid import UUID, uuid4

from pydantic import EmailStr, constr, validator
from sqlmodel import Column, Field, Relationship, SQLModel
from sqlmodel.sql.sqltypes import GUID

from ...utils.date import now_datetime

if TYPE_CHECKING:
    from .order import Order
    from .user import User


class BaseClient(SQLModel):
    name: str = Field(description="Client name")
    email: Optional[EmailStr] = Field(description="Client email", nullable=True)
    phone: Optional[constr(regex=r"^\d{2}9\d{8}$")] = Field(description="Client cellphone", nullable=True)  # noqa
    zip_code: Optional[str] = Field(description="Postal code", nullable=True)
    address: Optional[str] = Field(description="Address of Client", nullable=True)

    @validator("name")
    def validate_name(cls, value: str) -> str:
        return value.title()


class CreateClient(BaseClient):
    pass


class UpdateClient(BaseClient):
    id: UUID = Field(description="Client ID")


class QueryClient(SQLModel):
    name: Optional[str] = Field(description="Name of client for query")


class Client(BaseClient, table=True):
    __tablename__ = "clients"

    id: UUID = Field(default_factory=uuid4, description="Client ID", sa_column=Column("id", GUID(), primary_key=True))
    owner_id: UUID = Field(description="User ID that owns the client", foreign_key="users.id")
    created_at: datetime = Field(default_factory=now_datetime)

    owner: "User" = Relationship()
    orders: List["Order"] = Relationship(
        back_populates="client",
        sa_relationship_kwargs={"cascade": "all,delete", "lazy": "selectin", "passive_deletes": True},
    )

pydantic.validator pydantic.constr sqlmodel.Field sqlmodel.sql.sqltypes.GUID sqlmodel.Relationship
[((417, 449), 'sqlmodel.Field', 'Field', ([], {'description': '"""Client name"""'}), "(description='Client name')\n", (422, 449), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((482, 530), 'sqlmodel.Field', 'Field', ([], {'description': '"""Client email"""', 'nullable': '(True)'}), "(description='Client email', nullable=True)\n", (487, 530), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((585, 637), 'sqlmodel.Field', 'Field', ([], {'description': '"""Client cellphone"""', 'nullable': '(True)'}), "(description='Client cellphone', nullable=True)\n", (590, 637), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((676, 723), 'sqlmodel.Field', 'Field', ([], {'description': '"""Postal code"""', 'nullable': '(True)'}), "(description='Postal code', nullable=True)\n", (681, 723), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((753, 806), 'sqlmodel.Field', 'Field', ([], {'description': '"""Address of Client"""', 'nullable': '(True)'}), "(description='Address of Client', nullable=True)\n", (758, 806), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((813, 830), 'pydantic.validator', 'validator', (['"""name"""'], {}), "('name')\n", (822, 830), False, 'from pydantic import EmailStr, constr, validator\n'), ((999, 1029), 'sqlmodel.Field', 'Field', ([], {'description': '"""Client ID"""'}), "(description='Client ID')\n", (1004, 1029), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((1087, 1132), 'sqlmodel.Field', 'Field', ([], {'description': '"""Name of client for query"""'}), "(description='Name of client for query')\n", (1092, 1132), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((1344, 1417), 'sqlmodel.Field', 'Field', ([], {'description': '"""User ID that owns the client"""', 'foreign_key': '"""users.id"""'}), "(description='User ID that owns the client', foreign_key='users.id')\n", (1349, 1417), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((1445, 1480), 'sqlmodel.Field', 'Field', ([], {'default_factory': 'now_datetime'}), '(default_factory=now_datetime)\n', (1450, 1480), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((1502, 1516), 'sqlmodel.Relationship', 'Relationship', ([], {}), '()\n', (1514, 1516), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((1545, 1681), 'sqlmodel.Relationship', 'Relationship', ([], {'back_populates': '"""client"""', 'sa_relationship_kwargs': "{'cascade': 'all,delete', 'lazy': 'selectin', 'passive_deletes': True}"}), "(back_populates='client', sa_relationship_kwargs={'cascade':\n    'all,delete', 'lazy': 'selectin', 'passive_deletes': True})\n", (1557, 1681), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((551, 582), 'pydantic.constr', 'constr', ([], {'regex': '"""^\\\\d{2}9\\\\d{8}$"""'}), "(regex='^\\\\d{2}9\\\\d{8}$')\n", (557, 582), False, 'from pydantic import EmailStr, constr, validator\n'), ((1296, 1302), 'sqlmodel.sql.sqltypes.GUID', 'GUID', ([], {}), '()\n', (1300, 1302), False, 'from sqlmodel.sql.sqltypes import GUID\n')]