from typing import Optional
from pydantic import Field, field_validator, ConfigDict
from src.core.database import SessionCelery
from src.apps.products.schemas.product_common import ProductSchema
from src.apps.base.schemas.common import BaseSchema
from sqlalchemy.orm import Session
from src.apps.products.repository.common import product_repository


class PaymentRequestProductBase(BaseSchema):
    model_config = ConfigDict(from_attributes=True)
    
    description: Optional[str] = Field(default=None, description="Description of product")
    unit_price: Optional[float] = Field(default=None, description="Price of line item")
    quantity: Optional[int] = Field(default=None, ge=1, description="Quantity of Product")
    is_taxable: Optional[bool] = Field(
        default=True, description="Is this Product taxable?"
    )
    tax_percent: Optional[float] = Field(
        default=None, ge=0, le=100, description="Tax percentage, if applicable"
    )
    order: Optional[int] = Field(
        default=None, ge=0, le=999999, description="Sort Order of the product"
    )


class PaymentRequestProductSchema(PaymentRequestProductBase):
    model_config = ConfigDict(from_attributes=True)
    
    id: int = Field(description="Id of Payment Request Product resource")
    product: Optional[ProductSchema] = Field(default=None, description="Associated Product, if any")


class PaymentRequestProductCreate(PaymentRequestProductBase):
    model_config = ConfigDict(from_attributes=True)
    
    description: str = Field(description="Description of product")
    unit_price: float = Field(description="Price of line item")
    quantity: int = Field(ge=1, description="Quantity of Product")
    is_taxable: bool = Field(default=True, description="Is this Product taxable?")
    product_slug: Optional[str] = Field(
        default=None,
        description="Unique Slug of the associated Product, if any"
    )

    @field_validator("unit_price")
    @classmethod
    def validate_unit_price(cls, v):
        if v < 100:
            raise ValueError("Unit price must be greater than $1")
        if v > 999999999:
            raise ValueError("Unit price cannot be greater than $999999")
        return v

    @field_validator("product_slug")
    @classmethod
    def validate_product_slug(cls, v):
        if v:
            with SessionCelery() as db:
                exists = product_repository.get_one(
                    db=db, slug=v, deleted_at=None, is_active=True
                )
                if not exists:
                    raise ValueError(f"The product {v} was not found.")
        return v


class PaymentRequestProductUpdate(PaymentRequestProductBase):
    model_config = ConfigDict(from_attributes=True)
    
    object_id: Optional[int] = Field(default=None, description="ID of the item")
    product_slug: Optional[str] = Field(
        default=None,
        description="Unique Slug of the Associated Product"
    )

    @field_validator("unit_price")
    @classmethod
    def validate_unit_price(cls, v):
        if v < 100:
            raise ValueError("Unit price must be greater than $1")
        if v > 999999999:
            raise ValueError("Unit price cannot be greater than $999999")
        return v

    @field_validator("product_slug")
    @classmethod
    def validate_product_slug(cls, v):
        if v:
            with SessionCelery() as db:
                exists = product_repository.get_one(
                    db=db, slug=v, deleted_at=None, is_active=True
                )
                if not exists:
                    raise ValueError(f"The product {v} was not found.")
        return v
