#!/usr/bin/env python3
# quirinux-fix-libreoffice

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib
import subprocess
import threading
import locale
import socket
import sys

lang = locale.getlocale()[0] or ''
lang = lang[:2].lower()

MESSAGES = {
    'es': {
        'title': 'Quirinux - Actualización de LibreOffice',
        'info': 'Se va a reparar la instalación de LibreOffice para solucionar fallos detectados por la comunidad de Quirinux.\n\nEste proceso puede tardar varios minutos.\n\nPara realizar estos cambios será necesaria la contraseña de administración.',
        'button': 'Continuar',
        'progress': 'Reparando LibreOffice...',
        'done': '¡Proceso completado! LibreOffice ha sido restaurado correctamente.',
        'close': 'Cerrar',
        'error': 'Ocurrió un error durante el proceso. Intentaremos otra vez en el próximo reinicio.',
        'cancelled': 'Autenticación cancelada. Puede intentarlo de nuevo.',
        'no_internet': 'No se detectó conexión a internet. El proceso se volverá a intentar en el próximo reinicio.',
    },
    'gl': {
        'title': 'Quirinux - Actualización de LibreOffice',
        'info': 'Vaise reparar a instalación de LibreOffice para solucionar fallos detectados pola comunidade de Quirinux.\n\nEste proceso pode tardar varios minutos.\n\nPara realizar estes cambios será necesario o contrasinal de administración.',
        'button': 'Continuar',
        'progress': 'Reparando LibreOffice...',
        'done': 'Proceso completado! LibreOffice foi restaurado correctamente.',
        'close': 'Pechar',
        'error': 'Produciuse un erro durante o proceso. Tentaremos de novo no próximo reinicio.',
        'cancelled': 'Autenticación cancelada. Pode intentalo de novo.',
        'no_internet': 'Non se detectou conexión a internet. O proceso tentarase de novo no próximo reinicio.',
    },
    'de': {
        'title': 'Quirinux - LibreOffice-Aktualisierung',
        'info': 'Die LibreOffice-Installation wird repariert, um von der Quirinux-Community gemeldete Fehler zu beheben.\n\nDieser Vorgang kann einige Minuten dauern.\n\nFür diese Änderungen wird das Administratorpasswort benötigt.',
        'button': 'Weiter',
        'progress': 'LibreOffice wird repariert...',
        'done': 'Vorgang abgeschlossen! LibreOffice wurde erfolgreich wiederhergestellt.',
        'close': 'Schließen',
        'error': 'Während des Vorgangs ist ein Fehler aufgetreten. Beim nächsten Neustart wird es erneut versucht.',
        'cancelled': 'Authentifizierung abgebrochen. Sie können es erneut versuchen.',
        'no_internet': 'Keine Internetverbindung erkannt. Der Vorgang wird beim nächsten Neustart erneut versucht.',
    },
    'pt': {
        'title': 'Quirinux - Atualização do LibreOffice',
        'info': 'A instalação do LibreOffice será reparada para corrigir falhas detectadas pela comunidade Quirinux.\n\nEste processo pode demorar vários minutos.\n\nPara realizar estas alterações será necessária a senha de administrador.',
        'button': 'Continuar',
        'progress': 'Reparando LibreOffice...',
        'done': 'Processo concluído! O LibreOffice foi restaurado com sucesso.',
        'close': 'Fechar',
        'error': 'Ocorreu um erro durante o processo. Tentaremos novamente no próximo reinício.',
        'cancelled': 'Autenticação cancelada. Pode tentar novamente.',
        'no_internet': 'Nenhuma conexão à internet detectada. O processo será tentado novamente no próximo reinício.',
    },
    'fr': {
        'title': 'Quirinux - Mise à jour de LibreOffice',
        'info': 'L\'installation de LibreOffice va être réparée pour corriger des problèmes détectés par la communauté Quirinux.\n\nCe processus peut prendre plusieurs minutes.\n\nLe mot de passe administrateur sera nécessaire pour effectuer ces modifications.',
        'button': 'Continuer',
        'progress': 'Réparation de LibreOffice...',
        'done': 'Processus terminé ! LibreOffice a été restauré avec succès.',
        'close': 'Fermer',
        'error': 'Une erreur est survenue pendant le processus. Nous réessaierons au prochain redémarrage.',
        'cancelled': 'Authentification annulée. Vous pouvez réessayer.',
        'no_internet': 'Aucune connexion internet détectée. Le processus sera relancé au prochain redémarrage.',
    },
    'ru': {
        'title': 'Quirinux - Обновление LibreOffice',
        'info': 'Установка LibreOffice будет восстановлена для устранения ошибок, обнаруженных сообществом Quirinux.\n\nЭтот процесс может занять несколько минут.\n\nДля внесения этих изменений потребуется пароль администратора.',
        'button': 'Продолжить',
        'progress': 'Восстановление LibreOffice...',
        'done': 'Процесс завершён! LibreOffice успешно восстановлен.',
        'close': 'Закрыть',
        'error': 'В процессе произошла ошибка. Повторная попытка будет выполнена при следующей перезагрузке.',
        'cancelled': 'Аутентификация отменена. Вы можете повторить попытку.',
        'no_internet': 'Подключение к интернету не обнаружено. Повторная попытка будет выполнена при следующей перезагрузке.',
    },
    'it': {
        'title': 'Quirinux - Aggiornamento di LibreOffice',
        'info': 'L\'installazione di LibreOffice verrà riparata per risolvere i problemi segnalati dalla comunità Quirinux.\n\nQuesto processo potrebbe richiedere alcuni minuti.\n\nPer apportare queste modifiche sarà necessaria la password di amministratore.',
        'button': 'Continua',
        'progress': 'Riparazione di LibreOffice...',
        'done': 'Processo completato! LibreOffice è stato ripristinato correttamente.',
        'close': 'Chiudi',
        'error': 'Si è verificato un errore durante il processo. Riproveremo al prossimo riavvio.',
        'cancelled': 'Autenticazione annullata. È possibile riprovare.',
        'no_internet': 'Nessuna connessione internet rilevata. Il processo verrà ritentato al prossimo riavvio.',
    },
    'hu': {
        'title': 'Quirinux - LibreOffice frissítés',
        'info': 'A LibreOffice telepítése javításra kerül a Quirinux közösség által észlelt hibák kijavítása érdekében.\n\nEz a folyamat néhány percig tarthat.\n\nA módosítások elvégzéséhez rendszergazdai jelszó szükséges.',
        'button': 'Folytatás',
        'progress': 'LibreOffice javítása...',
        'done': 'A folyamat befejeződött! A LibreOffice sikeresen visszaállítva.',
        'close': 'Bezárás',
        'error': 'Hiba történt a folyamat során. A következő újraindításkor újra megpróbáljuk.',
        'cancelled': 'A hitelesítés megszakítva. Újra megpróbálhatja.',
        'no_internet': 'Nem észlelhető internetkapcsolat. A folyamat a következő újraindításkor újra megkísérelhető.',
    },
    'en': {
        'title': 'Quirinux - LibreOffice Update',
        'info': 'The LibreOffice installation will be repaired to fix issues detected by the Quirinux community.\n\nThis process may take several minutes.\n\nThe administrator password will be required to perform these changes.',
        'button': 'Continue',
        'progress': 'Repairing LibreOffice...',
        'done': 'Process complete! LibreOffice has been successfully restored.',
        'close': 'Close',
        'error': 'An error occurred during the process. We will try again at the next reboot.',
        'cancelled': 'Authentication cancelled. You can try again.',
        'no_internet': 'No internet connection detected. The process will be retried at the next reboot.',
    },
}

