"""
API response wrapper for Code of Conquest.

Provides standardized JSON response format for all API endpoints.
"""

from datetime import datetime
from typing import Any, Dict, Optional
from flask import jsonify, Response
from app.config import get_config


def api_response(
    result: Any = None,
    status: int = 200,
    error: Optional[Dict[str, Any]] = None,
    meta: Optional[Dict[str, Any]] = None,
    request_id: Optional[str] = None
) -> Response:
    """
    Create a standardized API response.

    Args:
        result: The response data (or None if error)
        status: HTTP status code
        error: Error information (dict with 'code', 'message', 'details')
        meta: Metadata (pagination, etc.)
        request_id: Optional request ID for tracking

    Returns:
        Response: Flask JSON response

    Example:
        >>> return api_response(
        ...     result={"user_id": "123"},
        ...     status=200
        ... )

        >>> return api_response(
        ...     error={
        ...         "code": "INVALID_INPUT",
        ...         "message": "Email is required",
        ...         "details": {"field": "email"}
        ...     },
        ...     status=400
        ... )
    """
    config = get_config()

    response_data = {
        "app": config.app.name,
        "version": config.app.version,
        "status": status,
        "timestamp": datetime.utcnow().isoformat() + "Z",
        "request_id": request_id,
        "result": result,
        "error": error,
        "meta": meta
    }

    return jsonify(response_data), status


def success_response(
    result: Any = None,
    status: int = 200,
    meta: Optional[Dict[str, Any]] = None,
    request_id: Optional[str] = None
) -> Response:
    """
    Create a success response.

    Args:
        result: The response data
        status: HTTP status code (default 200)
        meta: Optional metadata
        request_id: Optional request ID

    Returns:
        Response: Flask JSON response

    Example:
        >>> return success_response({"character_id": "123"})
    """
    return api_response(
        result=result,
        status=status,
        meta=meta,
        request_id=request_id
    )


def error_response(
    code: str,
    message: str,
    status: int = 400,
    details: Optional[Dict[str, Any]] = None,
    request_id: Optional[str] = None
) -> Response:
    """
    Create an error response.

    Args:
        code: Error code (e.g., "INVALID_INPUT")
        message: Human-readable error message
        status: HTTP status code (default 400)
        details: Optional additional error details
        request_id: Optional request ID

    Returns:
        Response: Flask JSON response

    Example:
        >>> return error_response(
        ...     code="NOT_FOUND",
        ...     message="Character not found",
        ...     status=404
        ... )
    """
    error = {
        "code": code,
        "message": message,
        "details": details or {}
    }

    return api_response(
        error=error,
        status=status,
        request_id=request_id
    )


def created_response(
    result: Any = None,
    request_id: Optional[str] = None
) -> Response:
    """
    Create a 201 Created response.

    Args:
        result: The created resource data
        request_id: Optional request ID

    Returns:
        Response: Flask JSON response with status 201

    Example:
        >>> return created_response({"character_id": "123"})
    """
    return success_response(
        result=result,
        status=201,
        request_id=request_id
    )


def accepted_response(
    result: Any = None,
    request_id: Optional[str] = None
) -> Response:
    """
    Create a 202 Accepted response (for async operations).

    Args:
        result: Job information or status
        request_id: Optional request ID

    Returns:
        Response: Flask JSON response with status 202

    Example:
        >>> return accepted_response({"job_id": "abc123"})
    """
    return success_response(
        result=result,
        status=202,
        request_id=request_id
    )


def no_content_response(request_id: Optional[str] = None) -> Response:
    """
    Create a 204 No Content response.

    Args:
        request_id: Optional request ID

    Returns:
        Response: Flask JSON response with status 204

    Example:
        >>> return no_content_response()
    """
    return success_response(
        result=None,
        status=204,
        request_id=request_id
    )


def paginated_response(
    items: list,
    page: int,
    limit: int,
    total: int,
    request_id: Optional[str] = None
) -> Response:
    """
    Create a paginated response.

    Args:
        items: List of items for current page
        page: Current page number
        limit: Items per page
        total: Total number of items
        request_id: Optional request ID

    Returns:
        Response: Flask JSON response with pagination metadata

    Example:
        >>> return paginated_response(
        ...     items=[{"id": "1"}, {"id": "2"}],
        ...     page=1,
        ...     limit=20,
        ...     total=100
        ... )
    """
    pages = (total + limit - 1) // limit  # Ceiling division

    meta = {
        "page": page,
        "limit": limit,
        "total": total,
        "pages": pages
    }

    return success_response(
        result=items,
        meta=meta,
        request_id=request_id
    )


# Common error responses

def unauthorized_response(
    message: str = "Unauthorized",
    request_id: Optional[str] = None
) -> Response:
    """401 Unauthorized response."""
    return error_response(
        code="UNAUTHORIZED",
        message=message,
        status=401,
        request_id=request_id
    )


def forbidden_response(
    message: str = "Forbidden",
    request_id: Optional[str] = None
) -> Response:
    """403 Forbidden response."""
    return error_response(
        code="FORBIDDEN",
        message=message,
        status=403,
        request_id=request_id
    )


def not_found_response(
    message: str = "Resource not found",
    request_id: Optional[str] = None
) -> Response:
    """404 Not Found response."""
    return error_response(
        code="NOT_FOUND",
        message=message,
        status=404,
        request_id=request_id
    )


def validation_error_response(
    message: str,
    details: Optional[Dict[str, Any]] = None,
    request_id: Optional[str] = None
) -> Response:
    """400 Bad Request for validation errors."""
    return error_response(
        code="INVALID_INPUT",
        message=message,
        status=400,
        details=details,
        request_id=request_id
    )


def rate_limit_exceeded_response(
    message: str = "Rate limit exceeded",
    request_id: Optional[str] = None
) -> Response:
    """429 Too Many Requests response."""
    return error_response(
        code="RATE_LIMIT_EXCEEDED",
        message=message,
        status=429,
        request_id=request_id
    )


def internal_error_response(
    message: str = "Internal server error",
    request_id: Optional[str] = None
) -> Response:
    """500 Internal Server Error response."""
    return error_response(
        code="INTERNAL_ERROR",
        message=message,
        status=500,
        request_id=request_id
    )


def premium_required_response(
    message: str = "This feature requires a premium subscription",
    request_id: Optional[str] = None
) -> Response:
    """403 Forbidden for premium-only features."""
    return error_response(
        code="PREMIUM_REQUIRED",
        message=message,
        status=403,
        request_id=request_id
    )
