"""
Pydantic schemas for payment-related requests and responses.
"""
from pydantic import BaseModel, Field, field_validator
from typing import Optional


class CreatePaymentRequest(BaseModel):
    """Schema for creating a payment."""
    booking_id: int = Field(..., gt=0, description="Booking ID")
    amount: float = Field(..., gt=0, le=999999.99, description="Payment amount")
    payment_method: str = Field(..., description="Payment method")
    payment_type: str = Field("full", description="Payment type (full, deposit)")
    mark_as_paid: Optional[bool] = Field(False, description="Mark payment as completed immediately")
    notes: Optional[str] = Field(None, max_length=1000, description="Payment notes")
    idempotency_key: Optional[str] = Field(None, max_length=255, description="Idempotency key to prevent duplicate payments")

    @field_validator('payment_method')
    @classmethod
    def validate_payment_method(cls, v: str) -> str:
        """Validate payment method."""
        allowed_methods = ['cash', 'stripe', 'paypal', 'borica']
        if v not in allowed_methods:
            raise ValueError(f'Payment method must be one of: {", ".join(allowed_methods)}')
        return v


class UpdatePaymentStatusRequest(BaseModel):
    """Schema for updating payment status."""
    status: str = Field(..., description="New payment status")
    notes: Optional[str] = Field(None, max_length=1000, description="Status change notes")

    @field_validator('status')
    @classmethod
    def validate_status(cls, v: str) -> str:
        """Validate payment status."""
        allowed_statuses = ['pending', 'completed', 'failed', 'refunded', 'cancelled']
        if v not in allowed_statuses:
            raise ValueError(f'Status must be one of: {", ".join(allowed_statuses)}')
        return v


class CreateStripePaymentIntentRequest(BaseModel):
    """Schema for creating a Stripe payment intent."""
    booking_id: int = Field(..., gt=0, description="Booking ID")
    amount: float = Field(..., gt=0, le=999999.99, description="Payment amount")
    currency: Optional[str] = Field("usd", description="Currency code")

    @field_validator('amount')
    @classmethod
    def validate_amount(cls, v: float) -> float:
        """Validate amount doesn't exceed Stripe limit."""
        if v > 999999.99:
            raise ValueError(f"Amount ${v:,.2f} exceeds Stripe's maximum of $999,999.99")
        return v

    @field_validator('currency')
    @classmethod
    def validate_currency(cls, v: Optional[str]) -> Optional[str]:
        """Validate currency code."""
        if v:
            # Basic currency code validation (3 uppercase letters)
            if not v.isupper() or len(v) != 3 or not v.isalpha():
                raise ValueError('Currency must be a valid 3-letter uppercase code (e.g., USD, EUR)')
        return v


class ConfirmStripePaymentRequest(BaseModel):
    """Schema for confirming a Stripe payment."""
    payment_intent_id: str = Field(..., min_length=1, max_length=255, description="Stripe payment intent ID")
    booking_id: Optional[int] = Field(None, gt=0, description="Optional booking ID for validation")


class CreatePayPalOrderRequest(BaseModel):
    """Schema for creating a PayPal order."""
    booking_id: int = Field(..., gt=0, description="Booking ID")
    amount: float = Field(..., gt=0, le=999999.99, description="Payment amount")
    currency: Optional[str] = Field("USD", description="Currency code")

    @field_validator('currency')
    @classmethod
    def validate_currency(cls, v: Optional[str]) -> Optional[str]:
        """Validate currency code."""
        if v:
            if not v.isupper() or len(v) != 3 or not v.isalpha():
                raise ValueError('Currency must be a valid 3-letter uppercase code (e.g., USD, EUR)')
        return v


class CancelPayPalPaymentRequest(BaseModel):
    """Schema for canceling a PayPal payment."""
    order_id: str = Field(..., min_length=1, max_length=255, description="PayPal order ID")
    booking_id: Optional[int] = Field(None, gt=0, description="Optional booking ID")


class CapturePayPalPaymentRequest(BaseModel):
    """Schema for capturing a PayPal payment."""
    order_id: str = Field(..., min_length=1, max_length=255, description="PayPal order ID")
    booking_id: Optional[int] = Field(None, gt=0, description="Optional booking ID")


class CreateBoricaPaymentRequest(BaseModel):
    """Schema for creating a Borica payment."""
    booking_id: int = Field(..., gt=0, description="Booking ID")
    amount: float = Field(..., gt=0, le=999999.99, description="Payment amount")
    currency: Optional[str] = Field("BGN", description="Currency code (default: BGN)")

    @field_validator('currency')
    @classmethod
    def validate_currency(cls, v: Optional[str]) -> Optional[str]:
        """Validate currency code."""
        if v:
            if not v.isupper() or len(v) != 3 or not v.isalpha():
                raise ValueError('Currency must be a valid 3-letter uppercase code (e.g., BGN, USD)')
        return v


class ConfirmBoricaPaymentRequest(BaseModel):
    """Schema for confirming a Borica payment (webhook)."""
    response_data: dict = Field(..., description="Borica payment response data")
