#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
SAIKYO OS License Activator - Modern GUI
Beautiful activation interface with dark theme
"""

import sys
import os
import subprocess
import re
from datetime import datetime

try:
    from PyQt6.QtWidgets import (
        QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
        QLabel, QPushButton, QLineEdit, QTextEdit, QFrame, QMessageBox,
        QFileDialog, QStackedWidget, QGroupBox, QSpacerItem, QSizePolicy
    )
    from PyQt6.QtCore import Qt, QTimer, QSize
    from PyQt6.QtGui import QFont, QPixmap, QIcon, QPalette, QColor
    PYQT_VERSION = 6
except ImportError:
    from PyQt5.QtWidgets import (
        QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
        QLabel, QPushButton, QLineEdit, QTextEdit, QFrame, QMessageBox,
        QFileDialog, QStackedWidget, QGroupBox, QSpacerItem, QSizePolicy
    )
    from PyQt5.QtCore import Qt, QTimer, QSize
    from PyQt5.QtGui import QFont, QPixmap, QIcon, QPalette, QColor
    PYQT_VERSION = 5

# Saikyo OS color scheme
COLORS = {
    'bg_dark': '#0a0a0a',
    'bg_card': '#1a1a1a',
    'bg_input': '#252525',
    'accent': '#00ff66',
    'accent_hover': '#00cc52',
    'text': '#ffffff',
    'text_secondary': '#888888',
    'border': '#333333',
    'success': '#00ff66',
    'warning': '#ffaa00',
    'error': '#ff4444',
}

STYLESHEET = f"""
QMainWindow, QWidget {{
    background-color: {COLORS['bg_dark']};
    color: {COLORS['text']};
    font-family: 'Segoe UI', 'Ubuntu', sans-serif;
}}

QLabel {{
    color: {COLORS['text']};
    background: transparent;
}}

QLabel#title {{
    font-size: 28px;
    font-weight: bold;
    color: {COLORS['accent']};
}}

QLabel#subtitle {{
    font-size: 14px;
    color: {COLORS['text_secondary']};
}}

QLabel#status_label {{
    font-size: 16px;
    font-weight: bold;
    padding: 10px;
    border-radius: 8px;
}}

QLabel#status_active {{
    background-color: rgba(0, 255, 102, 0.15);
    color: {COLORS['success']};
    border: 1px solid {COLORS['success']};
}}

QLabel#status_trial {{
    background-color: rgba(255, 170, 0, 0.15);
    color: {COLORS['warning']};
    border: 1px solid {COLORS['warning']};
}}

QLabel#status_expired, QLabel#status_missing {{
    background-color: rgba(255, 68, 68, 0.15);
    color: {COLORS['error']};
    border: 1px solid {COLORS['error']};
}}

QPushButton {{
    background-color: {COLORS['bg_card']};
    color: {COLORS['text']};
    border: 1px solid {COLORS['border']};
    border-radius: 8px;
    padding: 12px 24px;
    font-size: 14px;
    font-weight: 500;
    min-width: 120px;
}}

QPushButton:hover {{
    background-color: {COLORS['bg_input']};
    border-color: {COLORS['accent']};
}}

QPushButton:pressed {{
    background-color: {COLORS['accent']};
    color: {COLORS['bg_dark']};
}}

QPushButton#primary {{
    background-color: {COLORS['accent']};
    color: {COLORS['bg_dark']};
    border: none;
    font-weight: bold;
}}

QPushButton#primary:hover {{
    background-color: {COLORS['accent_hover']};
}}

QLineEdit, QTextEdit {{
    background-color: {COLORS['bg_input']};
    color: {COLORS['text']};
    border: 1px solid {COLORS['border']};
    border-radius: 6px;
    padding: 10px;
    font-size: 14px;
}}

QLineEdit:focus, QTextEdit:focus {{
    border-color: {COLORS['accent']};
}}

QGroupBox {{
    background-color: {COLORS['bg_card']};
    border: 1px solid {COLORS['border']};
    border-radius: 12px;
    margin-top: 16px;
    padding: 20px;
    font-size: 14px;
    font-weight: bold;
}}

QGroupBox::title {{
    subcontrol-origin: margin;
    left: 20px;
    padding: 0 10px;
    color: {COLORS['text_secondary']};
}}

QFrame#separator {{
    background-color: {COLORS['border']};
    max-height: 1px;
}}

