from datetime import date, datetime
from typing import Any, Dict, Optional
from uuid import UUID, uuid4

from pydantic.class_validators import root_validator
from sqlmodel import Column, Enum, Field, SQLModel
from sqlmodel.sql.sqltypes import GUID

from ...utils.date import now_datetime
from ..constants import OperationType, PaymentType, SaleType


class BaseBalance(SQLModel):
    value: float = Field(description="Value of operation")
    operation: OperationType = Field(
        description="Type of operation", sa_column=Column(Enum(OperationType), nullable=False)
    )
    description: str = Field(description="Description of operation", min_length=1)
    created_at: datetime = Field(default_factory=now_datetime)


class CreateBalance(BaseBalance):
    @root_validator()
    def normalize_value(cls, values: Dict[str, Any]) -> float:
        operation_type = values.get("operation")
        value = values.get("value")

        if not operation_type or not value:
            return values

        if any(operation_type.name == payment_type.name for payment_type in PaymentType) and value > 0:
            values["value"] = value * -1

        if any(operation_type.name == sale_type.name for sale_type in SaleType) and value < 0:
            values["value"] = value * -1

        return values


class QueryBalance(SQLModel):
    start_date: Optional[date] = Field(description="Initial date for query")
    end_date: Optional[date] = Field(description="End date for query")


class Balance(BaseBalance, table=True):
    id: UUID = Field(default_factory=uuid4, sa_column=Column("id", GUID(), primary_key=True))
    owner_id: UUID = Field(description="User ID that owns the balance", foreign_key="users.id")

sqlmodel.sql.sqltypes.GUID pydantic.class_validators.root_validator sqlmodel.Enum sqlmodel.Field
[((399, 438), 'sqlmodel.Field', 'Field', ([], {'description': '"""Value of operation"""'}), "(description='Value of operation')\n", (404, 438), False, 'from sqlmodel import Column, Enum, Field, SQLModel\n'), ((601, 660), 'sqlmodel.Field', 'Field', ([], {'description': '"""Description of operation"""', 'min_length': '(1)'}), "(description='Description of operation', min_length=1)\n", (606, 660), False, 'from sqlmodel import Column, Enum, Field, SQLModel\n'), ((688, 723), 'sqlmodel.Field', 'Field', ([], {'default_factory': 'now_datetime'}), '(default_factory=now_datetime)\n', (693, 723), False, 'from sqlmodel import Column, Enum, Field, SQLModel\n'), ((765, 781), 'pydantic.class_validators.root_validator', 'root_validator', ([], {}), '()\n', (779, 781), False, 'from pydantic.class_validators import root_validator\n'), ((1372, 1415), 'sqlmodel.Field', 'Field', ([], {'description': '"""Initial date for query"""'}), "(description='Initial date for query')\n", (1377, 1415), False, 'from sqlmodel import Column, Enum, Field, SQLModel\n'), ((1447, 1486), 'sqlmodel.Field', 'Field', ([], {'description': '"""End date for query"""'}), "(description='End date for query')\n", (1452, 1486), False, 'from sqlmodel import Column, Enum, Field, SQLModel\n'), ((1644, 1718), 'sqlmodel.Field', 'Field', ([], {'description': '"""User ID that owns the balance"""', 'foreign_key': '"""users.id"""'}), "(description='User ID that owns the balance', foreign_key='users.id')\n", (1649, 1718), False, 'from sqlmodel import Column, Enum, Field, SQLModel\n'), ((535, 554), 'sqlmodel.Enum', 'Enum', (['OperationType'], {}), '(OperationType)\n', (539, 554), False, 'from sqlmodel import Column, Enum, Field, SQLModel\n'), ((1596, 1602), 'sqlmodel.sql.sqltypes.GUID', 'GUID', ([], {}), '()\n', (1600, 1602), False, 'from sqlmodel.sql.sqltypes import GUID\n')]