from __future__ import annotations

from typing import Callable


def show_pairing_dialog(
    *,
    parent,
    adw_module,
    gtk_module,
    glib_module,
    status_adapter,
    translate: Callable[[str], str],
    on_complete: Callable[[], None] | None = None,
) -> None:
    """Open GTK dialog for entering a Pair Token and submitting pairing."""

    content = gtk_module.Box(orientation=gtk_module.Orientation.VERTICAL, spacing=10)
    content.set_margin_top(12)
    content.set_margin_bottom(12)
    content.set_margin_start(12)
    content.set_margin_end(12)

    hint = gtk_module.Label(label=translate("pairing.dialog.instruction"))
    hint.set_wrap(True)
    hint.set_xalign(0.0)
    content.append(hint)

    token_entry = gtk_module.Entry()
    token_entry.set_hexpand(True)
    token_entry.set_placeholder_text(translate("pairing.dialog.token.placeholder"))
    content.append(token_entry)

    error_label = gtk_module.Label(label="")
    error_label.set_wrap(True)
    error_label.set_xalign(0.0)
    error_label.add_css_class("error")
    error_label.set_visible(False)
    content.append(error_label)

    actions = gtk_module.Box(orientation=gtk_module.Orientation.HORIZONTAL, spacing=8)
    actions.set_halign(gtk_module.Align.END)

    paste_btn = gtk_module.Button(label=translate("pairing.dialog.paste"))
    pair_btn = gtk_module.Button(label=translate("pairing.dialog.pair"))
    pair_btn.add_css_class("suggested-action")

    actions.append(paste_btn)
    actions.append(pair_btn)
    content.append(actions)

    dialog = adw_module.MessageDialog(
        transient_for=parent,
        heading=translate("pairing.dialog.title"),
        body="",
    )
    dialog.set_extra_child(content)
    dialog.add_response("cancel", translate("dialog.cancel"))
    dialog.set_close_response("cancel")
    dialog.add_response("pair", translate("pairing.dialog.pair"))
    dialog.set_default_response("pair")
    dialog.set_response_appearance("pair", adw_module.ResponseAppearance.SUGGESTED)

    def _set_error(message: str) -> None:
        if message:
            error_label.set_label(message)
            error_label.set_visible(True)
        else:
            error_label.set_label("")
            error_label.set_visible(False)

    def _paste_from_clipboard(_btn):
        try:
            display = gtk_module.Display.get_default()
            if display is None:
                return
            clipboard = display.get_clipboard()
            clipboard.read_text_async(None, _on_clipboard_text, None)
        except Exception:
            _set_error(translate("pairing.error.clipboard_unavailable"))

    def _on_clipboard_text(_source, result, _user_data):
        try:
            text = _source.read_text_finish(result)
            if text:
                token_entry.set_text(str(text).strip())
                _set_error("")
        except Exception:
            _set_error(translate("pairing.error.clipboard_unavailable"))

    def _submit_pairing():
        token = str(token_entry.get_text() or "").strip()
        if not token:
            _set_error(translate("pairing.error.invalid_token"))
            return

        pair_btn.set_sensitive(False)
        paste_btn.set_sensitive(False)
        _set_error("")

        def _run_pairing():
            result = status_adapter.pair_with_token(token)
            glib_module.idle_add(_handle_pairing_result, result)
            return False

        glib_module.idle_add(_run_pairing)

    def _handle_pairing_result(result: dict[str, object]):
        pair_btn.set_sensitive(True)
        paste_btn.set_sensitive(True)

        if bool(result.get("ok")):
            dialog.close()
            if on_complete is not None:
                on_complete()
            success = adw_module.MessageDialog(
                transient_for=parent,
                heading=translate("pairing.success.title"),
                body=translate("pairing.success.body"),
            )
            success.add_response("ok", translate("dialog.ok"))
            success.set_close_response("ok")
            success.connect("response", lambda d, _r: d.close())
            success.present()
            return False

        status = str(result.get("status") or "backend_rejected")
        error_key = f"pairing.error.{status}"
        message = translate(error_key)
        if message == error_key:
            detail = str(result.get("detail") or "").strip()
            message = translate("pairing.error.backend_rejected")
            if detail:
                message = f"{message}\n{detail}"
        _set_error(message)
        return False

    def _on_response(_dialog, response):
        if response == "pair":
            _submit_pairing()
            return
        _dialog.close()

    paste_btn.connect("clicked", _paste_from_clipboard)
    pair_btn.connect("clicked", lambda _btn: _submit_pairing())
    token_entry.connect("activate", lambda _entry: _submit_pairing())
    dialog.connect("response", _on_response)
    dialog.present()
