from pydantic import BaseModel, Field, ConfigDict, field_validator
from typing import Optional, List
from datetime import datetime
from decimal import Decimal
from enum import Enum


class OrderStatus(str, Enum):
    PENDING = "PENDING"
    PAID = "PAID"
    PROCESSING = "PROCESSING"
    SHIPPED = "SHIPPED"
    DELIVERED = "DELIVERED"
    CANCELLED = "CANCELLED"
    REFUNDED = "REFUNDED"
    DISPUTED = "DISPUTED"


class PaymentMethod(str, Enum):
    CREDIT_CARD = "CREDIT_CARD"
    DEBIT_CARD = "DEBIT_CARD"
    PAYPAL = "PAYPAL"
    STRIPE = "STRIPE"
    BANK_TRANSFER = "BANK_TRANSFER"


class PaymentStatus(str, Enum):
    PENDING = "PENDING"
    PROCESSING = "PROCESSING"
    COMPLETED = "COMPLETED"
    FAILED = "FAILED"
    REFUNDED = "REFUNDED"
    CANCELLED = "CANCELLED"


class ShipmentStatus(str, Enum):
    PENDING = "PENDING"
    LABEL_CREATED = "LABEL_CREATED"
    IN_TRANSIT = "IN_TRANSIT"
    OUT_FOR_DELIVERY = "OUT_FOR_DELIVERY"
    DELIVERED = "DELIVERED"
    FAILED = "FAILED"
    RETURNED = "RETURNED"


# Order schemas
class OrderBase(BaseModel):
    order_number: str = Field(..., min_length=1, max_length=50)
    buyer_id: str = Field(..., min_length=36, max_length=36)
    seller_id: str = Field(..., min_length=36, max_length=36)
    status: OrderStatus
    subtotal: Decimal = Field(..., ge=0)
    shipping_cost: Decimal = Field(..., ge=0)
    tax_amount: Decimal = Field(..., ge=0)
    platform_fee: Decimal = Field(..., ge=0)
    total_amount: Decimal = Field(..., ge=0)
    shipping_address_id: str = Field(..., min_length=36, max_length=36)
    billing_address_id: str = Field(..., min_length=36, max_length=36)
    notes: Optional[str] = None
    cancelled_at: Optional[datetime] = None
    cancellation_reason: Optional[str] = None

    @field_validator("total_amount")
    @classmethod
    def validate_total_amount(cls, v: Decimal, info) -> Decimal:
        if v <= 0:
            raise ValueError("Total amount must be greater than zero")
        return v


class OrderCreate(OrderBase):
    pass


class OrderUpdate(BaseModel):
    order_number: Optional[str] = Field(None, min_length=1, max_length=50)
    buyer_id: Optional[str] = Field(None, min_length=36, max_length=36)
    seller_id: Optional[str] = Field(None, min_length=36, max_length=36)
    status: Optional[OrderStatus] = None
    subtotal: Optional[Decimal] = Field(None, ge=0)
    shipping_cost: Optional[Decimal] = Field(None, ge=0)
    tax_amount: Optional[Decimal] = Field(None, ge=0)
    platform_fee: Optional[Decimal] = Field(None, ge=0)
    total_amount: Optional[Decimal] = Field(None, ge=0)
    shipping_address_id: Optional[str] = Field(None, min_length=36, max_length=36)
    billing_address_id: Optional[str] = Field(None, min_length=36, max_length=36)
    notes: Optional[str] = None
    cancelled_at: Optional[datetime] = None
    cancellation_reason: Optional[str] = None


class OrderResponse(OrderBase):
    id: str
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


# Orderitem schemas
class OrderitemBase(BaseModel):
    order_id: str = Field(..., min_length=36, max_length=36)
    listing_id: str = Field(..., min_length=36, max_length=36)
    card_id: str = Field(..., min_length=36, max_length=36)
    quantity: int = Field(..., ge=1, le=999)
    price: Decimal = Field(..., ge=0.01)
    condition: str = Field(..., min_length=1, max_length=50)

    @field_validator("quantity")
    @classmethod
    def validate_quantity(cls, v: int) -> int:
        if v < 1 or v > 999:
            raise ValueError("Quantity must be between 1 and 999")
        return v


