from pathlib import Path
from typing import Literal

import narwhals as nw
from narwhals.typing import IntoDataFrame

from ssb_pubmd.adapters.content_parser import Content
from ssb_pubmd.adapters.content_parser import ContentParser
from ssb_pubmd.adapters.content_parser import MimirContentParser
from ssb_pubmd.adapters.storage import LocalFileStorage
from ssb_pubmd.adapters.storage import Storage
from ssb_pubmd.domain.document_publisher import USER_KEY_PREFIX

STORAGE: Storage = LocalFileStorage(project_folder=Path.cwd())
CONTENT_PARSER: ContentParser = MimirContentParser()

class NotebookClientError(Exception): ...

def configure_factbox(
    key: str,
    title: str,
    display_type: Literal["default", "sneakPeek", "aiIcon"] = "default",
) -> None:
    """Oppretter en faktaboks og printer en Markdown-snippet som kan limes inn i artikkelen (på en ny linje).

    :param key: En unik nøkkel for innholdet.
    :param title: Tittelen til faktaboksen.
    :param display_type: Visning av faktaboksen.

        Alternativer:

        * "default": Bare tittel (standard)
        * "sneakPeek": Tittel og litt av forklaringsteksten
        * "aiIcon": Tittel og litt av forklaringsteksten + KI-ikon
    """
    metadata = {
        "content_type": "factBox",
        "title": title,
        "display_type": display_type,
    }

    content = CONTENT_PARSER.parse(
        metadata=metadata,
        html=None,
    )
    _store_user_content(user_key=key, content=content)

    md = _get_markdown_snippet(
        key,
        placeholder_text="Faktaboksens tekst skrives her med Markdown-syntaks.\n\n### Underoverskrift\n\nNy paragraf.",
    )
    print(md)


def create_highchart(
    key: str,
    title: str,
    dataframe: IntoDataFrame | None = None,
    tbml: str | None = None,
    graph_type: Literal["line", "pie", "column", "bar", "area", "barNegative"] = "line",
    xlabel: str = "x",
    ylabel: str = "y"
) -> None:
    """Oppretter et highchart og printer en Markdown-snippet som kan limes inn i artikkelen (på en ny linje).

    Som datakilde er det nødvendig å spesifisere enten `dataframe` eller `tbml`.

    :param key: En unik nøkkel for innholdet.
    :param title: Tittelen til highchartet.
    :param dataframe: En pandas, Polars eller PyArrow dataframe.
    :param tbml: URL eller TBML-id.
    :param graph_type: Graftype.

        Alternativer:

        * "line": Linje (standard)
        * "pie": Kake
        * "column": Stolpe
        * "bar": Liggende stolpe
        * "area": Areal
        * "barNegative": Pyramide

    :param xlabel: X-akse, tittel.
    :param ylabel: Y-akse, tittel.
    """
    if dataframe is None and tbml is None:
        raise NotebookClientError("Either 'dataframe' or 'tbml' must be specified.")
    metadata = {
        "content_type": "highchart",
        "title": title,
        "graph_type": graph_type,
        "xlabel": xlabel,
        "ylabel": ylabel
    }
    if tbml is not None:
        metadata["tbml"] = tbml
    html = _dataframe_to_html_table(dataframe) if dataframe is not None else None
    content = CONTENT_PARSER.parse(metadata, html)
    _store_user_content(user_key=key, content=content)

    md = _get_markdown_snippet(key)
    print(md)


def _store_user_content(user_key: str, content: Content) -> None:
    key = USER_KEY_PREFIX + str(user_key)
    STORAGE.update(key, content.to_dict())


def _dataframe_to_html_table(dataframe: IntoDataFrame) -> str:
    df = nw.from_native(dataframe)
    html = "<table><tbody>\n"

    html += "<tr>\n"
    for name in df.columns:
        html += f"    <td>{name}</td>\n"
    html += "</tr>\n"

    for row in df.iter_rows():
        html += "  <tr>\n"
        for value in row:
            html += f"    <td>{value}</td>\n"
        html += "  </tr>\n"

    html += "</tbody></table>"

    return html


def _get_markdown_snippet(key: str, placeholder_text: str | None = None) -> str:
    div_config = f"{{ #{key} .ssb }}"
    div_content = f"\n{placeholder_text}\n\n" if placeholder_text is not None else ""
    return f"::: {div_config}\n{div_content}:::"