from __future__ import annotations

from typing import Annotated, Any

import dash_bootstrap_components as dbc
import vizro_dash_components as vdc
from dash import html
from pydantic import (
    AfterValidator,
    Field,
)
from pydantic.json_schema import SkipJsonSchema

from vizro.models import VizroBaseModel
from vizro.models._models_utils import _log_call, validate_icon
from vizro.models.types import _IdProperty


def coerce_str_to_tooltip(text: Any) -> Any:
    if isinstance(text, str):
        return Tooltip(text=text, icon="Info")
    return text


class Tooltip(VizroBaseModel):
    """A tooltip that displays text when hovering over an icon.

    Abstract: Usage documentation
        Read more about usage in the guides on [dashboards](../user-guides/dashboard.md#add-a-dashboard-tooltip),
        [pages](../user-guides/pages.md#add-a-tooltip),
        [containers](../user-guides/container.md#add-a-tooltip),
        [graphs](../user-guides/graph.md#add-a-tooltip),
        [tables](../user-guides/table.md#add-a-tooltip), [tabs](../user-guides/tabs.md#add-a-tooltip),
        [selectors](../user-guides/selectors.md#add-a-tooltip) and
        [buttons](../user-guides/button.md#add-a-tooltip).

    Example: `Tooltip` on a [`Checklist`][vizro.models.Checklist] selector
        ```python
        import vizro.models as vm

        vm.Checklist(
            title="Select Species",
            description=vm.Tooltip(text="Select something", icon="start"),
        )
        ```
    """

    text: str = Field(
        description="Markdown string for text shown when hovering over the icon. Should adhere to the CommonMark Spec."
    )
    icon: Annotated[
        str,
        AfterValidator(validate_icon),
        Field(description="Icon name from Google Material icons library."),
    ]
    extra: SkipJsonSchema[
        Annotated[
            dict[str, Any],
            Field(
                default={},
                description="""Extra keyword arguments that are passed to `dbc.Tooltip` and overwrite any
defaults chosen by the Vizro team. This may have unexpected behavior. Visit the
[dbc documentation](https://www.dash-bootstrap-components.com/docs/components/tooltip/)
to see all available arguments. [Not part of the official Vizro schema](../explanation/schema.md) and
the underlying component may change in the future.""",
            ),
        ]
    ]

    @property
    def _action_outputs(self) -> dict[str, _IdProperty]:
        return {
            "__default__": f"{self.id}-text.children",
            "text": f"{self.id}-text.children",
            "icon": f"{self.id}-icon.children",
        }

    @_log_call
    def build(self):
        defaults = {
            "id": self.id,
            "children": vdc.Markdown(id=f"{self.id}-text", children=self.text, className="card-text"),
            "target": f"{self.id}-icon",
            "autohide": False,
        }

        return html.Div(
            [
                html.Span(self.icon, id=f"{self.id}-icon", className="material-symbols-outlined tooltip-icon"),
                dbc.Tooltip(**(defaults | self.extra)),
            ]
        )