class OrderitemCreate(OrderitemBase):
    pass


class OrderitemUpdate(BaseModel):
    order_id: Optional[str] = Field(None, min_length=36, max_length=36)
    listing_id: Optional[str] = Field(None, min_length=36, max_length=36)
    card_id: Optional[str] = Field(None, min_length=36, max_length=36)
    quantity: Optional[int] = Field(None, ge=1, le=999)
    price: Optional[Decimal] = Field(None, ge=0.01)
    condition: Optional[str] = Field(None, min_length=1, max_length=50)


class OrderitemResponse(OrderitemBase):
    id: str
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


# Payment schemas
class PaymentBase(BaseModel):
    order_id: str = Field(..., min_length=36, max_length=36)
    payment_method: PaymentMethod
    amount: Decimal = Field(..., ge=0.01)
    currency: str = Field(..., min_length=3, max_length=3)
    status: PaymentStatus
    transaction_id: Optional[str] = Field(None, max_length=255)
    payment_gateway: Optional[str] = Field(None, max_length=50)
    payment_details: Optional[str] = None
    processed_at: Optional[datetime] = None

    @field_validator("amount")
    @classmethod
    def validate_amount(cls, v: Decimal) -> Decimal:
        if v <= 0:
            raise ValueError("Payment amount must be positive")
        return v


class PaymentCreate(PaymentBase):
    pass


class PaymentUpdate(BaseModel):
    order_id: Optional[str] = Field(None, min_length=36, max_length=36)
    payment_method: Optional[PaymentMethod] = None
    amount: Optional[Decimal] = Field(None, ge=0.01)
    currency: Optional[str] = Field(None, min_length=3, max_length=3)
    status: Optional[PaymentStatus] = None
    transaction_id: Optional[str] = Field(None, max_length=255)
    payment_gateway: Optional[str] = Field(None, max_length=50)
    payment_details: Optional[str] = None
    processed_at: Optional[datetime] = None


class PaymentResponse(PaymentBase):
    id: str
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


# Shipment schemas
class ShipmentBase(BaseModel):
    order_id: str = Field(..., min_length=36, max_length=36)
    carrier: str = Field(..., min_length=1, max_length=100)
    tracking_number: Optional[str] = Field(None, max_length=255)
    shipping_method: Optional[str] = Field(None, max_length=100)
    status: ShipmentStatus
    shipped_at: Optional[datetime] = None
    estimated_delivery_date: Optional[datetime] = None
    delivered_at: Optional[datetime] = None


class ShipmentCreate(ShipmentBase):
    pass


class ShipmentUpdate(BaseModel):
    order_id: Optional[str] = Field(None, min_length=36, max_length=36)
    carrier: Optional[str] = Field(None, min_length=1, max_length=100)
    tracking_number: Optional[str] = Field(None, max_length=255)
    shipping_method: Optional[str] = Field(None, max_length=100)
    status: Optional[ShipmentStatus] = None
    shipped_at: Optional[datetime] = None
    estimated_delivery_date: Optional[datetime] = None
    delivered_at: Optional[datetime] = None


class ShipmentResponse(ShipmentBase):
    id: str
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


# Detail response schemas
class OrderitemDetailResponse(BaseModel):
    id: str
    order_id: str
    listing_id: str
    card_id: str
    quantity: int
    price: Decimal
    condition: str
    listing_title: str
    card_name: str
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


class OrderDetailResponse(BaseModel):
    id: str
    order_number: str
    buyer_id: str
    seller_id: str
    status: OrderStatus
    subtotal: Decimal
    shipping_cost: Decimal
    tax_amount: Decimal
    platform_fee: Decimal
    total_amount: Decimal
    shipping_address_id: str
    billing_address_id: str
    notes: Optional[str]
    cancelled_at: Optional[datetime]
    cancellation_reason: Optional[str]
    buyer_email: str
    seller_email: str
    seller_store_name: Optional[str]
    order_items: List[OrderitemDetailResponse]
    payment_status: Optional[PaymentStatus]
    shipment_tracking_number: Optional[str]
    shipping_address_line1: str
    billing_address_line1: str
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)