import gi

gi.require_version("Gtk", "4.0")
import os
import threading
from typing import Any, Dict, Optional

from gi.repository import GLib, Gtk

from installation_backend import InstallationBackend

TARGET_ROOT = "/mnt/void"


class InstallationView(Gtk.Box):
    # Diese Seite zeigt den Fortschritt der Installation
    def __init__(self, *args, **kwargs):
        super().__init__(
            *args, **kwargs, 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(_("Installation"))
        title.add_css_class("title-2")
        title.set_halign(Gtk.Align.START)
        self.append(title)

        # Installationsschritte
        self.steps = [
            {
                "id": "partitioning",
                "label": _("1. Partitionen erstellen & formatieren"),
                "status": "queued",
            },
            {
                "id": "mounting",
                "label": _("2. Dateisysteme einhängen"),
                "status": "queued",
            },
            {
                "id": "install_base",
                "label": _("3. Basissystem und Pakete installieren"),
                "status": "queued",
            },
            {
                "id": "copy_customizations",
                "label": _("4. Anpassungen kopieren"),
                "status": "queued",
            },
            {
                "id": "configure_system",
                "label": _("5. System konfigurieren (fstab, Hostname, etc.)"),
                "status": "queued",
            },
            {
                "id": "configure_bootloader",
                "label": _("6. Bootloader (GRUB) installieren"),
                "status": "queued",
            },
        ]

        # Liste für die Schritte
        self.steps_listbox = Gtk.ListBox()
        self.steps_listbox.set_selection_mode(Gtk.SelectionMode.NONE)
        self.steps_listbox.add_css_class("boxed-list")
        self.append(self.steps_listbox)
        self._update_steps_ui()

        # Log Bereich
        log_frame = Gtk.Frame(label=_("Installations-Log"))
        log_frame.set_margin_top(8)
        self.append(log_frame)
        
        sc = Gtk.ScrolledWindow()
        sc.set_vexpand(True)
        sc.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        sc.set_min_content_height(150)
        log_frame.set_child(sc)
        
        self.textview = Gtk.TextView()
        self.textview.set_editable(False)
        self.textview.set_cursor_visible(False)
        self.textbuffer = self.textview.get_buffer()
        sc.set_child(self.textview)

        # Backend Initialisierung
        self.plan: Dict[str, Any] = {}
        self._worker: Optional[threading.Thread] = None
        self.target_root = TARGET_ROOT
        self.completion_callback = None
        self.backend = InstallationBackend(self.target_root, self._log)

    def _update_step_status(self, step_id: str, status: str, error_msg: Optional[str] = None):
        for step in self.steps:
            if step["id"] == step_id:
                step["status"] = status
                if error_msg:
                    step["error_msg"] = error_msg
                break
        GLib.idle_add(self._update_steps_ui)

    def _update_steps_ui(self):
        # Liste leeren
        child = self.steps_listbox.get_first_child()
        while child:
            self.steps_listbox.remove(child)
            child = self.steps_listbox.get_first_child()

        # Neu aufbauen
        for step in self.steps:
            row = Gtk.ListBoxRow()
            box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=12)
            # Hier war der Fehler - jetzt einzeln gesetzt:
            box.set_margin_top(10)
            box.set_margin_bottom(10)
            box.set_margin_start(10)
            box.set_margin_end(10)

            status = step["status"]
            if status == "running": icon, css = "⏳", "warning"
            elif status == "success": icon, css = "✅", "success"
            elif status == "failure": icon, css = "❌", "error"
            else: icon, css = "⚪", "dim-label"

            icon_label = Gtk.Label.new(icon)
            icon_label.add_css_class(css)
            box.append(icon_label)

            step_label = Gtk.Label.new(step["label"])
            step_label.set_halign(Gtk.Align.START)
            step_label.set_hexpand(True)
            box.append(step_label)

            row.set_child(box)
            self.steps_listbox.append(row)

    def set_plan(self, plan: Dict[str, Any]):
        self.plan = plan

    def set_completion_callback(self, callback):
        self.completion_callback = callback

    def start_installation(self):
        if self._worker and self._worker.is_alive():
            return
        self._worker = threading.Thread(target=self._run_install, daemon=True)
        self._worker.start()

    def _log(self, msg: str):
        def update_log():
            end_iter = self.textbuffer.get_end_iter()
            self.textbuffer.insert(end_iter, msg + "\n")
            # Auto-Scroll
            mark = self.textbuffer.create_mark(None, self.textbuffer.get_end_iter(), False)
            self.textview.scroll_mark_onscreen(mark)
        GLib.idle_add(update_log)

    def _run_install(self):
        current_step = "partitioning"
        try:
            self._log(_("Starte Installation..."))
            os.makedirs(self.target_root, exist_ok=True)
            
            # 1. Partitionierung
            self._update_step_status("partitioning", "running")
            mode = self.plan.get("mode", "erase")
            if mode == "erase":
                assignments = self.backend._apply_auto_partitioning_erase(self.plan)
            elif mode == "free":
                assignments = self.backend._apply_auto_partitioning_free(self.plan)
            elif mode == "existing":
                assignments = self.backend._apply_existing_partition(self.plan)
            self.plan["manual_partitions"] = assignments
            self._update_step_status("partitioning", "success")

            # 2. Mounting
            current_step = "mounting"
            self._update_step_status("mounting", "running")
            self.backend._mount_filesystems(self.plan)
            self._update_step_status("mounting", "success")

            # 3. Base Install
            current_step = "install_base"
            self._update_step_status("install_base", "running")
            self.backend._configure_mirror(self.plan)
            self.backend._xbps_install(self.plan)
            self._update_step_status("install_base", "success")

            # 4. Customizations
            current_step = "copy_customizations"
            self._update_step_status("copy_customizations", "running")
            copy_opt = self.plan.get("copy_option", "none")
            if copy_opt == "iso":
                self.backend._copy_iso_customizations()
            elif copy_opt == "include":
                self.backend._copy_include_root(self.plan.get("include_root", "/opt/INCLUDE"))
            self._update_step_status("copy_customizations", "success")

            # 5. Configuration
            current_step = "configure_system"
            self._update_step_status("configure_system", "running")
            self.backend._generate_fstab(self.plan)
            self.backend._configure_hostname(self.plan)
            self.backend._configure_locale_kbd(self.plan)
            self.backend._configure_timezone(self.plan)
            self.backend._configure_user(self.plan)
            self.backend._enable_services(self.plan)
            self.backend._configure_pipewire(self.plan)
            self._update_step_status("configure_system", "success")
            # --------------------------------------

            GLib.idle_add(self._update_step_status, current_step, "success")

            # 6. Bootloader
            current_step = "configure_bootloader"
            self._update_step_status("configure_bootloader", "running")
            self.backend._install_bootloader(self.plan)
            self._update_step_status("configure_bootloader", "success")

            self._log(_("\n=== INSTALLATION ERFOLGREICH ==="))
            if self.completion_callback:
                GLib.idle_add(self.completion_callback, True)

        except Exception as e:
            self._log(f"\nERROR in step '{current_step}': {e}")
            self._update_step_status(current_step, "failure", str(e))
            if self.completion_callback:
                GLib.idle_add(self.completion_callback, False)
        finally:
            self.backend._leave_chroot_mounts()
