from datetime import datetime, timezone
from typing import Any
from uuid import uuid4

from pydantic import BaseModel, Field


class ApiMeta(BaseModel):
    request_id: str = Field(alias="requestId")
    timestamp: str
    trace_id: str | None = Field(default=None, alias="traceId")

    model_config = {"populate_by_name": True}


class StandardResponse(BaseModel):
    code: int = 0
    message: str = "ok"
    data: Any | None = None
    meta: ApiMeta

    model_config = {"populate_by_name": True}


def build_meta(request_id: str | None = None) -> ApiMeta:
    return ApiMeta(
        requestId=request_id or uuid4().hex,
        timestamp=datetime.now(timezone.utc).isoformat(),
        traceId=uuid4().hex[:16],
    )


def ok(data: Any = None, message: str = "ok", request_id: str | None = None) -> dict[str, Any]:
    return StandardResponse(code=0, message=message, data=data, meta=build_meta(request_id)).model_dump(
        by_alias=True
    )


def error(code: int, message: str, request_id: str | None = None, **details: Any) -> dict[str, Any]:
    payload = {"errorCode": message, **details} if details else {"errorCode": message}
    return StandardResponse(code=code, message=message, data=payload, meta=build_meta(request_id)).model_dump(
        by_alias=True
    )
