import traceback

from lib.db import Users
from PyQt5.QtWidgets import QMessageBox
from ui.crud import Crud, Line_Edit_Cell_Widget
from ui.widget import Widget


class Users_Management(Widget):
    def __init__(self):
        super().__init__()

        class Username_Line_Edit_Cell_Widget(Line_Edit_Cell_Widget):
            def parse(self, action=None, row_number=None, crud=None):
                data = super().parse(action=action, row_number=row_number, crud=crud)
                if data is not None and len(data):
                    return data.upper()
                return None

        class Password_Line_Edit_Cell_Widget(Line_Edit_Cell_Widget):
            def _render(self, data, *args, **kwargs):
                data = [data, True]  # mark as hash
                super()._render(data, *args, **kwargs)

            def render(self, data, row_number=None, crud=None):
                if data is not None and data[0] is not None and len(data[0]):
                    data = "\u2022" * 8
                else:
                    data = None
                self.setText(data)

            def parse(self, action=None, row_number=None, crud=None):
                data = self.text()
                if data is not None and len(data):
                    return [data, False]  # mark as NOT hash
                return None

        class Roles_Line_Edit_Cell_Widget(Line_Edit_Cell_Widget):
            def render(self, data, row_number=None, crud=None):
                super().render(", ".join(data) if data is not None else None, row_number=row_number, crud=crud)

            def parse(self, action=None, row_number=None, crud=None):
                return Users.parse_roles(self.text())

        crud_aliases = {
            "id": "Id",
            "username": "Nome utente",
            "password": "Password",
            "roles": "Ruoli",
        }
        self.crud = Crud(
            "users",
            display_name="GESTIONE UTENTI",
            readonly=["id"],
            select=list(crud_aliases.keys()),
            fields_aliases=crud_aliases,
            autocomplete={"archived": False},
            widget_classes={
                "username": Username_Line_Edit_Cell_Widget,
                "password": Password_Line_Edit_Cell_Widget,
                "roles": Roles_Line_Edit_Cell_Widget,
            },
            row_filter=self.row_filter
        )
        self.layout().addWidget(self.crud, 0, 0, -1, -1)

    def row_filter(self, row, row_number, crud):
        if row["password"] is not None and all(map(lambda x: x == "\u2022", row["password"][0])):
            row.pop("password", None)
        else:
            try:
                if row["password"] is not None:
                    if row["password"][1] is False:
                        user = Users.generate(username=row["username"], password=row["password"][0], roles=row["roles"])
                    else:  # if user's password did not change it is already a hash
                        user = Users.generate(username=row["username"], password="temporary", roles=row["roles"])
                        user["password"] = row["password"][0]
                else:
                    user = Users.generate(username=row["username"], password=row["password"], roles=row["roles"])
            except AssertionError as e:
                self.log.exception(traceback.format_exc())
                self.crud.set_row_color(row_number, "red")
                QMessageBox.critical(None, "Errore Salvataggio DB", f"Errore alla riga {row_number}:\n{str(e)}")
                return False, None, True
            row.update(user)
        return True, row, False
