#!/usr/bin/env python3

import gi
import subprocess
from pathlib import Path
import os
import pwd

gi.require_version("Gtk", "3.0")  # Or '4.0' if using GTK4
from gi.repository import Gtk, Gdk  # noqa: E402


def touch_user_file():
    """
    Touch a file under the *invoking user's* home directory,
    even when running under pkexec as root.
    """
    uid = os.environ.get("PKEXEC_UID") or os.getuid()
    home = pwd.getpwuid(int(uid)).pw_dir
    p = Path(home) / ".config/bmc-user-setup-done"
    p.parent.mkdir(parents=True, exist_ok=True)
    p.touch(exist_ok=True)
    return p


def check_password_strength(pwd: str) -> bool:
    """Return True if password meets requirements (customize as needed)."""
    if len(pwd) < 8:
        return False
    has_lower = any(c.islower() for c in pwd)
    has_upper = any(c.isupper() for c in pwd)
    has_num = any(c.isdigit() for c in pwd)
    has_special = any(c in "!@#$%^&*()_+-=[]{};':\",.<>/?\\|" for c in pwd)
    return has_lower and has_upper and has_num and has_special


class BMCUserConfigWindow(Gtk.Window):
    def __init__(self):
        super().__init__(title="BMC User Config")
        self.set_border_width(10)

        # Get monitor resolution and adjust window size
        screen = Gdk.Display.get_default().get_primary_monitor().get_geometry()
        screen_width = screen.width
        screen_height = screen.height

        # Set window size to 50% of screen width and height
        window_width = int(screen_width * 0.4)
        window_height = int(screen_height * 0.2)
        self.set_default_size(window_width, window_height)

        self.set_type_hint(
            Gdk.WindowTypeHint.DIALOG
        )  # Disable minimize, maximize, close buttons

        # Header Bar
        header_bar = Gtk.HeaderBar()
        header_bar.props.title = "BMC User Setup"
        header_bar.set_show_close_button(
            False
        )  # No close button in the header
        self.set_titlebar(header_bar)

        # Ignore Button
        #ignore_button = Gtk.Button(label="Ignore")
        #ignore_button.connect("clicked", lambda _: self.close())
        #header_bar.pack_start(ignore_button)

        # Confirm Button
        self.confirm_btn = Gtk.Button(label="Confirm")
        self.confirm_btn.set_sensitive(False)
        self.confirm_btn.connect("clicked", self.on_confirm)
        header_bar.pack_end(self.confirm_btn)

        # Main Layout
        grid = Gtk.Grid(row_spacing=10, column_spacing=10)
        self.add(grid)

        # Add empty placeholder labels to ensure equal column widths
        user_input_placeholder = Gtk.Label(label="")
        logo_placeholder = Gtk.Label(label="")

        # Placeholders allow automatic equal spacing
        user_input_placeholder.set_hexpand(True)
        logo_placeholder.set_hexpand(True)

        grid.attach(
            user_input_placeholder, 0, 0, 1, 1
        )  # Placeholder for equal width (user input column)
        grid.attach(
            logo_placeholder, 2, 0, 1, 1
        )  # Placeholder for equal width (logo column)

        # Logo (right side of the form)
        self.logo = Gtk.Image.new_from_file(
            "/usr/share/pixmaps/ubuntu-logo-text.png"
        )
        grid.attach(self.logo, 2, 1, 1, 4)

        # Username
        grid.attach(Gtk.Label(label="Username:"), 0, 1, 1, 1)
        self.username_entry = Gtk.Entry()
        grid.attach(self.username_entry, 1, 1, 1, 1)

        # Password
        grid.attach(Gtk.Label(label="Password:"), 0, 2, 1, 1)
        self.password_entry = Gtk.Entry()
        self.password_entry.set_visibility(False)
        self.password_entry.set_invisible_char("*")
        self.password_entry.connect("changed", self.on_password_changed)
        grid.attach(self.password_entry, 1, 2, 1, 1)

        # Show password checkbox
        self.show_pwd = Gtk.CheckButton(label="Show password")
        self.show_pwd.connect("toggled", self.toggle_password_visibility)
        grid.attach(self.show_pwd, 1, 3, 1, 1)

        # Password strength label
        self.strength_label = Gtk.Label(label="")
        grid.attach(self.strength_label, 1, 4, 1, 1)

    def toggle_password_visibility(self, widget):
        self.password_entry.set_visibility(widget.get_active())

    def on_password_changed(self, widget):
        pwd = widget.get_text()
        strong = check_password_strength(pwd)
        self.confirm_btn.set_sensitive(strong)
        self.strength_label.set_text(
            "Strong"
            if strong
            else "Weak (min 8 chars, upper/lower/num/symbol)"
        )

    def on_confirm(self, widget):
        username = self.username_entry.get_text()
        password = self.password_entry.get_text()
        try:
            # Do not mess up the command order
            cmd = [
                "sudo",
                "ipmi-config",
                "--commit",
                "--section=User3",
                f"--key-pair=User3:Username={username}",
            ]
            subprocess.run(
                cmd,
                check=True,
                capture_output=True,
                text=True,
            )

            cmd = [
                "sudo",
                "ipmi-config",
                "--commit",
                "--section=User3",
                f"--key-pair=User3:Password={password}",
            ]
            subprocess.run(
                cmd,
                check=True,
                capture_output=True,
                text=True,
            )

            cmd = [
                "sudo",
                "ipmi-config",
                "--commit",
                "--section=User3",
                "--key-pair=User3:Enable_User=Yes",
            ]
            subprocess.run(
                cmd,
                check=True,
                capture_output=True,
                text=True,
            )

            cmd = [
                "sudo",
                "ipmi-config",
                "--commit",
                "--section=User3",
                "--key-pair=User3:Lan_Privilege_Limit=Administrator",
            ]
            subprocess.run(
                cmd,
                check=True,
                capture_output=True,
                text=True,
            )

            cmd = [
                "sudo",
                "ipmi-config",
                "--commit",
                "--section=User1",
                "--key-pair=User1:Enable_User=No",
            ]
            subprocess.run(
                cmd,
                check=True,
                capture_output=True,
                text=True,
            )

            dialog = Gtk.MessageDialog(
                self,
                0,
                Gtk.MessageType.INFO,
                Gtk.ButtonsType.OK,
                "BMC config updated successfully.",
            )

            dialog.run()
            dialog.destroy()
            self.destroy()
            Gtk.main_quit()
        except Exception as e:
            dialog = Gtk.MessageDialog(
                self,
                0,
                Gtk.MessageType.ERROR,
                Gtk.ButtonsType.OK,
                f"Failed to set BMC user: {e}",
            )
            dialog.run()
            dialog.destroy()


win = BMCUserConfigWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
touch_user_file()
