# SPDX-FileCopyrightText: 2024 Luca Weiss
# SPDX-License-Identifier: GPL-3.0-only

from gi.repository import GObject
from gi.repository import GdkPixbuf
from gi.repository import Gtk
from gi.repository import GLib
from .. import esim
from .. import helpers
from .. import notificationtask
from .. import widgets
import traceback


@Gtk.Template(resource_path="/eu/lucaweiss/lpa-gtk/pages/esimlist.ui")
class ESimListPage(Gtk.Box):
    __gtype_name__ = "LpaGtkESimList"

    overlay = Gtk.Template.Child()
    profile_list_box = Gtk.Template.Child()
    stack = Gtk.Template.Child()

    active_slot: int
    _manager: esim.ESimManager
    _notification_task: notificationtask.NotificationTask

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.profile_list_box.connect("row-activated", self._profile_selected)

    def icon_to_pixbuf(self, icon_data: bytes) -> GdkPixbuf.Pixbuf | None:
        if not icon_data:
            return None

        loader = GdkPixbuf.PixbufLoader()
        loader.write(icon_data)
        loader.close()
        return loader.get_pixbuf()

    @GObject.Signal(arg_types=(object,))
    def profile_selected(self, profile: esim.ESimProfile):
        pass

    @GObject.Signal
    def profile_add_clicked(self):
        pass

    def set_active_slot(self, slot: int) -> None:
        self.active_slot = slot

    def set_manager(self, manager: esim.ESimManager) -> None:
        self._manager = manager

    def set_no_backend(self) -> None:
        self.stack.set_visible_child_name("no-backend")

    def init_notification_task(self, available_slots: list[int], manager: esim.ESimManager) -> None:
        self._notification_task = notificationtask.NotificationTask(available_slots, manager)

    def _profile_selected(self, _list_box, profile_widget):
        self.emit("profile-selected", profile_widget.profile)

    def update(self):
        print("Updating eSIM profile list...")
        self.profile_list_box.remove_all()

        all_profiles = self._manager.get_profiles(self.active_slot)
        # Only show 'operational' profiles, skipping test & provisioning profiles
        # TODO: Make this contional, allow users to display these profiles if
        # they really want to. Then we also want to make sure to display the
        # profile class in the detail page - maybe always?
        profiles = list(filter(lambda p: p.profile_class == esim.ESimProfileClass.OPERATIONAL, all_profiles))
        for profile in profiles:
            w = widgets.ESimProfileWidget(
                title=profile.nickname or profile.name,
                enabled=profile.state == esim.ESimProfileState.ENABLED,
                provider=profile.service_provider_name,
                icon_pixbuf=self.icon_to_pixbuf(profile.icon),
            )
            w.profile = profile
            self.profile_list_box.append(w)

        if len(profiles):
            self.stack.set_visible_child_name("list")
        else:
            self.stack.set_visible_child_name("empty")

        def handle_success() -> None:
            print("eSIM notifications have been processed.")

        def handle_error(error: esim.ESimError, logs: list[str]) -> None:
            info = f"<tt>{GLib.markup_escape_text("".join(traceback.format_exception(error)))}</tt>\n"
            info += "Logs:\n"
            for line in logs:
                info += f" • {GLib.markup_escape_text(line)}\n"

            helpers.show_toast_info(self.overlay, self, "Failed to process eSIM notifications",
                                    info, markup=True)

        # Handle notifications in background
        self._notification_task.start(handle_success, handle_error)
