# Copyright © 2023-2024 ValidMind Inc. All rights reserved.
# See the LICENSE file in the root of this repository for details.
# SPDX-License-Identifier: AGPL-3.0 AND ValidMind Commercial

import os
from typing import TYPE_CHECKING, Dict, List, Union

import pandas as pd
from ipywidgets import HTML, GridBox, Layout
from jinja2 import Template

from ... import api_client
from ...logging import get_logger
from ..dataset import VMDataset
from ..figure import Figure
from ..input import VMInput

if TYPE_CHECKING:
    from .result import ResultTable


AI_REVISION_NAME = "Generated by ValidMind AI"
DEFAULT_REVISION_NAME = "Default Description"

logger = get_logger(__name__)

_result_template = None


def get_result_template():
    """Get the Jinja2 HTML template for rendering test results."""
    global _result_template

    if _result_template is None:
        with open(os.path.join(os.path.dirname(__file__), "result.jinja")) as f:
            _result_template = Template(f.read())

    return _result_template


async def update_metadata(content_id: str, text: str, _json: Union[Dict, List] = None):
    """Create or update a metadata object."""
    parts = content_id.split("::")
    content_id = parts[0]
    revision_name = parts[1] if len(parts) > 1 else None

    if revision_name:
        content_id = f"{content_id}::{revision_name}"

    logger.debug(f"Updating metadata for `{content_id}`")

    await api_client.alog_metadata(content_id, text, _json)


def check_for_sensitive_data(data: pd.DataFrame, inputs: List[VMInput]):
    """Check if the data contains sensitive information from input datasets."""
    dataset_columns = {
        col: len(input_obj.df)
        for input_obj in inputs
        if isinstance(input_obj, VMDataset)
        for col in input_obj.columns
    }

    table_columns = {col: len(data) for col in data.columns}

    offending_columns = [
        col
        for col in table_columns
        if col in dataset_columns and table_columns[col] == dataset_columns[col]
    ]

    if offending_columns:
        raise ValueError(
            f"Raw input data found in table, pass `unsafe=True` "
            f"or remove the offending columns: {offending_columns}"
        )


def tables_to_widgets(tables: List["ResultTable"]):
    """Convert a list of tables to ipywidgets."""
    widgets = [
        HTML("<h3>Tables</h3>"),
    ]

    for table in tables:
        html = ""
        if table.title:
            html += f"<h4>{table.title}</h4>"

        html += (
            table.data.reset_index(drop=True)
            .style.format(precision=4)
            .hide(axis="index")
            .set_table_styles(
                [
                    {
                        "selector": "",
                        "props": [("width", "100%")],
                    },
                    {
                        "selector": "th",
                        "props": [("text-align", "left")],
                    },
                    {
                        "selector": "tbody tr:nth-child(even)",
                        "props": [("background-color", "#FFFFFF")],
                    },
                    {
                        "selector": "tbody tr:nth-child(odd)",
                        "props": [("background-color", "#F5F5F5")],
                    },
                    {
                        "selector": "td, th",
                        "props": [
                            ("padding-left", "5px"),
                            ("padding-right", "5px"),
                        ],
                    },
                ]
            )
            .set_properties(**{"text-align": "left"})
            .to_html(escape=False)
        )

        widgets.append(HTML(html))

    return widgets


def figures_to_widgets(figures: List[Figure]) -> list:
    """Convert a list of figures to ipywidgets."""
    num_columns = 2 if len(figures) > 1 else 1

    plot_widgets = GridBox(
        [figure.to_widget() for figure in figures],
        layout=Layout(
            grid_template_columns=f"repeat({num_columns}, 1fr)",
        ),
    )

    return [HTML("<h3>Figures</h3>"), plot_widgets]
