from flask import Flask, render_template, request, jsonify, session
import subprocess
import os
import uuid
import time
from datetime import datetime
import base64
import io
import platform
import socket
from PIL import Image

app = Flask(__name__)
app.secret_key = os.urandom(24)


class RemoteDesktop:
    def __init__(self):
        self.sessions = {}
        self.screen_quality = 80
        self.screen_scale = 0.7
        self.screenshot_method = None
        self._detect_screenshot_method()

    def _detect_screenshot_method(self):
        """Автоматическое определение доступного метода захвата экрана"""
        methods = []

        # Проверяем системные утилиты для Ubuntu
        if subprocess.run(['which', 'gnome-screenshot'], capture_output=True).returncode == 0:
            methods.append('gnome-screenshot')
        if subprocess.run(['which', 'scrot'], capture_output=True).returncode == 0:
            methods.append('scrot')
        if subprocess.run(['which', 'import'], capture_output=True).returncode == 0:
            methods.append('imagemagick')

        # Проверяем Python библиотеки
        try:
            import mss
            methods.append('mss')
        except ImportError:
            pass

        print(f"📸 Доступные методы захвата экрана: {methods}")

        if methods:
            self.screenshot_method = methods[0]
            print(f"✅ Выбран метод: {self.screenshot_method}")
        else:
            print("❌ Не найдены методы захвата экрана")

    def create_session(self):
        session_id = str(uuid.uuid4())
        self.sessions[session_id] = {
            'created_at': datetime.now(),
            'last_activity': datetime.now()
        }
        return session_id

    def get_system_info(self):
        """Получение информации о системе"""
        try:
            # Получаем информацию о дистрибутиве Ubuntu
            distro_info = ""
            try:
                with open('/etc/lsb-release', 'r') as f:
                    for line in f:
                        if line.startswith('DISTRIB_DESCRIPTION'):
                            distro_info = line.split('=')[1].strip().strip('"')
            except:
                distro_info = "Ubuntu (точная версия неизвестна)"

            system_info = {
                'distribution': distro_info,
                'platform': platform.system(),
                'platform_release': platform.release(),
                'architecture': platform.machine(),
                'hostname': socket.gethostname(),
                'username': os.getenv('USER'),
                'display': os.environ.get('DISPLAY', ':0'),
                'screenshot_method': self.screenshot_method,
                'python_version': platform.python_version(),
                'current_directory': os.getcwd()
            }
            return system_info
        except Exception as e:
            return {'error': str(e)}

    def capture_screenshot(self):
        """Создание скриншота рабочего стола"""
        try:
            if not self.screenshot_method:
                return None, "Не найдены методы захвата экрана"

            if self.screenshot_method == 'gnome-screenshot':
                return self._capture_with_gnome_screenshot()
            elif self.screenshot_method == 'scrot':
                return self._capture_with_scrot()
            elif self.screenshot_method == 'imagemagick':
                return self._capture_with_imagemagick()
            elif self.screenshot_method == 'mss':
                return self._capture_with_mss()
            else:
                return None, f"Неизвестный метод: {self.screenshot_method}"

        except Exception as e:
            return None, f"Ошибка захвата экрана: {str(e)}"

    def _capture_with_gnome_screenshot(self):
        """Захват экрана с помощью gnome-screenshot (рекомендуется для Ubuntu)"""
        try:
            # Используем временный файл для надежности
            temp_file = f"/tmp/screenshot_{int(time.time())}.png"

            result = subprocess.run([
                'gnome-screenshot', '-f', temp_file, '--include-pointer'
            ], capture_output=True, text=True, timeout=10)

            if result.returncode != 0:
                return None, f"GNOME Screenshot failed: {result.stderr}"

            # Читаем файл
            with open(temp_file, 'rb') as f:
                img_data = f.read()

            # Удаляем временный файл
            os.unlink(temp_file)

            img = Image.open(io.BytesIO(img_data))
            return self._encode_image(img), None

        except subprocess.TimeoutExpired:
            return None, "GNOME Screenshot timeout"
        except Exception as e:
            return None, f"GNOME Screenshot error: {str(e)}"

    def _capture_with_scrot(self):
        """Захват экрана с помощью scrot"""
        try:
            temp_file = f"/tmp/screenshot_{int(time.time())}.png"

            result = subprocess.run(['scrot', '-o', temp_file],
                                    capture_output=True, text=True, timeout=10)

            if result.returncode != 0:
                return None, f"Scrot failed: {result.stderr}"

            with open(temp_file, 'rb') as f:
                img_data = f.read()
            os.unlink(temp_file)

            img = Image.open(io.BytesIO(img_data))
            return self._encode_image(img), None

        except subprocess.TimeoutExpired:
            return None, "Scrot timeout"
        except Exception as e:
            return None, f"Scrot error: {str(e)}"

    def _capture_with_imagemagick(self):
        """Захват экрана с помощью ImageMagick"""
        try:
            result = subprocess.run(['import', '-window', 'root', 'png:-'],
                                    capture_output=True, timeout=10)

            if result.returncode != 0:
                return None, f"ImageMagick failed: {result.stderr}"

            img = Image.open(io.BytesIO(result.stdout))
            return self._encode_image(img), None
        except subprocess.TimeoutExpired:
            return None, "ImageMagick timeout"
        except Exception as e:
            return None, f"ImageMagick error: {str(e)}"

    def _capture_with_mss(self):
        """Захват экрана с помощью mss"""
        try:
            import mss
            with mss.mss() as sct:
                monitor = sct.monitors[1]
                screenshot = sct.grab(monitor)
                img = Image.frombytes("RGB", screenshot.size, screenshot.bgra, "raw", "BGRX")
                return self._encode_image(img), None
        except Exception as e:
            return None, f"MSS error: {str(e)}"

    def _encode_image(self, img):
        """Кодирование изображения в base64"""
        try:
            # Масштабирование
            if self.screen_scale != 1.0:
                new_size = (int(img.width * self.screen_scale),
                            int(img.height * self.screen_scale))
                img = img.resize(new_size, Image.Resampling.LANCZOS)

            buffer = io.BytesIO()
            img.save(buffer, format='JPEG', quality=self.screen_quality)
            return base64.b64encode(buffer.getvalue()).decode('utf-8')
        except Exception as e:
            raise Exception(f"Image encoding error: {str(e)}")

    def execute_command(self, command):
        """Выполнение команды в оболочке"""
        try:
            result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=30)
            output = result.stdout
            if result.stderr:
                output += f"\nSTDERR: {result.stderr}"
            return output, None
        except subprocess.TimeoutExpired:
            return None, "Command timeout"
        except Exception as e:
            return None, f"Command error: {str(e)}"

    def send_key(self, key):
        """Отправка клавиши (эмуляция)"""
        try:
            # Используем xdotool для эмуляции клавиатуры
            result = subprocess.run(['xdotool', 'key', key],
                                    capture_output=True, text=True, timeout=10)
            if result.returncode == 0:
                return True, None
            else:
                return False, result.stderr
        except Exception as e:
            return False, f"Keyboard error: {str(e)}"

    def mouse_click(self, x, y, button='left'):
        """Клик мыши в указанных координатах"""
        try:
            # Используем xdotool для эмуляции мыши
            if button == 'left':
                click_arg = '1'
            elif button == 'right':
                click_arg = '3'
            else:
                click_arg = '1'

            result = subprocess.run([
                'xdotool', 'mousemove', str(x), str(y), 'click', click_arg
            ], capture_output=True, text=True, timeout=10)

            if result.returncode == 0:
                return True, None
            else:
                return False, result.stderr
        except Exception as e:
            return False, f"Mouse click error: {str(e)}"