T = MESSAGES.get(lang, MESSAGES['en'])

def necesita_reparacion():
    """
    Devuelve True si:
    - Hay paquetes libreoffice instalados (ii) con versión backports (~bpo), O
    - Hay restos rotos (rc) de libreoffice sin versión funcional instalada.

    Devuelve False si LibreOffice está en versión estable de Daedalus/Quirinux
    (+deb12u, +q1, +q2, etc.) o no hay ninguna instalación.

    La cadena ~bpo es el marcador canónico de Debian/Devuan para backports.
    Ejemplos de versiones que activan la reparación:
        4:24.8.3~bpo12+1
        4:25.2.1~bpo13+1
    Ejemplos de versiones que NO activan la reparación:
        4:7.4.7-1+deb12u11   (estable Daedalus)
        1.1.2+q2             (paquete propio Quirinux)
    """
    try:
        result = subprocess.run(
            ['dpkg', '-l', 'libreoffice*'],
            capture_output=True, text=True
        )
        lineas = result.stdout.splitlines()

        tiene_backport = any(
            l.startswith('ii') and 'libreoffice' in l and '~bpo' in l
            for l in lineas
        )
        tiene_rotos = any(
            l.startswith('rc') and 'libreoffice' in l
            for l in lineas
        )
        return tiene_backport or tiene_rotos
    except Exception:
        return False


