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


class RefundStatus(str, Enum):
    PENDING = "pending"
    PROCESSED = "processed"
    FAILED = "failed"


class CancellationBase(BaseModel):
    booking_id: str
    user_id: str
    cancellation_datetime: datetime
    reason: Optional[str] = None
    refund_amount: float
    refund_status: str
    processed_at: Optional[datetime] = None

    @field_validator("refund_amount")
    @classmethod
    def validate_refund_amount(cls, v: float) -> float:
        if v < 0:
            raise ValueError("Refund amount must be a positive number")
        return v


class CancellationCreate(CancellationBase):
    pass


class CancellationUpdate(BaseModel):
    booking_id: Optional[str] = None
    user_id: Optional[str] = None
    cancellation_datetime: Optional[datetime] = None
    reason: Optional[str] = None
    refund_amount: Optional[float] = None
    refund_status: Optional[str] = None
    processed_at: Optional[datetime] = None

    @field_validator("refund_amount")
    @classmethod
    def validate_refund_amount(cls, v: Optional[float]) -> Optional[float]:
        if v is not None and v < 0:
            raise ValueError("Refund amount must be a positive number")
        return v


class CancellationResponse(CancellationBase):
    id: str
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


class CancellationDetailsResponse(BaseModel):
    id: str
    booking_id: str
    user_id: str
    cancellation_datetime: datetime
    reason: Optional[str]
    refund_amount: float
    refund_status: str
    processed_at: Optional[datetime]
    created_at: datetime
    updated_at: datetime
    booking_reference: str
    schedule_departure_datetime: datetime
    bus_number: str
    origin_city: str
    destination_city: str
    user_email: str
    user_first_name: str
    user_last_name: str

    model_config = ConfigDict(from_attributes=True)