"""Top-level render_* functions — public API called from route handlers."""
from __future__ import annotations

from shared.sx.helpers import (
    render_to_sx_with_env,
    post_admin_header_sx, oob_header_sx,
    header_child_sx, full_page_sx, oob_page_sx,
)

from .utils import _clear_deeper_oob, _ensure_container_nav
from .calendar import (
    _post_header_sx, _calendars_header_sx,
    _calendar_header_sx, _day_header_sx,
    _calendars_main_panel_sx,
    _calendar_main_panel_html, _day_main_panel_html,
    _calendar_admin_main_panel_html,
    _calendar_description_display_html,
    _markets_main_panel_html,
)
from .entries import (
    _events_main_panel_html, _entry_cards_html,
    _entry_main_panel_html,
)
from .tickets import render_buy_form


# ---------------------------------------------------------------------------
# All events
# ---------------------------------------------------------------------------

async def render_all_events_page(ctx: dict, entries, has_more, pending_tickets,
                                  page_info, page, view) -> str:
    """Full page: all events listing."""
    from quart import url_for
    from shared.utils import route_prefix
    from shared.infrastructure.urls import events_url

    prefix = route_prefix()
    view_param = f"&view={view}" if view != "list" else ""
    ticket_url = url_for("all_events.adjust_ticket")
    next_url = prefix + url_for("all_events.entries_fragment", page=page + 1) + (f"?view={view}" if view != "list" else "")

    content = _events_main_panel_html(
        ctx, entries, has_more, pending_tickets, page_info,
        page, view, ticket_url, next_url, events_url,
    )
    hdr = await render_to_sx_with_env("layout-root-full", {})
    return await full_page_sx(ctx, header_rows=hdr, content=content)


async def render_all_events_oob(ctx: dict, entries, has_more, pending_tickets,
                                 page_info, page, view) -> str:
    """OOB response: all events listing (htmx nav)."""
    from quart import url_for
    from shared.utils import route_prefix
    from shared.infrastructure.urls import events_url

    prefix = route_prefix()
    ticket_url = url_for("all_events.adjust_ticket")
    next_url = prefix + url_for("all_events.entries_fragment", page=page + 1) + (f"?view={view}" if view != "list" else "")

    content = _events_main_panel_html(
        ctx, entries, has_more, pending_tickets, page_info,
        page, view, ticket_url, next_url, events_url,
    )
    return await oob_page_sx(content=content)


def render_all_events_cards(entries, has_more, pending_tickets,
                            page_info, page, view) -> str:
    """Pagination fragment: all events cards only."""
    from quart import url_for
    from shared.utils import route_prefix
    from shared.infrastructure.urls import events_url

    prefix = route_prefix()
    ticket_url = url_for("all_events.adjust_ticket")
    next_url = prefix + url_for("all_events.entries_fragment", page=page + 1) + (f"?view={view}" if view != "list" else "")

    return _entry_cards_html(
        entries, page_info, pending_tickets, ticket_url, events_url,
        view, page, has_more, next_url,
    )


# ---------------------------------------------------------------------------
# Page summary
# ---------------------------------------------------------------------------

async def render_page_summary_page(ctx: dict, entries, has_more, pending_tickets,
                                    page_info, page, view) -> str:
    """Full page: page-scoped events listing."""
    from quart import url_for
    from shared.utils import route_prefix
    from shared.infrastructure.urls import events_url

    prefix = route_prefix()
    post = ctx.get("post") or {}
    ticket_url = url_for("page_summary.adjust_ticket")
    next_url = prefix + url_for("page_summary.entries_fragment", page=page + 1) + (f"?view={view}" if view != "list" else "")

    content = _events_main_panel_html(
        ctx, entries, has_more, pending_tickets, page_info,
        page, view, ticket_url, next_url, events_url,
        is_page_scoped=True, post=post,
    )

    hdr = await render_to_sx_with_env("layout-root-full", {})
    hdr += await header_child_sx(await _post_header_sx(ctx))
    return await full_page_sx(ctx, header_rows=hdr, content=content)


async def render_page_summary_oob(ctx: dict, entries, has_more, pending_tickets,
                                   page_info, page, view) -> str:
    """OOB response: page-scoped events (htmx nav)."""
    from quart import url_for
    from shared.utils import route_prefix
    from shared.infrastructure.urls import events_url

    prefix = route_prefix()
    post = ctx.get("post") or {}
    ticket_url = url_for("page_summary.adjust_ticket")
    next_url = prefix + url_for("page_summary.entries_fragment", page=page + 1) + (f"?view={view}" if view != "list" else "")

    content = _events_main_panel_html(
        ctx, entries, has_more, pending_tickets, page_info,
        page, view, ticket_url, next_url, events_url,
        is_page_scoped=True, post=post,
    )

    oobs = await _post_header_sx(ctx, oob=True)
    oobs += _clear_deeper_oob("post-row", "post-header-child")
    return await oob_page_sx(oobs=oobs, content=content)


def render_page_summary_cards(entries, has_more, pending_tickets,
                              page_info, page, view, post) -> str:
    """Pagination fragment: page-scoped events cards only."""
    from quart import url_for
    from shared.utils import route_prefix
    from shared.infrastructure.urls import events_url

    prefix = route_prefix()
    ticket_url = url_for("page_summary.adjust_ticket")
    next_url = prefix + url_for("page_summary.entries_fragment", page=page + 1) + (f"?view={view}" if view != "list" else "")

    return _entry_cards_html(
        entries, page_info, pending_tickets, ticket_url, events_url,
        view, page, has_more, next_url,
        is_page_scoped=True, post=post,
    )