remote_desktop = RemoteDesktop()


@app.route('/')
def index():
    if 'session_id' not in session:
        session['session_id'] = remote_desktop.create_session()

    system_info = remote_desktop.get_system_info()
    return render_template('remote_desktop.html', system_info=system_info)


@app.route('/system-info')
def system_info():
    info = remote_desktop.get_system_info()
    return jsonify(info)


@app.route('/screenshot')
def screenshot():
    """Получение скриншота"""
    if 'session_id' not in session:
        return jsonify({'error': 'Сессия не найдена'})

    image_data, error = remote_desktop.capture_screenshot()
    if error:
        return jsonify({'error': error})

    return jsonify({'image': image_data})


@app.route('/command', methods=['POST'])
def execute_command():
    """Выполнение команды"""
    if 'session_id' not in session:
        return jsonify({'error': 'Сессия не найдена'})

    data = request.get_json()
    command = data.get('command', '').strip()

    if not command:
        return jsonify({'error': 'Пустая команда'})

    output, error = remote_desktop.execute_command(command)
    if error:
        return jsonify({'error': error})

    return jsonify({'output': output})


@app.route('/keyboard', methods=['POST'])
def keyboard_action():
    """Эмуляция клавиатуры"""
    if 'session_id' not in session:
        return jsonify({'error': 'Сессия не найдена'})

    data = request.get_json()
    key = data.get('key', '')

    if not key:
        return jsonify({'error': 'Не указана клавиша'})

    success, error = remote_desktop.send_key(key)
    if not success:
        return jsonify({'error': error})

    return jsonify({'status': 'success'})


