from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from uuid import UUID, uuid4

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

if TYPE_CHECKING:
    from .user import User


class BaseItem(SQLModel):
    code: str = Field(description="Item code", min_length=1)
    name: str = Field(description="Item Name", min_length=1)
    cost: Optional[float] = Field(description="Production/Buy cost of the item", ge=0)
    value: PositiveFloat = Field(description="Sugested sell value of item")
    amount: int = Field(default=0, description="Quantity of itens avaliable", ge=0)


class CreateItem(BaseItem):
    @validator("value")
    def validate_value(cls, value: Union[str, float], values: Dict[str, Any]) -> float:
        if isinstance(value, str):
            if "," in value and "." not in value:
                value = value.replace(",", ".")

            value = float(value)

        if (values.get("cost") or 0) >= value:
            raise ValueError("The sugested sell value must be higher then buy value!")

        return value


class UpdateItem(BaseItem):
    id: UUID = Field(description="ID do item")

    @validator("value")
    def validate_value(cls, value: Union[str, float], values: Dict[str, Any]) -> float:
        if isinstance(value, str):
            value = float(value)

        if (values.get("cost") or 0) >= value:
            raise ValueError("The sugested sell value must be higher then buy value!")

        return value


class QueryItem(SQLModel):
    name: Optional[str] = Field(description="Name of the item for query")
    code: Optional[str] = Field(description="Code of the item for query")
    avaliable: Optional[bool] = Field(description="Flag to identify if the item is avaliable")


class Item(BaseItem, table=True):
    __tablename__ = "items"

    id: UUID = Field(default_factory=uuid4, description="ID do item", sa_column=Column("id", GUID(), primary_key=True))
    owner_id: UUID = Field(description="User ID that owns the file", foreign_key="users.id")
    owner: "User" = Relationship()

    @property
    def avaliable(self) -> bool:
        return self.amount > 0

sqlmodel.sql.sqltypes.GUID sqlmodel.Relationship sqlmodel.Field pydantic.validator
[((325, 369), 'sqlmodel.Field', 'Field', ([], {'description': '"""Item code"""', 'min_length': '(1)'}), "(description='Item code', min_length=1)\n", (330, 369), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((386, 430), 'sqlmodel.Field', 'Field', ([], {'description': '"""Item Name"""', 'min_length': '(1)'}), "(description='Item Name', min_length=1)\n", (391, 430), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((459, 517), 'sqlmodel.Field', 'Field', ([], {'description': '"""Production/Buy cost of the item"""', 'ge': '(0)'}), "(description='Production/Buy cost of the item', ge=0)\n", (464, 517), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((545, 593), 'sqlmodel.Field', 'Field', ([], {'description': '"""Sugested sell value of item"""'}), "(description='Sugested sell value of item')\n", (550, 593), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((612, 677), 'sqlmodel.Field', 'Field', ([], {'default': '(0)', 'description': '"""Quantity of itens avaliable"""', 'ge': '(0)'}), "(default=0, description='Quantity of itens avaliable', ge=0)\n", (617, 677), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((713, 731), 'pydantic.validator', 'validator', (['"""value"""'], {}), "('value')\n", (722, 731), False, 'from pydantic import PositiveFloat, validator\n'), ((1189, 1220), 'sqlmodel.Field', 'Field', ([], {'description': '"""ID do item"""'}), "(description='ID do item')\n", (1194, 1220), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((1227, 1245), 'pydantic.validator', 'validator', (['"""value"""'], {}), "('value')\n", (1236, 1245), False, 'from pydantic import PositiveFloat, validator\n'), ((1614, 1661), 'sqlmodel.Field', 'Field', ([], {'description': '"""Name of the item for query"""'}), "(description='Name of the item for query')\n", (1619, 1661), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((1688, 1735), 'sqlmodel.Field', 'Field', ([], {'description': '"""Code of the item for query"""'}), "(description='Code of the item for query')\n", (1693, 1735), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((1768, 1830), 'sqlmodel.Field', 'Field', ([], {'description': '"""Flag to identify if the item is avaliable"""'}), "(description='Flag to identify if the item is avaliable')\n", (1773, 1830), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((2037, 2108), 'sqlmodel.Field', 'Field', ([], {'description': '"""User ID that owns the file"""', 'foreign_key': '"""users.id"""'}), "(description='User ID that owns the file', foreign_key='users.id')\n", (2042, 2108), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((2129, 2143), 'sqlmodel.Relationship', 'Relationship', ([], {}), '()\n', (2141, 2143), False, 'from sqlmodel import Column, Field, Relationship, SQLModel\n'), ((1989, 1995), 'sqlmodel.sql.sqltypes.GUID', 'GUID', ([], {}), '()\n', (1993, 1995), False, 'from sqlmodel.sql.sqltypes import GUID\n')]