from .widget_sources.Ui_search_statistic_page import Ui_Dialog
from PyQt6 import QtWidgets, QtGui, QtCore
from PyQt6.QtCore import pyqtSignal
from src.backend import Database, Semester
from src import logger
from src.logic import custom_sort, Prof, sort_semesters_list
from src.ui.dialogs import Mail_Dialog, ApparatExtendDialog, reminder_ui
from src.ui.widgets import DataGraph, StatusWidget

from natsort import natsorted


class MyComboBox(QtWidgets.QComboBox):
    def __init__(self, parent=None):
        super().__init__(parent)


class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
    apparat_open = pyqtSignal(str)
    reloadSignal = pyqtSignal()
    refreshSignal = pyqtSignal()
    updateCalendar = pyqtSignal(int, list)

    def __init__(self):
        logger.info("SearchStatisticPage started")
        super().__init__()
        self.setupUi(self)
        self.book_search_result.horizontalHeader().setSectionResizeMode(
            QtWidgets.QHeaderView.ResizeMode.Stretch
        )
        self.check_deletable.stateChanged.connect(self.gridchange)
        self.tableWidget.horizontalHeader().setSectionResizeMode(
            QtWidgets.QHeaderView.ResizeMode.Stretch
        )
        self.btn_del_select_apparats.clicked.connect(self.delete_selected_apparats)
        self.statistics_table.doubleClicked.connect(self.display_detailed_data)
        self.tabWidget_2.currentChanged.connect(self.tabW2_changed)
        self.btn_search.clicked.connect(self.statistics)
        self.book_search.clicked.connect(self.search_book)
        self.tableWidget.customContextMenuRequested.connect(
            self.statistics_table_context_menu
        )
        # statistic side buttons
        self.btn_notify_for_deletion.clicked.connect(self.notify_for_deletion)
        self.btn_notify_for_deletion.setEnabled(False)
        self.btn_del_select_apparats.setEnabled(False)
        self.tableWidget.resizeColumnsToContents()
        self.tableWidget.resizeRowsToContents()
        self.db = Database()
        self.appnrs = self.db.getUnavailableApparatNumbers()
        self.box_appnrs.addItems(str(i) for i in self.appnrs)
        self.splitter = QtWidgets.QSplitter(QtCore.Qt.Orientation.Horizontal)
        # insert splitter in apparatResult to allow resizing of the columns
        self.splitter.addWidget(self.app_results)
        self.splitter.addWidget(self.stats)
        self.apparatResult.layout().removeWidget(self.stats)
        self.apparatResult.layout().removeWidget(self.app_results)
        self.apparatResult.layout().addWidget(self.splitter)
        # set tableWidget column 0 to be 50px wide
        self.tableWidget.setColumnWidth(0, 50)
        self.semester = Semester().value
        self.populate_tab()

    def restore_apparat(self):
        selected_rows = self.tableWidget.selectionModel().selectedRows()
        apparats = []
        if len(selected_rows) == 0:
            # get position of right click
            row = self.tableWidget.currentRow()
            apparats.append(self.tableWidget.item(row, 1).text())
        else:
            for row in selected_rows:
                apparats.append(self.tableWidget.item(row.row(), 1).text())
        for apparat in apparats:
            apparat_id = self.db.getApparatId(apparat)
            self.db.restoreApparat(apparat_id)
            # remove the red color from the row
            # get row where the apparat is
            row = self.tableWidget.findItems(apparat, QtCore.Qt.MatchFlag.MatchExactly)[
                0
            ].row()
            for j in range(5):
                self.tableWidget.item(row, j).setBackground(QtGui.QColor(255, 255, 255))
        self.reloadSignal.emit()

    def statistics_table_context_menu(self, position):
        menu = QtWidgets.QMenu()
        restore_action = menu.addAction("Wiederherstellen")
        extend_action = menu.addAction("Verlängern")
        remind_action = menu.addAction("Erinnerung")

        menu.addAction(restore_action)
        restore_action.triggered.connect(self.restore_apparat)
        extend_action.triggered.connect(self.extend_apparat)
        remind_action.triggered.connect(self.reminder)
        menu.exec(self.tableWidget.mapToGlobal(position))

    def extend_apparat(self):
        extend = ApparatExtendDialog()
        extend.exec()
        if extend.result() == QtWidgets.QDialog.DialogCode.Accepted:
            data = extend.get_data()
            logger.debug(data)
            app_name = self.tableWidget.item(self.tableWidget.currentRow(), 1).text()
            app_id = self.db.getApparatId(app_name)
            self.db.setNewSemesterDate(app_id, data["semester"], data["dauerapp"])
            # remove the row
            self.tableWidget.removeRow(self.tableWidget.currentRow())
            self.refreshSignal.emit()

    def reminder(self):
        logger.info("Opening reminder dialog")
        reminder = reminder_ui()
        reminder.exec()
        tableposition = self.tableWidget.currentRow()
        appnr = self.tableWidget.item(tableposition, 2).text()
        if reminder.result() == QtWidgets.QDialog.DialogCode.Accepted:
            data = reminder.return_message()
            # #print(data)
            self.db.addMessage(
                data,
                "admin",
                appnr,
            )
            self.updateCalendar.emit(data)
            logger.info("committed message to database")

    def tabW2_changed(self):
        if self.tabWidget_2.currentIndex() == 0:
            self.stackedWidget_4.setCurrentIndex(0)
        else:
            self.stackedWidget_4.setCurrentIndex(1)

    def search_book(self):
        self.book_search_result.setRowCount(0)
        signature = self.seach_by_signature.text()
        title = self.search_by_title.text()
        params = {
            "signature": signature if signature != "" else None,
            "title": title if title != "" else None,
        }
        params = {key: value for key, value in params.items() if value is not None}
        logger.debug(params)
        retdata = self.db.searchBook(params)
        if retdata is None:
            return
        for book in retdata:
            self.book_search_result.insertRow(0)
            self.book_search_result.setItem(
                0, 0, QtWidgets.QTableWidgetItem(book[0].title)
            )
            self.book_search_result.setItem(
                0, 1, QtWidgets.QTableWidgetItem(book[0].signature)
            )
            # #print(book[1])
            self.book_search_result.setItem(
                0,
                2,
                QtWidgets.QTableWidgetItem(self.db.getApparatName(book[1], book[2])),
            )

    def notify_for_deletion(self):
        # get all selected apparats
        selected_apparats: list[dict] = []
        for i in range(self.tableWidget.rowCount()):
            data = {}
            if self.tableWidget.cellWidget(i, 0).isChecked():
                data["app_id"] = self.tableWidget.item(i, 2).text()
                data["app_name"] = self.tableWidget.item(i, 1).text()
                data["prof_name"] = self.tableWidget.item(i, 3).text()

                selected_apparats.append(data)
        # delete all selected apparats
        logger.debug(selected_apparats)
        dialogs = []
        for i in selected_apparats:
            app_id = i["app_id"]
            app_name = i["app_name"]
            prof_name = i["prof_name"]
            prof_mail = self.db.getProfData(prof_name).mail
            self.mail_thread = Mail_Dialog(
                app_id=app_id,
                app_name=app_name,
                prof_name=prof_name,
                prof_mail=prof_mail,
                app_subject="",
                default_mail="Information bezüglich der Auflösung des Semesterapparates",
            )
            dialogs.append(self.mail_thread)
        for dialog in dialogs:
            dialog.exec()

        self.btn_notify_for_deletion.setEnabled(False)

    def setStatisticTableSize(self):
        # # #print(self.statistics_table.size(), self.statistics_table.rowCount())
        size = self.statistics_table.size()
        h = size.height()
        w = size.width()
        rows = self.statistics_table.rowCount()
        rowheight = round(h / rows) - 5
        header_width = round(w / 3) - 5
        for i in range(3):
            self.statistics_table.setColumnWidth(i, header_width)
        for i in range(rows):
            self.statistics_table.setRowHeight(i, rowheight)

    def __table_or_graph(self):
        return self.tabWidget_3.currentIndex()

    def gridchange(self):
        if self.check_deletable.isChecked():
            self.box_semester.setEnabled(False)
            self.box_appnrs.setEnabled(False)
            self.box_appnrs.clear()
            self.box_person.setEnabled(False)
            self.box_person.clear()
            self.box_fach.setEnabled(False)
            self.box_fach.clear()
            self.box_erstellsemester.setEnabled(False)
            self.box_erstellsemester.clear()
            self.box_dauerapp.setEnabled(False)
            self.box_dauerapp.clear()
            self.populate_tab(self.__table_or_graph())
        else:
            self.box_semester.setEnabled(True)
            self.box_appnrs.setEnabled(True)
            self.box_person.setEnabled(True)
            self.box_fach.setEnabled(True)
            self.box_erstellsemester.setEnabled(True)
            self.box_dauerapp.setEnabled(True)

    def populate_tab(self, table_or_graph=0):
        logger.info("populate_tab started")
        # add default values to the dropdowns
        self.box_appnrs.clear()
        self.box_appnrs.addItem("")
        self.box_appnrs.setCurrentText("")
        self.box_person.clear()
        self.box_person.addItem("")
        self.box_person.setCurrentText("")
        self.box_fach.clear()
        self.box_fach.addItem("")
        self.box_fach.setCurrentText("")
        self.box_erstellsemester.clear()
        self.box_erstellsemester.addItem("")
        self.box_erstellsemester.setCurrentText("")
        self.box_semester.clear()
        self.box_semester.addItem("")
        self.box_semester.setCurrentText("")
        self.box_dauerapp.clear()
        self.box_dauerapp.addItems(["Ja", "Nein", ""])
        self.box_dauerapp.setCurrentText("")
        # add custom vaules
        appnrs = self.appnrs
        apparats = natsorted(appnrs)
        apparats = [str(apparat) for apparat in apparats]
        self.box_appnrs.addItems(apparats)
        persons = self.db.getProfs()
        persons = sorted(persons, key=lambda x: x.lastname)
        self.box_person.addItems(
            [f"{person.lastname}, {person.firstname}" for person in persons]
        )
        self.box_fach.addItems(subject[1] for subject in self.db.getSubjects())
        semester = self.db.getSemesters()
        semester = sort_semesters_list(semester)
        self.box_erstellsemester.addItems(semester)
        self.box_semester.addItems(semester)
        self.statistics_table.setRowCount(0)

        # set data for table and graph in tab 2 tableWidget_3
        data = self.db.getApparatCountBySemester()
        data = custom_sort(data)
        # self.tabWidget_3.clear()
        self.tabWidget_3.removeTab(1)
        self.statistics_table.setRowCount(len(data))
        for i in range(len(data)):
            self.statistics_table.setItem(i, 0, QtWidgets.QTableWidgetItem(data[i][0]))
            self.statistics_table.setItem(
                i, 1, QtWidgets.QTableWidgetItem(str(data[i][1]))
            )
            self.statistics_table.setItem(
                i, 2, QtWidgets.QTableWidgetItem(str(data[i][2]))
            )
        self.statistics_table.resizeColumnsToContents()
        self.statistics_table.resizeRowsToContents()
        # self.setStatisticTableSize()

        # get height of the table
        # create graph

        graph_data = {
            "x": [i[0] for i in data],
            "y": {"Erstellt": [i[1] for i in data], "Gelöscht": [i[2] for i in data]},
        }
        graph = DataGraph(title="Erstellte und gelöschte Apparate", data=graph_data)

        # place the graph into tabWidget_3
        self.tabWidget_3.addTab(graph, "Graph")
        self.tabWidget_3.setCurrentIndex(table_or_graph)
        logger.info("populate_tab finished")

    def delete_selected_apparats(self):
        # get all selected apparats
        selected_apparats = []
        selected_apparat_rows = []
        for i in range(self.tableWidget.rowCount()):
            if self.tableWidget.cellWidget(i, 0).isChecked():
                selected_apparats.append(self.tableWidget.item(i, 2).text())
                selected_apparat_rows.append(i)
        # delete all selected apparats
        # # #print(selected_apparats)
        logger.info(f"Deleting apparats: {selected_apparats}")
        for apparat in selected_apparats:
            self.db.deleteApparat(apparat, self.semester)
        for row in selected_apparat_rows:
            # set the background of the row to red
            for j in range(5):
                self.tableWidget.item(row, j).setBackground(QtGui.QColor(235, 74, 71))
        # refresh the table
        self.populate_tab(self.__table_or_graph())
        self.btn_del_select_apparats.setEnabled(False)

    def statistics(self):
        """Generate the statistics based on the selected filters."""
        self.tableWidget.setRowCount(0)
        active_semseter = self.semester
        self.db_err_message.setText("")
        self.btn_del_select_apparats.setEnabled(False)
        self.btn_notify_for_deletion.setEnabled(False)
        params = {
            "appnr": (
                self.box_appnrs.currentText()
                if self.box_appnrs.currentText() != ""
                else None
            ),
            "prof_id": (
                self.db.getProfId(Prof(fullname=self.box_person.currentText()))
                if self.box_person.currentText() != ""
                else None
            ),
            "fach": (
                self.box_fach.currentText()
                if self.box_fach.currentText() != ""
                else None
            ),
            "erstellsemester": (
                self.box_erstellsemester.currentText()
                if self.box_erstellsemester.currentText() != ""
                else None
            ),
            "dauer": (
                "1"
                if self.box_dauerapp.currentText() == "Ja"
                else "0"
                if self.box_dauerapp.currentText() == "Nein"
                else None
            ),
            "endsemester": (
                self.box_semester.currentText()
                if self.box_semester.currentText() != ""
                else None
            ),
            "deletable": "True" if self.check_deletable.isChecked() else None,
            "deletesemester": active_semseter,
        }
        params = {
            key: value for key, value in params.items() if value is not None
        }  # remove empty lines to prevent errors
        params = {
            key: value for key, value in params.items() if value != "Alle"
        }  # remove empty lines to prevent errors
        result = self.db.statistic_request(**params)
        # add QTableWidgetItems to the table
        # self.tableWidget.setRowCount(len(result))
        if len(result) == 0:
            self.db_err_message.setText("Keine Ergebnisse gefunden")
            return
        data = []

        for entry in result:
            if "deletable" in params.keys():
                sem = Semester().from_string(
                    entry[8] if entry[8] is not None else entry[5]
                )
                logger.info(f"Semester: {sem}")
                if sem.isPastSemester(Semester()):
                    data.append(entry)
            else:
                data.append(entry)
        self.tableWidget.setRowCount(len(data))
        if len(data) > 0:
            self.btn_del_select_apparats.setEnabled(True)
            self.btn_notify_for_deletion.setEnabled(True)

        for i in range(len(data)):
            # set the items 0 = clickable checkbox, 1 = appname, 2 = profname, 3 = fach
            self.tableWidget.setItem(i, 0, QtWidgets.QTableWidgetItem(""))
            self.tableWidget.setItem(i, 1, QtWidgets.QTableWidgetItem(data[i][1]))
            # set tooltip for the apparat name
            self.tableWidget.item(i, 1).setToolTip(data[i][1])
            self.tableWidget.setItem(i, 2, QtWidgets.QTableWidgetItem(str(data[i][4])))
            self.tableWidget.setItem(i, 3, QtWidgets.QTableWidgetItem(data[i][2]))
            self.tableWidget.setItem(i, 4, QtWidgets.QTableWidgetItem(data[i][3]))
            # replace the 0 with a checkbox
            checkbox = QtWidgets.QCheckBox()
            checkbox.setChecked(False)
            self.tableWidget.setCellWidget(i, 0, checkbox)
            # if i[9] is 1, set the background of the row to red
            if int(data[i][9]) == 1:
                for j in range(5):
                    self.tableWidget.item(i, j).setBackground(QtGui.QColor(235, 74, 71))
                # disable the checkbox
                self.tableWidget.cellWidget(i, 0).setEnabled(False)
                # set the tooltip
                self.tableWidget.cellWidget(i, 0).setToolTip(
                    "Dieser Semesterapparat kann nicht gelöscht werden, da er bereits gelöscht wurde"
                )
        # # remove empty rows
        for row in range(self.tableWidget.rowCount()):
            if self.tableWidget.item(row, 1) is None:
                self.tableWidget.removeRow(row)

    def display_detailed_data(self):
        selected_semester = self.statistics_table.item(
            self.statistics_table.currentRow(), 0
        ).text()
        # get all apparats from the selected semester
        data = self.db.getApparatsBySemester(selected_semester)
        # replace keys for german names
        # split to two lists
        created = {"Erstellt": data["created"]}
        deleted = {"Gelöscht": data["deleted"]}
        created_status = StatusWidget(created, selected_semester)
        deleted_status = StatusWidget(deleted, selected_semester)
        created_status.setSizePolicy(
            QtWidgets.QSizePolicy.Policy.Expanding,
            QtWidgets.QSizePolicy.Policy.Expanding,
        )
        deleted_status.setSizePolicy(
            QtWidgets.QSizePolicy.Policy.Expanding,
            QtWidgets.QSizePolicy.Policy.Expanding,
        )

        # add them to the gridLayout_4
        if self.dataLayout.count() > 0:
            self.dataLayout.itemAt(0).widget().deleteLater()
            self.dataLayout.itemAt(1).widget().deleteLater()
        self.dataLayout.addWidget(created_status)
        self.dataLayout.addWidget(deleted_status)

        # self.setStatisticTableSize()
        created_status.person_double_clicked.connect(self.open_apparat)
        created_status.setToolTip("Doppelklick um den Semesterapparat zu öffnen")
        deleted_status.setToolTip("Nur zur Übersicht")
        # set deleted_status background to slightly gray

    def open_apparat(self, *args):
        header = "created"
        # in *args
        parent_depth = args[2]
        apparat = args[1]
        if header == "deleted" and parent_depth == 2:
            # TODO: warn message here
            logger.warning("Semesterapparat wurde bereits gelöscht")
        if parent_depth == 1:
            # person selected case - open all apparats from this person in the tableWidget
            self.tableWidget.setRowCount(0)
            name = apparat.split("(")[0].strip()
            prof_id = self.db.getProfId({"profname": name})
            apparats = self.db.getApparatsByProf(prof_id)
            for app in apparats:
                # set the items 0 = clickable checkbox, 1 = appname, 2 = profname, 3 = fach
                # insert new row
                self.tableWidget.insertRow(0)
                self.tableWidget.setItem(0, 0, QtWidgets.QTableWidgetItem(""))
                self.tableWidget.setItem(0, 1, QtWidgets.QTableWidgetItem(app[1]))
                self.tableWidget.setItem(0, 2, QtWidgets.QTableWidgetItem(str(app[4])))
                self.tableWidget.setItem(0, 3, QtWidgets.QTableWidgetItem(app[2]))
                self.tableWidget.setItem(0, 4, QtWidgets.QTableWidgetItem(app[3]))
                # replace the 0 with a checkbox
                checkbox = QtWidgets.QCheckBox()
                checkbox.setChecked(False)
                self.tableWidget.setCellWidget(0, 0, checkbox)
                # if i[9] is 1, set the background of the row to red
                if int(app[9]) == 1:
                    for j in range(5):
                        self.tableWidget.item(0, j).setBackground(
                            QtGui.QColor(235, 74, 71)
                        )
                    # disable the checkbox
                    self.tableWidget.cellWidget(0, 0).setEnabled(False)
                    # set the tooltip
                    self.tableWidget.cellWidget(0, 0).setToolTip(
                        "Dieser Semesterapparat kann nicht gelöscht werden, da er bereits gelöscht wurde"
                    )
        elif parent_depth == 2:
            # #print("depth", parent_depth)
            # apparat selected case - open the apparat in the frame
            self.apparat_open.emit(apparat)
        return

    def emit_signal(self, *args):
        # #print("emit_signal", *args)
        self.apparat_open.emit(args[1])


def show_ui():
    app = QtWidgets.QApplication([])
    window = SearchStatisticPage()
    window.show()
    app.exec()
