import json

from .const import CASE_ATTRS_TO_KEYS_MAPPING
from .my_typing import *

INDENT4 = " " * 4


def serialize(x: Any, indent: str = "", sep: str = "\n") -> str:
    if isinstance(x, str):
        s = x
    elif isinstance(x, list) or isinstance(x, tuple):
        s = sep.join([f"{indent}* {serialize(i, indent + INDENT4)}" for i in x])
        s = "None" if s == "" else "\n" + s
    elif isinstance(x, dict):
        s = sep.join(
            [f"{indent}- {k}: {serialize(v, indent + INDENT4)}" for k, v in x.items()]
        )
        s = "None" if s == "" else "\n" + s
    else:
        s = str(x)

    return s


def case_to_input_dict(case: Dict[str, Any], case_type: str = "legacy"):
    inputs = {}
    for k, v in case.items():
        k = CASE_ATTRS_TO_KEYS_MAPPING[k]
        if k in ["input", "underspecifications"]:
            if case_type == "std":
                v = v["Standard"]
            elif case_type == "redteam":
                v = v["Red-teaming"]
            elif isinstance(v, dict) and k == "input":
                raise ValueError(f"incorrect case type for the case: {case_type}")

        if k == "underspecifications":
            assert isinstance(v, dict)
            # rename the keys
            v = v.copy()
            renames = {
                "Task Information": "Task Information Underspecifications",
                "Safety & Security Constraints": "Safety & Security Constraint Underspecifications",
            }
            for name in renames:
                rename = renames[name]
                if name in v:
                    v[rename] = v.pop(name)
                elif rename not in v:
                    raise ValueError(f"missing key: {name} or {rename} in case spec.")

        inputs[k] = serialize(v)
    return inputs


def html_highlight_content(html_content, key, color="red", start="", end=""):
    return html_content.replace(
        start + key + end, f"{start}<span style='color:{color}'>{key}</span>{end}"
    )


def html_title(title: str, level: int = 2) -> str:
    return f"<h{level}>{title}</h{level}>"


def html_text(data: str) -> str:
    return f"<pre>{data}</pre>"


def html_title_content(title, content, level=3):
    return html_title(title, level) + "\n" + html_text(content) + "\n\n"


def to_html(data: Any, level: int = 3, max_level: int = 5):
    if isinstance(data, dict):
        if level > max_level:
            content = html_text(json.dumps(data, indent=4))
        else:
            content = ""
            for key, value in data.items():
                content += html_title(key, level) + "\n"
                content += to_html(value, level + 1, max_level)
    elif isinstance(data, list):
        content = html_text("\n".join(["* " + x for x in data]))
    else:
        content = html_text(str(data))

    return content