def check_internet():
    try:
        socket.setdefaulttimeout(5)
        socket.create_connection(('8.8.8.8', 53))
        return True
    except OSError:
        return False


class QuirinuxFixApp:

    def __init__(self):
        self.win = Gtk.Window(title=T['title'])
        self.win.set_border_width(20)
        self.win.set_default_size(480, 220)
        self.win.set_position(Gtk.WindowPosition.CENTER)
        self.win.set_resizable(False)
        self.win.connect('delete-event', Gtk.main_quit)

        self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=16)
        self.win.add(self.box)

        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=12)
        self.icon = Gtk.Image.new_from_icon_name('dialog-information', Gtk.IconSize.DIALOG)
        hbox.pack_start(self.icon, False, False, 0)

        self.label = Gtk.Label(label=T['info'])
        self.label.set_line_wrap(True)
        self.label.set_xalign(0)
        hbox.pack_start(self.label, True, True, 0)
        self.box.pack_start(hbox, True, True, 0)

        self.progress = Gtk.ProgressBar()
        self.progress.set_text(T['progress'])
        self.progress.set_show_text(True)
        self.progress.set_no_show_all(True)
        self.box.pack_start(self.progress, False, False, 0)

        self.button = Gtk.Button(label=T['button'])
        self.button.connect('clicked', self.on_start)
        self.box.pack_start(self.button, False, False, 0)

        self.win.show_all()

    def _show_final(self, message, icon_name='dialog-information'):
        self.icon.set_from_icon_name(icon_name, Gtk.IconSize.DIALOG)
        self.label.set_text(message)
        self.progress.hide()
        self.button.set_label(T['close'])
        self.button.set_sensitive(True)
        try:
            self.button.disconnect_by_func(self.on_start)
        except Exception:
            pass
        self.button.connect('clicked', lambda w: Gtk.main_quit())

    def on_start(self, widget):
        self.button.set_sensitive(False)

        if not check_internet():
            self._show_final(T['no_internet'], 'network-offline')
            return

        self.progress.show()
        self.label.set_text(T['progress'])
        self._pulse_id = GLib.timeout_add(100, self._pulse)
        thread = threading.Thread(target=self._wait_helper, daemon=True)
        thread.start()

    def _pulse(self):
        self.progress.pulse()
        return True

    def _wait_helper(self):
        try:
            result = subprocess.run(
                ['pkexec', '/usr/lib/quirinux/fix-libreoffice-helper'],
                capture_output=True
            )
            success = result.returncode == 0
            cancelled = result.returncode == 126
        except Exception:
            success = False
            cancelled = False

        GLib.idle_add(self._on_done, success, cancelled)

    def _on_done(self, success, cancelled):
        GLib.source_remove(self._pulse_id)
        self.progress.set_fraction(1.0)

        if cancelled:
            self.label.set_text(T['cancelled'])
            self.progress.hide()
            self.button.set_label(T['button'])
            self.button.set_sensitive(True)
            return

        if success:
            self._show_final(T['done'])
        else:
            self._show_final(T['error'], 'dialog-error')


if __name__ == '__main__':
    # Comprobación silenciosa ANTES de inicializar la GUI.
    # Si no hay nada que reparar, el proceso termina aquí
    # sin mostrar ninguna ventana y sin consumir recursos gráficos.
    if not necesita_reparacion():
        sys.exit(0)

    app = QuirinuxFixApp()
    Gtk.main()
