"""Abstract UI interface for Edubuntu Installer."""

from __future__ import annotations

from abc import ABC, abstractmethod
from collections.abc import Callable
from dataclasses import dataclass


@dataclass
class ChecklistItem:
    key: str
    label: str
    description: str
    checked: bool = False
    children: list["ChecklistItem"] | None = None


@dataclass
class ComboItem:
    label: str
    options: list[str]
    default: str = ""


class InstallerUI(ABC):

    @abstractmethod
    def show_info(self, title: str, text: str) -> None: ...

    @abstractmethod
    def show_error(self, title: str, text: str) -> None: ...

    @abstractmethod
    def show_warning(self, title: str, text: str) -> None: ...

    @abstractmethod
    def show_question(
        self,
        title: str,
        text: str,
        ok_label: str = "Yes",
        cancel_label: str = "No",
    ) -> bool: ...

    @abstractmethod
    def show_entry(
        self,
        title: str,
        text: str,
        default: str = "",
        ok_label: str = "OK",
        cancel_label: str = "Cancel",
    ) -> str | None: ...

    @abstractmethod
    def show_combo_dialog(
        self,
        title: str,
        text: str,
        combos: list[ComboItem],
        ok_label: str = "OK",
        cancel_label: str = "Cancel",
    ) -> list[str] | None: ...

    @abstractmethod
    def show_checklist(
        self,
        title: str,
        text: str,
        items: list[ChecklistItem],
        ok_label: str = "OK",
        cancel_label: str = "Cancel",
        width: int = 0,
        height: int = 0,
    ) -> list[str] | None: ...

    @abstractmethod
    def show_radiolist(
        self,
        title: str,
        text: str,
        items: list[ChecklistItem],
        ok_label: str = "OK",
        cancel_label: str = "Cancel",
        width: int = 0,
        height: int = 0,
    ) -> str | None: ...

    @abstractmethod
    def show_installer_tabs(
        self,
        title: str,
        pkg_text: str,
        pkg_items: list[ChecklistItem],
        global_setup_text: str,
        global_setup_items: list[ChecklistItem],
        per_user_setup_text: str,
        usernames: list[str],
        user_default_fn: Callable[[str], str],
        ok_label: str = "OK",
        cancel_label: str = "Cancel",
        width: int = 0,
        height: int = 0,
    ) -> tuple[list[str], str, str, str] | None:
        """Show a two-tab dialog: Packages + Default Setup.

        The Default Setup tab has two simultaneous sections — a Global
        radio-list and a Per-User radio-list with a user dropdown.
        *user_default_fn(username)* returns the current choice key for
        that user.

        Return *(selected_pkg_keys, global_choice_key, username,
        per_user_choice_key)* or *None* if the user cancelled."""

    @abstractmethod
    def show_progress(
        self,
        title: str,
        text: str,
        callback: Callable[
            [Callable[[str], None], Callable[[float], None]], None
        ],
    ) -> bool:
        """Run *callback* while showing a progress dialog with an
        expandable output log.

        *callback* receives two arguments:

        1. **on_output(line)** — call with each line of text to display
           in the collapsible terminal-style text view.
        2. **on_progress(fraction)** — call with a float 0.0–1.0 to
           switch the bar from indeterminate pulsing to a real
           percentage.  If never called, the bar stays indeterminate.

        Return True if it completed successfully."""

    @abstractmethod
    def init(self) -> None: ...

    @abstractmethod
    def quit(self) -> None: ...
