from datetime import datetime
from typing import Any, Dict, Generic, List, Optional, TypeVar, Union

from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field, ConfigDict, create_model
from pydantic.generics import GenericModel
from starlette import status


T = TypeVar("T")


class ResponseModel(GenericModel, Generic[T]):
    """
    Base Response Model
    """

    model_config = ConfigDict(arbitrary_types_allowed=True)

    data: T = Field(default=None)
    status_code: int = status.HTTP_200_OK
    success: bool = True
    message: str = "Request handled successfully"


class ErrorResponseModel(BaseModel):
    """
    Base Error Model
    """

    model_config = ConfigDict(arbitrary_types_allowed=True)

    error: Any = {}
    status_code: int = status.HTTP_500_INTERNAL_SERVER_ERROR
    success: bool = False
    message: str = "Request could not be processed"


class WebhookResponse(BaseModel):
    result: str


class WebhookRequest(BaseModel):
    type: Optional[str] = Field(description="Type of event being fired")
    data: Optional[Dict] = Field(description="Event data payload")
    created_at: Optional[datetime] = Field(description="Created date and time")
    updated_at: Optional[datetime] = Field(description="Updated date and time")


def create_response(
    data: Any = None,
    message: str = "Request handled successfully",
    status_code: int = status.HTTP_200_OK,
) -> JSONResponse:
    """
    Create a consistent response format for all API endpoints
    """
    # Convert Pydantic models to dict for JSON serialization
    if isinstance(data, BaseModel):
        data = data.model_dump()
    elif isinstance(data, list) and len(data) > 0 and isinstance(data[0], BaseModel):
        data = [item.model_dump() if isinstance(item, BaseModel) else item for item in data]
    
    return JSONResponse(
        status_code=status_code,
        content={
            "data": data,
            "status_code": status_code,
            "success": 200 <= status_code < 300,
            "message": message,
        },
    )


def create_error_response(
    error: Any = None,
    message: str = "Request could not be processed",
    status_code: int = status.HTTP_500_INTERNAL_SERVER_ERROR,
) -> JSONResponse:
    """
    Create a consistent error response format for all API endpoints
    """
    return JSONResponse(
        status_code=status_code,
        content={
            "error": error,
            "status_code": status_code,
            "success": False,
            "message": message,
        },
    )