from __future__ import annotations

from ...types import Atom, Ctx, EncodedCtx
from ...stages import Operated, Encoded
from typing import Any, Optional

from ... import events as _ev
from .templates import render_template
from .renderer import ResponseHints

ANCHOR = _ev.OUT_DUMP  # "out:dump"


async def _run(obj: Optional[object], ctx: Any) -> None:
    """response:template@out:dump

    Render a template if configured on ``ctx.response``.
    """
    resp_ns = getattr(ctx, "response", None)
    req = getattr(ctx, "request", None)
    if resp_ns is None or req is None:
        return
    tmpl = getattr(resp_ns, "template", None)
    if not tmpl:
        return
    result = getattr(resp_ns, "result", None)
    context = result if isinstance(result, dict) else {"data": result}
    html = await render_template(
        name=tmpl.name,
        context=context,
        search_paths=tmpl.search_paths,
        package=tmpl.package,
        auto_reload=bool(tmpl.auto_reload),
        filters=tmpl.filters,
        globals_=tmpl.globals,
        request=req,
    )
    resp_ns.result = html
    hints = getattr(resp_ns, "hints", None)
    if hints is None:
        hints = ResponseHints(status_code=int(getattr(ctx, "status_code", 200) or 200))
        resp_ns.hints = hints
    if not hints.media_type:
        hints.media_type = "text/html"


class AtomImpl(Atom[Operated, Encoded]):
    name = "response.template"
    anchor = ANCHOR

    async def __call__(self, obj: object | None, ctx: Ctx[Operated]) -> Ctx[Encoded]:
        await _run(obj, ctx)
        return ctx.promote(EncodedCtx)


INSTANCE = AtomImpl()

__all__ = ["ANCHOR", "INSTANCE"]
