"""Federation defpage setup — registers layouts and loads .sx pages."""
from __future__ import annotations

from typing import Any


def setup_federation_pages() -> None:
    """Register federation-specific layouts and load page definitions."""
    _register_federation_layouts()
    _load_federation_page_files()


def _load_federation_page_files() -> None:
    import os
    from shared.sx.pages import load_page_dir
    load_page_dir(os.path.dirname(__file__), "federation")


# ---------------------------------------------------------------------------
# Layouts — .sx defcomps read free variables from env
# ---------------------------------------------------------------------------

def _register_federation_layouts() -> None:
    from shared.sx.layouts import register_custom_layout
    register_custom_layout("social", _social_full, _social_oob)


def _actor_data(ctx: dict) -> dict | None:
    actor = ctx.get("actor")
    if not actor:
        return None
    from services.federation_page import _serialize_actor
    return _serialize_actor(actor)


async def _social_full(ctx: dict, **kw: Any) -> str:
    from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env
    env = _ctx_to_env(ctx)
    env["actor"] = kw.get("actor") or _actor_data(ctx)
    return await render_to_sx_with_env("social-layout-full", env)


async def _social_oob(ctx: dict, **kw: Any) -> str:
    from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env
    env = _ctx_to_env(ctx, oob=True)
    env["actor"] = kw.get("actor") or _actor_data(ctx)
    return await render_to_sx_with_env("social-layout-oob", env)


# ---------------------------------------------------------------------------
# Helpers still used by route handlers
# ---------------------------------------------------------------------------

def _serialize_actor(actor) -> dict | None:
    """Serialize an actor profile to a dict for sx defcomps."""
    from services.federation_page import _serialize_actor as _impl
    return _impl(actor)


def _serialize_timeline_item(item) -> dict:
    """Serialize a timeline item DTO to a dict for sx defcomps."""
    from services.federation_page import _serialize_timeline_item as _impl
    return _impl(item)


def _serialize_remote_actor(a) -> dict:
    """Serialize a remote actor DTO to a dict for sx defcomps."""
    from services.federation_page import _serialize_remote_actor as _impl
    return _impl(a)


async def _social_page(ctx: dict, actor, *, content: str,
                       title: str = "Rose Ash", meta_html: str = "") -> str:
    """Build a full social page with social header."""
    from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env, full_page_sx
    from markupsafe import escape

    env = _ctx_to_env(ctx)
    env["actor"] = _serialize_actor(actor) if actor else None
    header_rows = await render_to_sx_with_env("social-layout-full", env)
    return await full_page_sx(ctx, header_rows=header_rows, content=content,
                          meta_html=meta_html or f'<title>{escape(title)}</title>')


def _get_actor():
    """Return current user's actor or None."""
    from quart import g
    return getattr(g, "_social_actor", None)


def _require_actor():
    """Return current user's actor or abort 403."""
    from quart import abort
    actor = _get_actor()
    if not actor:
        abort(403, "You need to choose a federation username first")
    return actor