@app.route('/mouse/click', methods=['POST'])
def mouse_click():
    """Клик мыши"""
    if 'session_id' not in session:
        return jsonify({'error': 'Сессия не найдена'})

    data = request.get_json()
    x = data.get('x', 0)
    y = data.get('y', 0)
    button = data.get('button', 'left')

    success, error = remote_desktop.mouse_click(x, y, button)
    if not success:
        return jsonify({'error': error})

    return jsonify({'status': 'success'})


@app.route('/settings', methods=['POST'])
def update_settings():
    """Обновление настроек"""
    if 'session_id' not in session:
        return jsonify({'error': 'Сессия не найдена'})

    data = request.get_json()
    quality = data.get('quality')
    scale = data.get('scale')

    if quality is not None:
        remote_desktop.screen_quality = max(10, min(100, quality))
    if scale is not None:
        remote_desktop.screen_scale = max(0.1, min(1.0, scale))

    return jsonify({
        'quality': remote_desktop.screen_quality,
        'scale': remote_desktop.screen_scale
    })


@app.route('/test')
def test_page():
    """Тестовая страница"""
    image_data, error = remote_desktop.capture_screenshot()

    if error:
        return f"""
        <html>
            <body style="background: #1e1e1e; color: white; font-family: Ubuntu, Arial; padding: 20px;">
                <h2>❌ Ошибка захвата экрана</h2>
                <p>{error}</p>
                <h3>Решение для Ubuntu:</h3>
                <code style="background: #2d2d30; padding: 15px; display: block;">
                sudo apt update<br>
                sudo apt install gnome-screenshot scrot imagemagick xdotool<br>
                pip install mss pillow
                </code>
            </body>
        </html>
        """

    return f"""
    <html>
        <body style="background: #1e1e1e; color: white; font-family: Ubuntu, Arial; padding: 20px;">
            <h2>✅ Тест захвата экрана - УСПЕШНО!</h2>
            <p>Метод: {remote_desktop.screenshot_method}</p>
            <img src="data:image/jpeg;base64,{image_data}" style="max-width: 800px; border: 2px solid #007acc; border-radius: 5px;">
            <p><a href="/" style="color: #007acc; text-decoration: none;">← Вернуться к удаленному рабочему столу</a></p>
        </body>
    </html>
    """


