from dataclasses import dataclass, field
from typing import Optional, List, Any

from markupsafe import escape


@dataclass
class TopbarAction:
    """
    A topbar button registered by a plugin.

    Register in ``on_load_complete`` via ``GlobalRegistry``::

        from fastpluggy.core.global_registry import GlobalRegistry
        from fastpluggy.core.topbar import TopbarAction
        from fastpluggy.core.widgets.categories.input.button_list import ButtonListWidget
        from fastpluggy.core.widgets.categories.input.button import AutoLinkWidget

        GlobalRegistry.extend_globals('topbar_actions', items=[
            TopbarAction(
                id='my-plugin-topbar',
                icon='ti ti-star',
                tooltip='My Plugin',
                position=20,
                module_name=self.module_name,
                modal_widgets=[
                    {
                        'widget': ButtonListWidget,
                        'kwargs': {
                            'title': 'My Plugin',
                            'buttons': [
                                AutoLinkWidget(route_name='my_index', label='Home'),
                            ],
                        },
                    },
                ],
            )
        ])

    The action renders as an ``.fp-icon-btn`` button in the topbar right section.

    **Action modes** (mutually exclusive, evaluated in priority order):

    1. ``modal_widgets`` — widget entry dicts pre-rendered server-side into a
       dedicated Bootstrap modal (``#fp-modal-{id}``). Widgets are instantiated
       per request via ``ViewBuilder.build_widget_entries`` (full DI, ``is_visible``
       respected). The button uses ``data-bs-toggle="modal"`` — no JS required.
    2. ``js_onclick`` — arbitrary JS expression placed in ``onclick="…"``.
    3. ``url`` — plain ``<a>`` navigation link.
    """

    #: Unique HTML ``id`` for the button element.
    id: str

    #: CSS icon classes, e.g. ``"ti ti-bug"`` or ``"fas fa-wrench"``.
    icon: str

    #: Tooltip / title attribute.
    tooltip: str = ""

    #: Sort order — lower values appear first (leftmost) in the topbar right section.
    position: int = 50

    #: Widget entry dicts rendered into a dedicated server-side modal.
    #: Format: ``[{'widget': WidgetClass, 'kwargs': {...}}, …]``
    #: Processed per request via ``ViewBuilder.build_widget_entries``:
    #: full DI via ``call_with_injection``, ``is_visible()`` respected.
    #: Takes priority over ``js_onclick`` and ``url``.
    modal_widgets: List[Any] = field(default_factory=list)

    #: JS expression called on click, e.g. ``"myAction()"``.
    #: Rendered verbatim inside ``onclick="..."``.
    js_onclick: Optional[str] = None

    #: URL to navigate to on click (used when the other modes are not set).
    url: Optional[str] = None

    #: Extra CSS classes added to the button element.
    extra_classes: str = ""

    #: Extra CSS classes added to the ``modal-body`` div, e.g. ``"p-0"`` to remove padding.
    modal_body_class: str = ""

    #: Name of the plugin that registered this action (used in admin overview).
    #: Set this to your plugin's ``module_name`` so the admin UI can attribute it.
    module_name: str = ""

    def to_admin_row(self) -> dict:
        """Return a dict suitable for a ``TableWidget`` row in the admin overview."""
        if self.modal_widgets:
            action_type = '<span class="fp-meta-chip fp-meta-chip--dim">modal</span>'
            action_detail = ', '.join(
                f'<code class="fp-path-code">{escape(e["widget"].__name__)}</code>'
                for e in self.modal_widgets
            )
        elif self.js_onclick:
            action_type = '<span class="fp-meta-chip fp-meta-chip--dim">js</span>'
            action_detail = f'<code class="fp-path-code">{escape(self.js_onclick)}</code>'
        elif self.url:
            action_type = '<span class="fp-meta-chip fp-meta-chip--dim">url</span>'
            action_detail = (
                f'<a href="{escape(self.url)}" class="fp-meta-chip fp-meta-chip--blue">'
                f'{escape(self.url)}</a>'
            )
        else:
            action_type = '<span class="fp-meta-none">—</span>'
            action_detail = ''

        return {
            'id': f'<code>{escape(self.id)}</code>',
            'tooltip': self.tooltip or '—',
            'position': f'<span class="fp-meta-chip fp-meta-chip--dim">{self.position}</span>',
            'type': action_type,
            'widgets': action_detail,
        }

    def __hash__(self):
        return hash(self.id)

    def __eq__(self, other):
        if isinstance(other, TopbarAction):
            return self.id == other.id
        return NotImplemented
