# Right-click a file, send it to your phone.
#
# macOS has a Share sheet in Finder and Windows has "Send to". Both are among
# the few context-menu entries people genuinely reach for, and neither exists
# on a stock Linux file manager.
#
# This adds no new machinery. Panama already talks to KDE Connect through
# scripts/panama-kdeconnect, which the Home & Phone settings page and the quick
# settings panel both use; this is the same `send-file` verb from the file
# manager instead of from a panel.
#
# The entry appears only when a phone is actually reachable. A menu item that
# is present and fails is worse than one that is absent, because the absence
# is self-explaining: no phone, no send.

import json
import os
import subprocess
from urllib.parse import unquote, urlparse

from gi.repository import GObject, Nautilus, Notify

HELPER = os.path.expanduser("~/.config/quickshell/scripts/panama-kdeconnect")


def _status():
    """What panama-kdeconnect reports, or None when it cannot be asked."""
    try:
        result = subprocess.run(
            [HELPER, "status"], capture_output=True, text=True, timeout=4, check=False
        )
        return json.loads(result.stdout) if result.returncode == 0 else None
    except (OSError, ValueError, subprocess.SubprocessError):
        return None


def _local_path(file_info):
    """A real filesystem path, or None for anything that is not one.

    Nautilus hands out URIs, and a remote or trashed file has one that no
    amount of unquoting turns into something sendable.
    """
    uri = file_info.get_uri()
    parsed = urlparse(uri)
    if parsed.scheme != "file":
        return None
    path = unquote(parsed.path)
    return path if os.path.isfile(path) else None


class PanamaShareExtension(GObject.GObject, Nautilus.MenuProvider):
    def __init__(self):
        super().__init__()
        Notify.init("Panama")

    def get_file_items(self, files):
        # One file at a time. KDE Connect's --share takes a single path, and
        # looping it for a selection of forty would be forty transfers and
        # forty notifications on the phone.
        if len(files) != 1:
            return []
        path = _local_path(files[0])
        if path is None:
            return []

        status = _status()
        if not status or not status.get("devices"):
            return []
        device = next(
            (d for d in status["devices"] if d.get("reachable") and d.get("id")), None
        )
        if device is None:
            return []

        item = Nautilus.MenuItem(
            name="Panama::SendToPhone",
            label=f"Send to {device.get('name') or 'phone'}",
            tip=f"Send this file to {device.get('name') or 'your phone'} with KDE Connect",
        )
        item.connect("activate", self._send, path, device["id"], device.get("name"))
        return [item]

    def _send(self, _menu, path, device_id, device_name):
        try:
            result = subprocess.run(
                [HELPER, "send-file", device_id, path],
                capture_output=True,
                text=True,
                timeout=30,
                check=False,
            )
            ok = result.returncode == 0
        except (OSError, subprocess.SubprocessError):
            ok = False

        name = os.path.basename(path)
        target = device_name or "your phone"
        notification = Notify.Notification.new(
            "Sent" if ok else "Could not send",
            f"{name} → {target}" if ok else f"{name} did not reach {target}",
            "phone-symbolic" if ok else "dialog-error-symbolic",
        )
        try:
            notification.show()
        except GObject.GError:
            pass