if __name__ == '__main__':
    os.makedirs('templates', exist_ok=True)

    with open('templates/remote_desktop.html', 'w', encoding='utf-8') as f:
        f.write('''<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Удаленный рабочий стол Ubuntu</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Ubuntu', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: #1e1e1e;
            color: #ffffff;
            line-height: 1.6;
        }

        .header {
            background: #2d2d30;
            padding: 20px;
            border-bottom: 1px solid #3e3e42;
            text-align: center;
        }

        .header h1 {
            color: #007acc;
            margin-bottom: 10px;
        }

        .controls {
            display: flex;
            gap: 10px;
            background: #2d2d30;
            padding: 15px;
            border-bottom: 1px solid #3e3e42;
            flex-wrap: wrap;
            justify-content: center;
        }

        button {
            background: #007acc;
            color: white;
            border: none;
            padding: 12px 20px;
            border-radius: 6px;
            cursor: pointer;
            font-size: 14px;
            font-family: 'Ubuntu', sans-serif;
            transition: background 0.3s;
        }

        button:hover {
            background: #005a9e;
            transform: translateY(-1px);
        }

        .desktop-container {
            position: relative;
            width: 100%;
            min-height: 500px;
            background: #000;
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 20px;
        }

        #remote-screen {
            max-width: 95%;
            max-height: 75vh;
            border: 3px solid #333;
            border-radius: 8px;
            box-shadow: 0 4px 20px rgba(0,0,0,0.5);
            cursor: crosshair;
        }

        .status-bar {
            background: #007acc;
            padding: 10px 20px;
            display: flex;
            justify-content: space-between;
            font-size: 14px;
            font-family: 'Ubuntu Mono', monospace;
        }

        .error-message {
            background: #d32f2f;
            color: white;
            padding: 15px;
            margin: 10px;
            border-radius: 6px;
            border-left: 4px solid #ff5252;
        }

        .info-panel {
            background: #2d2d30;
            padding: 20px;
            margin: 15px;
            border-radius: 8px;
            border: 1px solid #3e3e42;
            display: none;
        }

        .command-section {
            background: #2d2d30;
            padding: 20px;
            margin: 15px;
            border-radius: 8px;
        }

        .command-input {
            width: 100%;
            padding: 12px;
            background: #1e1e1e;
            border: 1px solid #3e3e42;
            color: white;
            border-radius: 6px;
            font-family: 'Ubuntu Mono', monospace;
            margin-bottom: 10px;
        }

        .placeholder {
            color: #888;
            font-size: 20px;
            text-align: center;
            padding: 60px 20px;
        }

        .success-badge {
            background: #388e3c;
            color: white;
            padding: 8px 16px;
            border-radius: 20px;
            font-size: 12px;
            display: inline-block;
            margin-left: 10px;
        }

        #command-output {
            background: #1e1e1e;
            padding: 15px;
            border-radius: 6px;
            margin-top: 10px;
            max-height: 300px;
            overflow-y: auto;
            font-family: 'Ubuntu Mono', monospace;
            font-size: 13px;
            white-space: pre-wrap;
            display: none;
        }
    </style>
</head>
<body>
    <div class="header">
        <h1>🖥️ Удаленный рабочий стол Ubuntu</h1>
        <p>Управление рабочим столом через веб-интерфейс</p>
    </div>

    <div class="controls">
        <button onclick="refreshScreen()">🔄 Обновить экран</button>
        <button onclick="toggleAutoRefresh()">⏱️ Авто-обновление</button>
        <button onclick="showSystemInfo()">ℹ️ Информация о системе</button>
        <button onclick="testConnection()">🧪 Тест подключения</button>
        <button onclick="sendEnter()">↵ Отправить Enter</button>
        <button onclick="sendCtrlC()">⎈ Ctrl+C</button>
    </div>

    <div id="error-container"></div>
    <div id="info-panel" class="info-panel"></div>

    <div class="desktop-container" id="desktop-container">
        <div id="screen-placeholder" class="placeholder">
            🖼️ Нажмите "Обновить экран" для захвата рабочего стола
        </div>
        <img id="remote-screen" style="display: none;" alt="Удаленный рабочий стол" 
             onclick="handleScreenClick(event)">
    </div>

    <div class="command-section">
        <h3>💻 Командная строка</h3>
        <input type="text" id="command-input" class="command-input" 
               placeholder="Введите команду (например: ls -la, pwd, gnome-terminal...)" 
               onkeypress="handleCommandInput(event)">
        <button onclick="executeCommand()" style="width: 200px;">⚡ Выполнить команду</button>
        <div id="command-output"></div>
    </div>

    <div class="status-bar">
        <span id="status-info">Статус: Готов</span>
        <span id="performance-info">Метод: {{ system_info.screenshot_method }} | Ubuntu</span>
    </div>

    <script>
        let autoRefreshInterval = null;
        let isAutoRefresh = false;

        const remoteScreen = document.getElementById('remote-screen');
        const screenPlaceholder = document.getElementById('screen-placeholder');
        const statusInfo = document.getElementById('status-info');
        const performanceInfo = document.getElementById('performance-info');
        const infoPanel = document.getElementById('info-panel');
        const errorContainer = document.getElementById('error-container');
        const commandOutput = document.getElementById('command-output');
        const commandInput = document.getElementById('command-input');

        // Инициализация
        document.addEventListener('DOMContentLoaded', function() {
            updateStatus('Система готова к работе');
            commandInput.focus();
        });

        function refreshScreen() {
            updateStatus('Захват экрана...');

            fetch('/screenshot?' + new Date().getTime())
                .then(response => response.json())
                .then(data => {
                    if (data.error) {
                        showError('Ошибка: ' + data.error);
                        screenPlaceholder.style.display = 'block';
                        remoteScreen.style.display = 'none';
                        screenPlaceholder.innerHTML = '❌ ' + data.error;
                    } else if (data.image) {
                        hideError();
                        remoteScreen.src = 'data:image/jpeg;base64,' + data.image;
                        screenPlaceholder.style.display = 'none';
                        remoteScreen.style.display = 'block';
                        updateStatus('Экран обновлен ✓');
                    }
                })
                .catch(error => {
                    showError('Ошибка подключения: ' + error);
                });
        }

        function toggleAutoRefresh() {
            isAutoRefresh = !isAutoRefresh;
            if (isAutoRefresh) {
                autoRefreshInterval = setInterval(refreshScreen, 3000);
                updateStatus('Авто-обновление включено (3 сек)');
            } else {
                clearInterval(autoRefreshInterval);
                updateStatus('Авто-обновление выключено');
            }
        }

        function executeCommand() {
            const command = commandInput.value.trim();
            if (!command) return;

            updateStatus('Выполнение команды...');
            commandOutput.style.display = 'block';
            commandOutput.textContent = 'Выполнение...';

            fetch('/command', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ command: command })
            })
            .then(response => response.json())
            .then(data => {
                if (data.error) {
                    commandOutput.textContent = 'Ошибка: ' + data.error;
                    commandOutput.style.color = '#ff5252';
                } else {
                    commandOutput.textContent = data.output;
                    commandOutput.style.color = '#4caf50';
                }
                updateStatus('Команда выполнена ✓');
                commandInput.value = '';
                commandInput.focus();
            })
            .catch(error => {
                commandOutput.textContent = 'Ошибка сети: ' + error;
                commandOutput.style.color = '#ff5252';
                updateStatus('Ошибка выполнения команды');
            });
        }

        function handleCommandInput(event) {
            if (event.key === 'Enter') {
                executeCommand();
            }
        }

        function handleScreenClick(event) {
            const rect = remoteScreen.getBoundingClientRect();
            const x = Math.round(event.clientX - rect.left);
            const y = Math.round(event.clientY - rect.top);

            // Масштабируем координаты для реального экрана
            const scaleX = remoteScreen.naturalWidth / rect.width;
            const scaleY = remoteScreen.naturalHeight / rect.height;
            const realX = Math.round(x * scaleX);
            const realY = Math.round(y * scaleY);

            fetch('/mouse/click', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ 
                    x: realX, 
                    y: realY,
                    button: event.button === 2 ? 'right' : 'left'
                })
            }).then(() => {
                updateStatus('Клик мыши отправлен ✓');
                setTimeout(refreshScreen, 500); // Обновляем экран после клика
            }).catch(error => {
                showError('Ошибка мыши: ' + error);
            });

            event.preventDefault();
        }

        function sendEnter() {
            fetch('/keyboard', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ key: 'Return' })
            }).then(() => {
                updateStatus('Enter отправлен ✓');
                setTimeout(refreshScreen, 500);
            }).catch(error => {
                showError('Ошибка клавиатуры: ' + error);
            });
        }

        function sendCtrlC() {
            fetch('/keyboard', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ key: 'ctrl+c' })
            }).then(() => {
                updateStatus('Ctrl+C отправлен ✓');
                setTimeout(refreshScreen, 500);
            }).catch(error => {
                showError('Ошибка клавиатуры: ' + error);
            });
        }

        function showSystemInfo() {
            fetch('/system-info')
                .then(response => response.json())
                .then(data => {
                    let infoHtml = '<h3>🖥️ Информация о системе Ubuntu:</h3>';
                    for (const [key, value] of Object.entries(data)) {
                        infoHtml += `<p><strong>${key}:</strong> ${value}</p>`;
                    }
                    infoPanel.innerHTML = infoHtml;
                    infoPanel.style.display = 'block';
                })
                .catch(error => {
                    showError('Ошибка загрузки информации: ' + error);
                });
        }

        function testConnection() {
            window.open('/test', '_blank');
        }

        function updateStatus(message) {
            statusInfo.textContent = 'Статус: ' + message;
        }

        function showError(message) {
            errorContainer.innerHTML = `<div class="error-message">${message}</div>`;
            updateStatus('Ошибка');
        }

        function hideError() {
            errorContainer.innerHTML = '';
        }

        // Запрещаем контекстное меню на изображении
        remoteScreen.addEventListener('contextmenu', function(e) {
            e.preventDefault();
        });
    </script>
</body>
</html>''')

    print("=" * 60)
    print("🖥️  УДАЛЕННЫЙ РАБОЧИЙ СТОЛ ДЛЯ UBUNTU")
    print("=" * 60)

    system_info = remote_desktop.get_system_info()
    print(f"💻 Система: {system_info.get('distribution', 'Ubuntu')}")
    print(f"📸 Метод захвата: {remote_desktop.screenshot_method}")

    if remote_desktop.screenshot_method:
        print("✅ Захват экрана настроен корректно")
    else:
        print("❌ Установите зависимости:")
        print("   sudo apt install gnome-screenshot scrot imagemagick xdotool")

    print("🌐 Сервер запущен: http://0.0.0.0:5000")
    print("🧪 Тест: http://0.0.0.0:5000/test")
    print("=" * 60)

    app.run(host='0.0.0.0', port=5000, debug=False, threaded=True)