# ---------------------------------------------------------------------------
# Calendars home
# ---------------------------------------------------------------------------

async def render_calendars_page(ctx: dict) -> str:
    """Full page: calendars listing."""
    content = _calendars_main_panel_sx(ctx)
    ctx = await _ensure_container_nav(ctx)
    slug = (ctx.get("post") or {}).get("slug", "")
    root_hdr = await render_to_sx_with_env("layout-root-full", {})
    post_hdr = await _post_header_sx(ctx)
    admin_hdr = await post_admin_header_sx(ctx, slug, selected="calendars")
    return await full_page_sx(ctx, header_rows=root_hdr + post_hdr + admin_hdr, content=content)


async def render_calendars_oob(ctx: dict) -> str:
    """OOB response: calendars listing."""
    content = _calendars_main_panel_sx(ctx)
    ctx = await _ensure_container_nav(ctx)
    slug = (ctx.get("post") or {}).get("slug", "")
    oobs = await post_admin_header_sx(ctx, slug, oob=True, selected="calendars")
    oobs += _clear_deeper_oob("post-row", "post-header-child",
                               "post-admin-row", "post-admin-header-child")
    return await oob_page_sx(oobs=oobs, content=content)


# ---------------------------------------------------------------------------
# Calendar month view
# ---------------------------------------------------------------------------

async def render_calendar_page(ctx: dict) -> str:
    """Full page: calendar month view."""
    content = _calendar_main_panel_html(ctx)
    hdr = await render_to_sx_with_env("layout-root-full", {})
    child = await _post_header_sx(ctx) + _calendar_header_sx(ctx)
    hdr += await header_child_sx(child)
    return await full_page_sx(ctx, header_rows=hdr, content=content)


async def render_calendar_oob(ctx: dict) -> str:
    """OOB response: calendar month view."""
    content = _calendar_main_panel_html(ctx)
    oobs = await _post_header_sx(ctx, oob=True)
    oobs += await oob_header_sx("post-header-child", "calendar-header-child",
                              _calendar_header_sx(ctx))
    oobs += _clear_deeper_oob("post-row", "post-header-child",
                               "calendar-row", "calendar-header-child")
    return await oob_page_sx(oobs=oobs, content=content)


# ---------------------------------------------------------------------------
# Day detail
# ---------------------------------------------------------------------------

async def render_day_page(ctx: dict) -> str:
    """Full page: day detail."""
    content = _day_main_panel_html(ctx)
    hdr = await render_to_sx_with_env("layout-root-full", {})
    child = (await _post_header_sx(ctx)
             + _calendar_header_sx(ctx) + _day_header_sx(ctx))
    hdr += await header_child_sx(child)
    return await full_page_sx(ctx, header_rows=hdr, content=content)


async def render_day_oob(ctx: dict) -> str:
    """OOB response: day detail."""
    content = _day_main_panel_html(ctx)
    oobs = _calendar_header_sx(ctx, oob=True)
    oobs += await oob_header_sx("calendar-header-child", "day-header-child",
                              _day_header_sx(ctx))
    oobs += _clear_deeper_oob("post-row", "post-header-child",
                               "calendar-row", "calendar-header-child",
                               "day-row", "day-header-child")
    return await oob_page_sx(oobs=oobs, content=content)


# ---------------------------------------------------------------------------
# Day main panel -- public API
# ---------------------------------------------------------------------------

def render_day_main_panel(ctx: dict) -> str:
    """Public wrapper for day main panel rendering."""
    return _day_main_panel_html(ctx)


# ---------------------------------------------------------------------------
# Calendar description display + edit form
# ---------------------------------------------------------------------------

def render_calendar_description(calendar, *, oob: bool = False) -> str:
    """Render calendar description display with edit button, optionally with OOB title."""
    from quart import url_for
    from shared.sx.helpers import sx_call

    cal_slug = getattr(calendar, "slug", "")
    edit_url = url_for("calendar.admin.calendar_description_edit", calendar_slug=cal_slug)
    html = _calendar_description_display_html(calendar, edit_url)

    if oob:
        desc = getattr(calendar, "description", "") or ""
        html += sx_call("events-calendar-description-title-oob",
                       description=desc)
    return html


def render_calendar_description_edit(calendar) -> str:
    """Render calendar description edit form."""
    from quart import url_for
    from shared.browser.app.csrf import generate_csrf_token
    from shared.sx.helpers import sx_call
    csrf = generate_csrf_token()
    cal_slug = getattr(calendar, "slug", "")
    desc = getattr(calendar, "description", "") or ""

    save_url = url_for("calendar.admin.calendar_description_save", calendar_slug=cal_slug)
    cancel_url = url_for("calendar.admin.calendar_description_view", calendar_slug=cal_slug)

    return sx_call("events-calendar-description-edit-form",
                  save_url=save_url, cancel_url=cancel_url,
                  csrf=csrf, description=desc)


# ---------------------------------------------------------------------------
# Calendars / Markets list panels (for POST create / DELETE)
# ---------------------------------------------------------------------------

def render_calendars_list_panel(ctx: dict) -> str:
    """Render the calendars main panel HTML for POST/DELETE response."""
    return _calendars_main_panel_sx(ctx)


def render_markets_list_panel(ctx: dict) -> str:
    """Render the markets main panel HTML for POST/DELETE response."""
    return _markets_main_panel_html(ctx)