QFrame#card {{
    background-color: {COLORS['bg_card']};
    border: 1px solid {COLORS['border']};
    border-radius: 12px;
    padding: 20px;
}}
"""


class LicenseManager:
    """Interface to saikyo-license CLI"""
    
    LICENSE_CMD = '/usr/sbin/saikyo-license'
    
    @classmethod
    def run_cmd(cls, *args):
        try:
            result = subprocess.run(
                [cls.LICENSE_CMD] + list(args),
                capture_output=True, text=True, timeout=30
            )
            return result.returncode, result.stdout, result.stderr
        except Exception as e:
            return -1, '', str(e)
    
    @classmethod
    def run_privileged(cls, *args):
        try:
            result = subprocess.run(
                ['pkexec', cls.LICENSE_CMD] + list(args),
                capture_output=True, text=True, timeout=60
            )
            return result.returncode, result.stdout, result.stderr
        except Exception as e:
            return -1, '', str(e)
    
    @classmethod
    def get_status(cls):
        code, out, err = cls.run_cmd('status')
        status = {
            'status': 'unknown',
            'trial_days': '',
            'trial_remaining_seconds': '0',
            'valid_until': '',
            'expired': 'no',
            'org_name': '',
            'tier': '',
            'machine_id': '',
        }
        for line in out.split('\n'):
            if '=' in line:
                k, v = line.split('=', 1)
                k = k.strip().replace('-', '_')
                status[k] = v.strip()
        return status
    
    @classmethod
    def verify(cls):
        code, _, _ = cls.run_cmd('verify')
        return code == 0
    
    @classmethod
    def install_code(cls, code):
        return cls.run_privileged('install-code', code)
    
    @classmethod
    def install_files(cls, json_path, sig_path):
        return cls.run_privileged('install', json_path, sig_path)
    
    @classmethod
    def activate_online(cls, token, server='https://saikyo-os.ru/license'):
        return cls.run_privileged('activate', '--token', token, '--server', server)
    
    @classmethod
    def get_machine_id(cls):
        try:
            with open('/etc/machine-id', 'r') as f:
                return f.read().strip()
        except:
            return 'Не удалось прочитать'


def human_duration(seconds):
    try:
        s = int(seconds)
    except:
        return '—'
    if s <= 0:
        return '0м'
    d = s // 86400
    h = (s % 86400) // 3600
    m = (s % 3600) // 60
    if d > 0:
        return f'{d}д {h}ч {m}м'
    elif h > 0:
        return f'{h}ч {m}м'
    else:
        return f'{m}м'


class StatusCard(QFrame):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setObjectName('card')
        self.setup_ui()
    
    def setup_ui(self):
        layout = QVBoxLayout(self)
        layout.setSpacing(16)
        
        # Status badge
        self.status_label = QLabel('Загрузка...')
        self.status_label.setObjectName('status_label')
        self.status_label.setAlignment(Qt.AlignmentFlag.AlignCenter if PYQT_VERSION == 6 else Qt.AlignCenter)
        layout.addWidget(self.status_label)
        
        # Info grid
        info_layout = QVBoxLayout()
        info_layout.setSpacing(8)
        
        self.org_label = self._create_info_row('Организация:', '—')
        self.tier_label = self._create_info_row('Тариф:', '—')
        self.remaining_label = self._create_info_row('Осталось:', '—')
        self.valid_until_label = self._create_info_row('Действует до:', '—')
        self.machine_id_label = self._create_info_row('Machine ID:', '—')
        
        info_layout.addLayout(self.org_label[0])
        info_layout.addLayout(self.tier_label[0])
        info_layout.addLayout(self.remaining_label[0])
        info_layout.addLayout(self.valid_until_label[0])
        info_layout.addLayout(self.machine_id_label[0])
        
        layout.addLayout(info_layout)
    
    def _create_info_row(self, label_text, value_text):
        layout = QHBoxLayout()
        label = QLabel(label_text)
        label.setStyleSheet(f'color: {COLORS["text_secondary"]}; font-size: 13px;')
        value = QLabel(value_text)
        value.setStyleSheet('font-size: 13px; font-weight: 500;')
        value.setTextInteractionFlags(Qt.TextInteractionFlag.TextSelectableByMouse if PYQT_VERSION == 6 else Qt.TextSelectableByMouse)
        layout.addWidget(label)
        layout.addStretch()
        layout.addWidget(value)
        return (layout, value)
    
    def update_status(self, status_data):
        status = status_data.get('status', 'unknown')
        
        # Update status badge
        if status == 'trial':
            self.status_label.setText('⏱ ПРОБНЫЙ ПЕРИОД')
            self.status_label.setObjectName('status_trial')
        elif status == 'missing':
            self.status_label.setText('⚠ НЕ АКТИВИРОВАНА')
            self.status_label.setObjectName('status_missing')
        elif status_data.get('expired') == 'yes':
            self.status_label.setText('✗ ИСТЕКЛА')
            self.status_label.setObjectName('status_expired')
        elif LicenseManager.verify():
            self.status_label.setText('✓ АКТИВНА')
            self.status_label.setObjectName('status_active')
        else:
            self.status_label.setText('? НЕИЗВЕСТНО')
            self.status_label.setObjectName('status_missing')
        
        # Force style refresh
        self.status_label.setStyleSheet(self.status_label.styleSheet())
        
        # Update info
        self.org_label[1].setText(status_data.get('org_name') or '—')
        self.tier_label[1].setText(status_data.get('tier') or '—')
        
        # Calculate remaining time
        if status == 'trial':
            remaining = human_duration(status_data.get('trial_remaining_seconds', 0))
        elif status_data.get('valid_until'):
            try:
                exp = datetime.fromisoformat(status_data['valid_until'].replace('Z', '+00:00'))
                now = datetime.now(exp.tzinfo) if exp.tzinfo else datetime.now()
                delta = (exp - now).total_seconds()
                remaining = human_duration(delta) if delta > 0 else 'Истекла'
            except:
                remaining = '—'
        else:
            remaining = '—'
        
        self.remaining_label[1].setText(remaining)
        self.valid_until_label[1].setText(status_data.get('valid_until') or '—')
        self.machine_id_label[1].setText(LicenseManager.get_machine_id()[:16] + '...')


class ActivationWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setup_ui()
    
    def setup_ui(self):
        layout = QVBoxLayout(self)
        layout.setSpacing(20)
        
        # Online activation
        online_group = QGroupBox('Онлайн активация')
        online_layout = QVBoxLayout(online_group)
        
        self.token_input = QLineEdit()
        self.token_input.setPlaceholderText('Введите токен активации...')
        online_layout.addWidget(self.token_input)
        
        self.activate_btn = QPushButton('Активировать')
        self.activate_btn.setObjectName('primary')
        self.activate_btn.clicked.connect(self.activate_online)
        online_layout.addWidget(self.activate_btn)
        
        layout.addWidget(online_group)
        
        # Offline activation
        offline_group = QGroupBox('Оффлайн активация (response-код)')
        offline_layout = QVBoxLayout(offline_group)
        
        self.code_input = QTextEdit()
        self.code_input.setPlaceholderText('Вставьте response-код (SAI-RC:... или SAI-RESP2:...)')
        self.code_input.setMaximumHeight(100)
        offline_layout.addWidget(self.code_input)
        
        self.offline_btn = QPushButton('Активировать оффлайн')
        self.offline_btn.clicked.connect(self.activate_offline)
        offline_layout.addWidget(self.offline_btn)
        
        layout.addWidget(offline_group)
        
        # File installation
        file_group = QGroupBox('Установка из файлов')
        file_layout = QVBoxLayout(file_group)
        
        file_hint = QLabel('Выберите license.json и license.sig')
        file_hint.setStyleSheet(f'color: {COLORS["text_secondary"]}; font-size: 12px;')
        file_layout.addWidget(file_hint)
        
        self.file_btn = QPushButton('Выбрать файлы...')
        self.file_btn.clicked.connect(self.install_from_files)
        file_layout.addWidget(self.file_btn)
        
        layout.addWidget(file_group)
        
        layout.addStretch()
    
    def activate_online(self):
        token = self.token_input.text().strip()
        if not token:
            QMessageBox.warning(self, 'Ошибка', 'Введите токен активации')
            return
        
        code, out, err = LicenseManager.activate_online(token)
        if code == 0:
            QMessageBox.information(self, 'Успех', 'Лицензия успешно активирована!')
            self.token_input.clear()
            self.parent().parent().refresh_status()
        else:
            QMessageBox.critical(self, 'Ошибка', f'Ошибка активации:\n{err or out}')
    
    def activate_offline(self):
        code = self.code_input.toPlainText().strip()
        if not code:
            QMessageBox.warning(self, 'Ошибка', 'Вставьте response-код')
            return
        
        ret, out, err = LicenseManager.install_code(code)
        if ret == 0:
            QMessageBox.information(self, 'Успех', 'Лицензия успешно установлена!')
            self.code_input.clear()
            self.parent().parent().refresh_status()
        else:
            QMessageBox.critical(self, 'Ошибка', f'Ошибка установки:\n{err or out}')
    
    def install_from_files(self):
        json_path, _ = QFileDialog.getOpenFileName(
            self, 'Выберите license.json', os.path.expanduser('~'),
            'JSON files (*.json);;All files (*)'
        )
        if not json_path:
            return
        
        sig_path, _ = QFileDialog.getOpenFileName(
            self, 'Выберите license.sig', os.path.dirname(json_path),
            'Signature files (*.sig);;All files (*)'
        )
        if not sig_path:
            return
        
        ret, out, err = LicenseManager.install_files(json_path, sig_path)
        if ret == 0:
            QMessageBox.information(self, 'Успех', 'Лицензия успешно установлена!')
            self.parent().parent().refresh_status()
        else:
            QMessageBox.critical(self, 'Ошибка', f'Ошибка установки:\n{err or out}')


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('SAIKYO OS — Активация лицензии')
        self.setMinimumSize(500, 650)
        self.setMaximumSize(600, 800)
        
        # Set window icon
        icon_path = '/usr/share/icons/hicolor/512x512/apps/saikyo-activation-logo.png'
        if os.path.exists(icon_path):
            self.setWindowIcon(QIcon(icon_path))
        
        self.setup_ui()
        self.refresh_status()
    
    def setup_ui(self):
        central = QWidget()
        self.setCentralWidget(central)
        
        layout = QVBoxLayout(central)
        layout.setContentsMargins(30, 30, 30, 30)
        layout.setSpacing(20)
        
        # Header
        header_layout = QVBoxLayout()
        header_layout.setSpacing(8)
        
        # Logo
        logo_path = '/usr/share/icons/hicolor/512x512/apps/saikyo-activation-logo.png'
        if os.path.exists(logo_path):
            logo_label = QLabel()
            pixmap = QPixmap(logo_path).scaled(
                80, 80,
                Qt.AspectRatioMode.KeepAspectRatio if PYQT_VERSION == 6 else Qt.KeepAspectRatio,
                Qt.TransformationMode.SmoothTransformation if PYQT_VERSION == 6 else Qt.SmoothTransformation
            )
            logo_label.setPixmap(pixmap)
            logo_label.setAlignment(Qt.AlignmentFlag.AlignCenter if PYQT_VERSION == 6 else Qt.AlignCenter)
            header_layout.addWidget(logo_label)
        
        title = QLabel('SAIKYO OS')
        title.setObjectName('title')
        title.setAlignment(Qt.AlignmentFlag.AlignCenter if PYQT_VERSION == 6 else Qt.AlignCenter)
        header_layout.addWidget(title)
        
        subtitle = QLabel('Активация лицензии')
        subtitle.setObjectName('subtitle')
        subtitle.setAlignment(Qt.AlignmentFlag.AlignCenter if PYQT_VERSION == 6 else Qt.AlignCenter)
        header_layout.addWidget(subtitle)
        
        layout.addLayout(header_layout)
        
        # Status card
        self.status_card = StatusCard()
        layout.addWidget(self.status_card)
        
        # Activation widget
        self.activation_widget = ActivationWidget(self)
        layout.addWidget(self.activation_widget)
        
        # Footer buttons
        footer_layout = QHBoxLayout()
        
        refresh_btn = QPushButton('Обновить')
        refresh_btn.clicked.connect(self.refresh_status)
        footer_layout.addWidget(refresh_btn)
        
        portal_btn = QPushButton('Открыть портал')
        portal_btn.clicked.connect(self.open_portal)
        footer_layout.addWidget(portal_btn)
        
        close_btn = QPushButton('Закрыть')
        close_btn.clicked.connect(self.close)
        footer_layout.addWidget(close_btn)
        
        layout.addLayout(footer_layout)
    
    def refresh_status(self):
        status = LicenseManager.get_status()
        self.status_card.update_status(status)
    
    def open_portal(self):
        try:
            subprocess.Popen(['xdg-open', 'https://saikyo-os.ru/license'],
                           stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        except:
            pass


def main():
    app = QApplication(sys.argv)
    app.setStyle('Fusion')
    app.setStyleSheet(STYLESHEET)
    
    # Dark palette
    palette = QPalette()
    palette.setColor(QPalette.ColorRole.Window if PYQT_VERSION == 6 else QPalette.Window, QColor(COLORS['bg_dark']))
    palette.setColor(QPalette.ColorRole.WindowText if PYQT_VERSION == 6 else QPalette.WindowText, QColor(COLORS['text']))
    palette.setColor(QPalette.ColorRole.Base if PYQT_VERSION == 6 else QPalette.Base, QColor(COLORS['bg_input']))
    palette.setColor(QPalette.ColorRole.Text if PYQT_VERSION == 6 else QPalette.Text, QColor(COLORS['text']))
    palette.setColor(QPalette.ColorRole.Button if PYQT_VERSION == 6 else QPalette.Button, QColor(COLORS['bg_card']))
    palette.setColor(QPalette.ColorRole.ButtonText if PYQT_VERSION == 6 else QPalette.ButtonText, QColor(COLORS['text']))
    palette.setColor(QPalette.ColorRole.Highlight if PYQT_VERSION == 6 else QPalette.Highlight, QColor(COLORS['accent']))
    app.setPalette(palette)
    
    window = MainWindow()
    window.show()
    
    sys.exit(app.exec() if PYQT_VERSION == 6 else app.exec_())


if __name__ == '__main__':
    main()
