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


class CancellationRequestStatus(str, Enum):
    PENDING = "pending"
    APPROVED = "approved"
    REJECTED = "rejected"
    PROCESSED = "processed"


class CancellationrequestBase(BaseModel):
    booking_id: str = Field(..., min_length=36, max_length=36)
    customer_id: str = Field(..., min_length=36, max_length=36)
    reason: str = Field(..., min_length=1)
    requested_date: datetime
    cancellation_fee: Decimal = Field(..., ge=0)
    refund_amount: Decimal = Field(..., ge=0)
    status: CancellationRequestStatus = CancellationRequestStatus.PENDING
    processed_by: Optional[str] = Field(None, min_length=36, max_length=36)
    processed_date: Optional[datetime] = None
    admin_notes: Optional[str] = None

    @field_validator("cancellation_fee", "refund_amount")
    @classmethod
    def validate_amounts(cls, v: Decimal) -> Decimal:
        if v < 0:
            raise ValueError("Amount must be greater than or equal to zero")
        return v

    @field_validator("reason")
    @classmethod
    def validate_reason(cls, v: str) -> str:
        if not v or not v.strip():
            raise ValueError("Cancellation reason cannot be empty")
        return v.strip()


class CancellationrequestCreate(CancellationrequestBase):
    pass


class CancellationrequestUpdate(BaseModel):
    booking_id: Optional[str] = Field(None, min_length=36, max_length=36)
    customer_id: Optional[str] = Field(None, min_length=36, max_length=36)
    reason: Optional[str] = None
    requested_date: Optional[datetime] = None
    cancellation_fee: Optional[Decimal] = None
    refund_amount: Optional[Decimal] = None
    status: Optional[CancellationRequestStatus] = None
    processed_by: Optional[str] = Field(None, min_length=36, max_length=36)
    processed_date: Optional[datetime] = None
    admin_notes: Optional[str] = None

    @field_validator("cancellation_fee", "refund_amount")
    @classmethod
    def validate_amounts(cls, v: Optional[Decimal]) -> Optional[Decimal]:
        if v is not None and v < 0:
            raise ValueError("Amount must be greater than or equal to zero")
        return v

    @field_validator("reason")
    @classmethod
    def validate_reason(cls, v: Optional[str]) -> Optional[str]:
        if v is not None and (not v or not v.strip()):
            raise ValueError("Cancellation reason cannot be empty")
        return v.strip() if v else None


class CancellationrequestResponse(CancellationrequestBase):
    id: str
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


class CancellationrequestDetailResponse(BaseModel):
    id: str
    booking_id: str
    customer_id: str
    reason: str
    requested_date: datetime
    cancellation_fee: Decimal
    refund_amount: Decimal
    status: CancellationRequestStatus
    processed_by: Optional[str]
    processed_date: Optional[datetime]
    admin_notes: Optional[str]
    created_at: datetime
    updated_at: datetime
    booking: Optional[dict] = None
    customer: Optional[dict] = None
    processor: Optional[dict] = None

    model_config = ConfigDict(from_attributes=True)