import random
import sys
from typing import Any, Union


import loguru
from PySide6 import QtWidgets, QtCore, QtGui
from PySide6.QtCore import Qt
from PySide6.QtGui import QPainter, QPen, QColor
from PySide6.QtCharts import QChart, QChartView, QLineSeries, QValueAxis, QCategoryAxis

from src import LOG_DIR
from src.backend.semester import Semester

log = loguru.logger
log.remove()
log.add(sys.stdout, level="INFO")
log.add(f"{LOG_DIR}/application.log", rotation="1 MB", retention="10 days")


def mergedicts(d1: dict[str, Any], d2: dict[str, Any]):
    res: dict[str, Any] = {}
    d1_data = list(d1.items())
    d2_data = list(d2.items())
    for i in range(len(d1)):
        # _data is a list of tuples
        d1_data_slice = d1_data[i]
        d2_data_slice = d2_data[i]
        # convert the tuples to dicts
        d1_dict = dict([d1_data_slice])
        d2_dict = dict([d2_data_slice])
        # merge the dicts
        res.update(d1_dict)  # type: ignore
        res.update(d2_dict)  # type: ignore
    return res

class DataQtGraph(QtWidgets.QWidget):
    def __init__(
        self,
        title: str,
        data: dict[str, Union[list[str], dict[str, list[int]]]],
        generateMissing: bool,
        y_label: str,
        x_rotation: int = 90,
    ):
        super().__init__()
        self.series = QLineSeries()
        self.chart = QChart()
        # scale the chart to fit the data
        self.chart.setTitle(title)
        self.chart.legend().setVisible(True)

        layout = QtWidgets.QVBoxLayout()

        lst = []
        if generateMissing:
            s_start = Semester.from_string(data["x"][0])
            s_end = Semester.from_string(data["x"][-1])
            # generate all semesters from start to end
            missing_semesters = Semester.generate_missing(s_start, s_end)
            x_data = data["x"]
            y_data = data["y"]
            if not isinstance(y_data, list):
                for key in y_data:
                    data = {"x": [], "y": []}
                    data["y-label"] = key
                    for semester in missing_semesters:
                        if semester not in x_data:
                            data["x"].append(semester)
                            data["y"].append(0)
                        data["x"].append(semester)
                        # get the index of the semester in x_data
                        if semester in x_data:
                            index = x_data.index(semester)
                            print("index:", index)
                            print(key, y_data[key])
                            data["y"].append(y_data[key][index])
                    lst.append(data)
                # for key in y_data:
                # data = {"x": x_data, "y": y_data[key]}
                # data = self.generateMissingSemesters(data)
                # data["y-label"] = key
            else:
                # data = self.generateMissingSemesters(data)
                data = {"x": [], "y": []}
                for semester in missing_semesters:
                    # if semester not in x_data, set y to 0
                    if semester not in x_data:
                        data["x"].append(semester)
                        data["y"].append(0)
                    data["x"].append(semester)
                    # get the index of the semester in x_data
                    if semester in x_data:
                        index = x_data.index(semester)
                        data["y"].append(y_data[index])
                data["y-label"] = y_label
                lst.append(data)

        else:
            x_data = data["x"]
            y_data = data["y"]
            if not isinstance(y_data, list):
                for key in y_data:
                    data = {"x": x_data, "y": y_data[key]}
                    data["y-label"] = key
                    lst.append(data)
            else:
                lst.append(data)
        x_data = lst[0]["x"]  #

        self.chart.createDefaultAxes()
        for entry in lst:
            print("entry:", entry)
            entryseries = QLineSeries()
            for x_val, y_val in zip(entry["x"], entry["y"]):
                #
                entryseries.append(entry["x"].index(x_val), y_val)
                entryseries.setName(entry["y-label"] if "y-label" in entry else y_label)
                entryseries.setPen(
                    QPen(
                        QColor(
                            random.randint(0, 255),
                            random.randint(0, 255),
                            random.randint(0, 255),
                        ),
                        2,
                    )
                )

            self.chart.addSeries(entryseries)

        x_axis = QCategoryAxis()
        for index, semester in enumerate(lst[0]["x"]):
            x_axis.append(semester, index)
        x_axis.setLabelsPosition(
            QCategoryAxis.AxisLabelsPosition.AxisLabelsPositionOnValue
        )
        # rotare the label by 45 degrees
        x_axis.setLabelsAngle(x_rotation)
        x_axis.setLabelsFont(QtGui.QFont("Arial", 8, QtGui.QFont.Weight.Normal, False))
        self.chart.setAxisX(x_axis, entryseries)

        # entryseries.append(
        #     str()
        # )
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(QtCore.Qt.AlignmentFlag.AlignTop)
        # set legend labels

        self.chart.setAxisY(QValueAxis(self.chart), entryseries)
        # the chart's x axis labels are not being displayed, as the chart only has limited space. scale down the x axis font

        chartview = QChartView(self.chart)
        chartview.setRenderHint(QPainter.RenderHint.Antialiasing)
        layout.addWidget(chartview)
        self.setLayout(layout)

    def generateMissingSemesters(self, data: dict[list]):
        # join the data into a single dict with x values as key and y values as value
        tmp_data = dict(zip(data["x"], data["y"], strict=False))
        # split into dicts based on SoSe and WiSe
        SoSe_data = {k: v for k, v in tmp_data.items() if "SoSe" in k}
        WiSe_data = {k: v for k, v in tmp_data.items() if "WiSe" in k}
        SoSe_years = [int(sose.split("SoSe")[1]) for sose in SoSe_data]
        WiSe_years = [int(wise.split("WiSe")[1].split("/")[0]) for wise in WiSe_data]
        years = SoSe_years + WiSe_years
        years = [
            year for year in range(min(list(set(years))), max(list(set(years))) + 1)
        ]
        years.sort()
        for year in years:
            SoSe_year = f"SoSe{year}"
            WiSe_year = f"WiSe{year}/{year + 1}"
            if SoSe_year not in SoSe_data.keys():
                SoSe_data[SoSe_year] = 0
            if WiSe_year not in WiSe_data.keys():
                WiSe_data[WiSe_year] = 0

        # sort WiSe_data to have same order as SoSe_data
        WiSe_data = dict(sorted(WiSe_data.items(), key=lambda x: x[0]))
        SoSe_data = dict(sorted(SoSe_data.items(), key=lambda x: x[0]))
        data = mergedicts(SoSe_data, WiSe_data)
        # split the data back into x and y
        data = {"x": list(data.keys()), "y": list(data.values())}
        return data


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)

    graph_data = {"x": ["WiSe 25/26", "WiSe 24/25", "SoSe 25"], "y": [1, 2, 1]}
    widget = DataGraph(
        "ELSA Apparate pro Semester", graph_data, True, "Anzahl der Apparate"
    )
    widget.show()
    sys.exit(app.exec())
