import gi
import re
from typing import Dict

gi.require_version("Gtk", "4.0")
from gi.repository import Gtk

__all__ = ["UserConfigView"]

SHELLS = [
    ("Bash (Standard)", "/bin/bash"),
    ("Zsh (Z Shell)", "/bin/zsh"),
    ("Fish (Friendly Interactive Shell)", "/usr/bin/fish"),
]

class UserConfigView(Gtk.Box):
    # Page to configure username, hostname, password and root password

    def __init__(self):
        super().__init__(orientation=Gtk.Orientation.VERTICAL, spacing=8)
        for s in (
            self.set_margin_top,
            self.set_margin_bottom,
            self.set_margin_start,
            self.set_margin_end,
        ):
            s(6)

        title = Gtk.Label.new(_("Benutzerkonfiguration"))
        title.add_css_class("title-1")
        title.set_halign(Gtk.Align.START)
        self.append(title)

        info = Gtk.Label.new(
            _("Lege einen Benutzer und Hostname für dein System an. "
            "Alle Felder sind erforderlich für die Installation.")
        )
        info.set_wrap(True)
        info.set_halign(Gtk.Align.START)
        self.append(info)

        sc = Gtk.ScrolledWindow()
        sc.set_vexpand(True)
        sc.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
        self.append(sc)

        root = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12)
        sc.set_child(root)

        frm_user = Gtk.Frame(label=_("Benutzer & Host"))
        frm_user.add_css_class("card")
        root.append(frm_user)

        box_user = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8)
        for s in (
            box_user.set_margin_top,
            box_user.set_margin_bottom,
            box_user.set_margin_start,
            box_user.set_margin_end,
        ):
            s(6)
        frm_user.set_child(box_user)

        # Hostname
        row_hn = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)
        hostname_label = Gtk.Label.new(_("Hostname:"))
        hostname_label.set_xalign(0)
        hostname_label.set_hexpand(True)
        row_hn.append(hostname_label)
        self.entry_hostname = Gtk.Entry()
        self.entry_hostname.set_placeholder_text(_("z. B. voidbox"))
        row_hn.append(self.entry_hostname)
        box_user.append(row_hn)

        # Username
        row_un = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)
        username_label = Gtk.Label.new(_("Benutzername:"))
        username_label.set_xalign(0)
        username_label.set_hexpand(True)
        row_un.append(username_label)
        self.entry_username = Gtk.Entry()
        self.entry_username.set_placeholder_text(_("z. B. alice"))
        row_un.append(self.entry_username)
        box_user.append(row_un)

        separator = Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL)
        separator.set_margin_top(12)
        separator.set_margin_bottom(8)
        box_user.append(separator)

        # User Password
        row_pw = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)
        password_label = Gtk.Label.new(_("Passwort:"))
        password_label.set_xalign(0)
        password_label.set_hexpand(True)
        row_pw.append(password_label)
        self.entry_password = Gtk.Entry()
        self.entry_password.set_visibility(False)
        self.entry_password.set_input_purpose(Gtk.InputPurpose.PASSWORD)
        self.entry_password.set_placeholder_text(_("Passwort"))
        row_pw.append(self.entry_password)
        box_user.append(row_pw)

        row_pw_confirm = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)
        pw_confirm_label = Gtk.Label.new(_("Passwort wiederholen:"))
        pw_confirm_label.set_xalign(0)
        pw_confirm_label.set_hexpand(True)
        row_pw_confirm.append(pw_confirm_label)
        self.entry_password_confirm = Gtk.Entry()
        self.entry_password_confirm.set_visibility(False)
        self.entry_password_confirm.set_input_purpose(Gtk.InputPurpose.PASSWORD)
        self.entry_password_confirm.set_placeholder_text(_("Passwort bestätigen"))
        row_pw_confirm.append(self.entry_password_confirm)
        box_user.append(row_pw_confirm)

        separator = Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL)
        separator.set_margin_top(12)
        separator.set_margin_bottom(8)
        box_user.append(separator)

        # --- NEU: Checkbox für gleiches Passwort ---
        self.cb_same_password = Gtk.CheckButton.new_with_label(_("Gleiches Passwort für Root verwenden"))
        self.cb_same_password.connect("toggled", self._on_same_password_toggled)
        box_user.append(self.cb_same_password)
        # -------------------------------------------

        # Root Password
        row_root_pw = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)
        root_pw_label = Gtk.Label.new(_("Root-Passwort:"))
        root_pw_label.set_xalign(0)
        root_pw_label.set_hexpand(True)
        row_root_pw.append(root_pw_label)
        self.entry_root_password = Gtk.Entry()
        self.entry_root_password.set_visibility(False)
        self.entry_root_password.set_input_purpose(Gtk.InputPurpose.PASSWORD)
        self.entry_root_password.set_placeholder_text(_("Root-Passwort"))
        row_root_pw.append(self.entry_root_password)
        box_user.append(row_root_pw)

        row_root_pw_confirm = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)
        root_pw_confirm_label = Gtk.Label.new(_("Root-Passwort wiederholen:"))
        root_pw_confirm_label.set_xalign(0)
        root_pw_confirm_label.set_hexpand(True)
        row_root_pw_confirm.append(root_pw_confirm_label)
        self.entry_root_password_confirm = Gtk.Entry()
        self.entry_root_password_confirm.set_visibility(False)
        self.entry_root_password_confirm.set_input_purpose(Gtk.InputPurpose.PASSWORD)
        self.entry_root_password_confirm.set_placeholder_text(
            _("Root-Passwort bestätigen")
        )
        row_root_pw_confirm.append(self.entry_root_password_confirm)
        box_user.append(row_root_pw_confirm)

        separator = Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL)
        separator.set_margin_top(12)
        separator.set_margin_bottom(8)
        box_user.append(separator)

        # Shell Selection
        row_shell = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)
        shell_label = Gtk.Label.new(_("Standard-Shell:"))
        shell_label.set_xalign(0)
        shell_label.set_hexpand(True)
        row_shell.append(shell_label)
        
        self.cmb_shell = Gtk.ComboBoxText()
        for name, path in SHELLS:
            self.cmb_shell.append_text(name)
        self.cmb_shell.set_active(0)
        row_shell.append(self.cmb_shell)
        box_user.append(row_shell)

        # Hint Box
        hint_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8)
        hint_frame = Gtk.Frame(label="")
        hint_frame.add_css_class("card")
        root.append(hint_frame)

        hint_text = Gtk.Label.new(
            _("Hinweis:\n"
            "• Der Benutzer wird zur Gruppe 'wheel' hinzugefügt (sudo-Zugriff)\n"
            "• Root-Passwort ist separat vom Benutzer-Passwort\n"
            "• Hostname ist der Name deines Computers im Netzwerk\n"
            "• Nutze starke, einzigartige Passwörter für Sicherheit\n"
            "• Mindestens 6 Zeichen für alle Passwörter empfohlen")
        )
        hint_text.set_wrap(True)
        hint_text.set_halign(Gtk.Align.START)
        hint_text.set_use_markup(True)
        hint_box.append(hint_text)
        hint_frame.set_child(hint_box)

        # Decorative icons
        spacer = Gtk.Box()
        spacer.set_vexpand(True)
        root.append(spacer)

        icon_box = Gtk.Box(spacing=24)
        icon_box.set_halign(Gtk.Align.CENTER)
        icon_box.set_valign(Gtk.Align.END)

        icon_region = Gtk.Image.new_from_icon_name("avatar-default-symbolic")
        icon_region.set_pixel_size(120)
        icon_region.add_css_class("page-illustration")

        icon_keyboard = Gtk.Image.new_from_icon_name("dialog-password-symbolic")
        icon_keyboard.set_pixel_size(120)
        icon_keyboard.add_css_class("page-illustration")

        icon_box.append(icon_region)
        icon_box.append(icon_keyboard)

        root.append(icon_box)

    def _on_same_password_toggled(self, button):
        """Aktiviert/Deaktiviert die Root-Passwort-Felder basierend auf der Checkbox."""
        is_active = button.get_active()
        # Wenn aktiv, Felder deaktivieren (ausgrauen)
        self.entry_root_password.set_sensitive(not is_active)
        self.entry_root_password_confirm.set_sensitive(not is_active)
        
        if is_active:
            # Optional: Felder leeren, wenn deaktiviert, um Verwirrung zu vermeiden
            self.entry_root_password.set_text("")
            self.entry_root_password_confirm.set_text("")

    def validate_user_input(self):
        hostname = (self.entry_hostname.get_text() or "").strip()
        username = (self.entry_username.get_text() or "").strip()
        password = self.entry_password.get_text() or ""
        password_confirm = self.entry_password_confirm.get_text() or ""
        
        # Logik für Root-Passwort
        use_same_pw = self.cb_same_password.get_active()
        
        if use_same_pw:
            # Wir nehmen das User-Passwort als Root-Passwort an
            root_password = password
            root_password_confirm = password_confirm
        else:
            # Wir lesen die Felder aus
            root_password = self.entry_root_password.get_text() or ""
            root_password_confirm = self.entry_root_password_confirm.get_text() or ""

        if not hostname:
            raise ValueError(_("Hostname ist erforderlich."))
        if not username:
            raise ValueError(_("Benutzername ist erforderlich."))
        if not password:
            raise ValueError(_("Benutzer-Passwort ist erforderlich."))
        
        if not use_same_pw and not root_password:
             raise ValueError(_("Root-Passwort ist erforderlich."))

        if password != password_confirm:
            raise ValueError(
                _("Das Benutzer Passwort stimmt nicht überein. Bitte überprüfe deine eingabe.")
            )

        if not use_same_pw and (root_password != root_password_confirm):
            raise ValueError(
                _("Das Root Passwort stimmt nicht überein. Bitte überprüfe deine eingabe.")
            )

        if username != username.lower():
            raise ValueError(_("Benutzername darf keine Großbuchstaben enthalten."))

        if not re.match(r"^[a-z][a-z0-9_-]*$", username):
            raise ValueError(
                _("Benutzername darf nur Buchstaben, Zahlen, Unterstriche und Bindestriche enthalten und muss mit einem Buchstaben beginnen.")
            )

        if len(username) > 32:
            raise ValueError(_("Benutzername darf höchstens 32 Zeichen lang sein."))

        if username.startswith("-"):
            raise ValueError(_("Benutzername darf nicht mit einem Bindestrich beginnen."))

        if "--" in username:
            raise ValueError(
                _("Benutzername darf keine aufeinanderfolgenden Bindestriche enthalten.")
            )

        if not all(c.isalnum() or c in "-." for c in hostname):
            raise ValueError(
                _("Hostname darf nur Buchstaben, Nummern, Bindestriche und Punkte enthalten.")
            )

    def get_user_payload(self) -> Dict:
        out: Dict[str, object] = {}
        hostname = (self.entry_hostname.get_text() or "").strip()
        username = (self.entry_username.get_text() or "").strip()
        password = (self.entry_password.get_text() or "").strip()
        
        use_same_pw = self.cb_same_password.get_active()
        
        if use_same_pw:
            root_password = password
        else:
            root_password = self.entry_root_password.get_text() or ""

        out["hostname"] = hostname
        out["name"] = username.lower()
        out["password"] = password
        out["root_password"] = root_password
        
        # Shell
        idx = self.cmb_shell.get_active()
        if idx < 0: idx = 0
        out["shell"] = SHELLS[idx][1]

        if username:
            out["groups"] = [
                "wheel", "users", "audio", "video", "input", "render", "kvm", 
                "network", "lpadmin", "bluetooth", "storage", "optical", 
                "scanner", "plugdev", "dialout"
            ]

        return out