"""HTML views for gated action previews (#434)."""

from __future__ import annotations

import html
import json

from webui.gated_actions import ActionRegistry, GatedAction, preview_action
from webui.layout import render_page


def _escape(text: str) -> str:
    return html.escape(text, quote=True)


def _ledger_block(action: GatedAction) -> str:
    sample_params: dict[str, object]
    if action.action_id == "create_issue":
        sample_params = {"title": "Example issue"}
    elif action.action_id == "create_pr":
        sample_params = {"head": "feat/issue-99-example", "base": "master"}
    elif action.action_id == "delete_branch":
        sample_params = {"branch_name": "feat/issue-99-example"}
    elif action.action_id in {"review_pr", "merge_pr", "comment_pr", "close_pr"}:
        sample_params = {"pr_number": 99}
    else:
        sample_params = {"issue_number": 99}

    preview = preview_action(action.action_id, **sample_params)
    ledger_json = json.dumps(preview.get("mutation_ledger", []), indent=2)
    return (
        "<details class='action-preview'>"
        "<summary>Preview mutation ledger</summary>"
        f"<pre class='prompt-text'>{_escape(ledger_json)}</pre>"
        f"<p class='muted meta'>Sample params: "
        f"<code>{_escape(json.dumps(sample_params))}</code></p>"
        f"<p><a href=\"/api/actions/{_escape(action.action_id)}/preview?"
        f"{_preview_query(sample_params)}\">JSON preview</a></p>"
        "</details>"
    )


def _preview_query(params: dict[str, object]) -> str:
    parts = []
    for key, value in params.items():
        parts.append(f"{key}={_escape(str(value))}")
    return "&".join(parts)


def _action_card(action: GatedAction) -> str:
    disabled_attr = " disabled" if not action.enabled else ""
    return (
        "<article class='prompt-card action-card'>"
        f"<h3>{_escape(action.label)}</h3>"
        f"<p class='muted'>{_escape(action.description)}</p>"
        "<p class='meta'>"
        f"Task <code>{_escape(action.task_key)}</code> · "
        f"MCP <code>{_escape(action.mcp_tool)}</code><br>"
        f"Requires <code>{_escape(action.required_permission)}</code> "
        f"({_escape(action.required_role)} profile)</p>"
        f"<button type='button' class='copy-btn action-btn'{disabled_attr} "
        f"aria-disabled='true' title='Disabled in read-only MVP'>"
        f"{_escape(action.label)}</button>"
        f"{_ledger_block(action)}"
        "</article>"
    )


ACTION_PAGE_STYLES = """
<style>
  .action-card .action-btn[disabled] {
    opacity: 0.45;
    cursor: not-allowed;
    filter: none;
  }
  .action-preview { margin-top: 0.75rem; }
  .action-preview summary {
    cursor: pointer;
    color: var(--accent);
    font-size: 0.9rem;
  }
</style>
"""


def render_actions_page(registry: ActionRegistry) -> str:
    cards = "".join(_action_card(action) for action in registry.actions)
    body = (
        "<h2>Gated actions</h2>"
        "<p>Future write actions are registered here but remain "
        "<strong>disabled</strong> in the read-only MVP. Each action "
        "declares the MCP capability and profile role from "
        "<code>task_capability_map</code>; previews show the mutation "
        "ledger before any execution path ships.</p>"
        f"<p class='meta'>{len(registry.actions)} registered actions · "
        "execution: fail-closed</p>"
        f"{cards}"
        "<p><a href=\"/api/actions\">JSON registry</a></p>"
        f"{ACTION_PAGE_STYLES}"
    )
    return render_page(title="Actions", body_html=body)