import uuid
from datetime import datetime
from decimal import Decimal
from typing import Any

from pydantic import BaseModel, ConfigDict, Field


class OrderCreate(BaseModel):
    product_id: uuid.UUID | None = None
    flow: str | None = None
    input_data: dict[str, Any] = Field(default_factory=dict)


class OrderInputUpdate(BaseModel):
    input_data: dict[str, Any]


class CouponApply(BaseModel):
    code: str = Field(min_length=2, max_length=32)


class OrderStatusUpdate(BaseModel):
    status: str
    note: str | None = None


class PaymentOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: uuid.UUID
    order_id: uuid.UUID
    method: str
    status: str
    amount: Decimal
    currency: str
    original_amount: Decimal | None = None
    payable_amount: Decimal | None = None
    pay_currency: str | None = None
    wallet_address: str | None = None
    tx_hash: str | None = None
    receipt_image: str | None = None
    expires_at: datetime | None = None
    paid_at: datetime | None = None
    note: str | None = None
    created_at: datetime


class OrderOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: uuid.UUID
    order_number: str
    user_id: uuid.UUID
    product_id: uuid.UUID | None = None
    status: str
    payment_status: str
    payment_method: str | None = None
    quantity: int
    price: Decimal
    discount: Decimal
    final_price: Decimal
    currency: str
    input_data: dict[str, Any]
    product_snapshot: dict[str, Any]
    result_data: dict[str, Any]
    error_message: str | None = None
    completed_at: datetime | None = None
    created_at: datetime


class OrderDetailOut(OrderOut):
    payments: list[PaymentOut] = Field(default_factory=list)
    summary: dict[str, Any] = Field(default_factory=dict)


class PaymentCreate(BaseModel):
    order_id: uuid.UUID
    method: str = Field(pattern="^(wallet|tron|bank)$")


class ReceiptUpload(BaseModel):
    payment_id: uuid.UUID
    receipt_image: str


class ManualPaymentAction(BaseModel):
    note: str | None = None
