#!/usr/bin/env python3
"""
POPRAVEN SERVER со Sysmon обработка
"""
import traceback

from flask import Flask, request, jsonify, render_template_string
import json
import sqlite3
from datetime import datetime, timedelta
import time
import os
import socket
from collections import defaultdict
import threading
import requests
from openai import OpenAI
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()

OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
client = OpenAI(
    api_key=OPENAI_API_KEY,
    timeout=15  # максимум 15 секунди да чека
) if OPENAI_API_KEY else None


app = Flask(__name__)

DB_FILE = "lan_logs_sysmon.db"
LOG_DIR = "received_data_sysmon"

import secrets

ADMIN_KEY = os.environ.get("ADMIN_KEY", "")
ADMIN_KEY = os.environ.get("ADMIN_KEY", "")


def init_admin_tables():
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    c.execute('''CREATE TABLE IF NOT EXISTS environments(
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT UNIQUE,
        created_at TEXT
    )''')

    c.execute('''CREATE TABLE IF NOT EXISTS env_tokens(
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        env_name TEXT,
        token TEXT UNIQUE,
        created_at TEXT,
        expires_at TEXT
    )''')

    # migration ако табелата веќе постои
    c.execute("PRAGMA table_info(env_tokens)")
    cols = [r[1] for r in c.fetchall()]
    if "expires_at" not in cols:
        c.execute("ALTER TABLE env_tokens ADD COLUMN expires_at TEXT")

    c.execute('''CREATE TABLE IF NOT EXISTS admin_sessions(
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        token TEXT UNIQUE,
        created_at TEXT
    )''')

    # default env
    c.execute("INSERT OR IGNORE INTO environments(name, created_at) VALUES('default', datetime('now'))")

    conn.commit()
    conn.close()

def require_admin_session():
    tok = request.headers.get("X-Admin-Session", "")
    if not tok:
        return False
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    c.execute("SELECT 1 FROM admin_sessions WHERE token = ?", (tok,))
    ok = c.fetchone() is not None
    conn.close()
    return ok

def get_env_from_token(req):
    tok = req.headers.get("X-Env-Token", "")
    if not tok:
        return None

    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    c.execute("""
        SELECT env_name
        FROM env_tokens
        WHERE token = ?
          AND (expires_at IS NULL OR expires_at > datetime('now'))
    """, (tok,))
    row = c.fetchone()
    conn.close()
    return row[0] if row else None


def init_database():
    """Креирај подобрена база со Sysmon табели"""
    os.makedirs(LOG_DIR, exist_ok=True)

    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    # Табела за компјутери
    c.execute('''CREATE TABLE IF NOT EXISTS computers
                 (id INTEGER PRIMARY KEY AUTOINCREMENT,
                  name TEXT UNIQUE,
                  user TEXT,
                  ip TEXT,
                  os TEXT,
                  first_seen TIMESTAMP,
                  last_seen TIMESTAMP,
                  sysmon_available BOOLEAN DEFAULT 0)''')
    # --- MIGRATION: add env_name column if missing ---
    c.execute("PRAGMA table_info(computers)")
    cols = [r[1] for r in c.fetchall()]
    if "env_name" not in cols:
        c.execute("ALTER TABLE computers ADD COLUMN env_name TEXT DEFAULT 'default'")
    # --- END MIGRATION ---

    # Табела за историја
    c.execute('''CREATE TABLE IF NOT EXISTS computer_history
                 (id INTEGER PRIMARY KEY AUTOINCREMENT,
                  computer_id INTEGER,
                  cpu_usage REAL,
                  ram_usage REAL,
                  disk_usage REAL,
                  network_sent_mb REAL,
                  network_recv_mb REAL,
                  timestamp TIMESTAMP,
                  FOREIGN KEY(computer_id) REFERENCES computers(id))''')

    # Табела за процеси
    c.execute('''CREATE TABLE IF NOT EXISTS computer_processes
                 (id INTEGER PRIMARY KEY AUTOINCREMENT,
                  computer_id INTEGER,
                  pid INTEGER,
                  name TEXT,
                  cpu_percent REAL,
                  memory_mb REAL,
                  username TEXT,
                  cmdline TEXT,
                  timestamp TIMESTAMP,
                  FOREIGN KEY(computer_id) REFERENCES computers(id))''')

    # НОВА: Табела за Sysmon настани
    c.execute('''CREATE TABLE IF NOT EXISTS sysmon_events
                 (id INTEGER PRIMARY KEY AUTOINCREMENT,
                  computer_id INTEGER,
                  event_id INTEGER,
                  event_type TEXT,
                  message TEXT,
                  timestamp TIMESTAMP,
                  details TEXT,
                  FOREIGN KEY(computer_id) REFERENCES computers(id))''')

    # НОВА: Табела за детални мрежни конекции
    c.execute('''CREATE TABLE IF NOT EXISTS network_connections
                 (id INTEGER PRIMARY KEY AUTOINCREMENT,
                  computer_id INTEGER,
                  pid INTEGER,
                  local_address TEXT,
                  remote_address TEXT,
                  status TEXT,
                  process_name TEXT,
                  timestamp TIMESTAMP,
                  FOREIGN KEY(computer_id) REFERENCES computers(id))''')

    # НОВА: Табела за безбедносни настани
    c.execute('''CREATE TABLE IF NOT EXISTS security_alerts
                 (id INTEGER PRIMARY KEY AUTOINCREMENT,
                  computer_id INTEGER,
                  alert_type TEXT,
                  severity TEXT,
                  description TEXT,
                  timestamp TIMESTAMP,
                  resolved BOOLEAN DEFAULT 0,
                  FOREIGN KEY(computer_id) REFERENCES computers(id))''')

    conn.commit()
    conn.close()

    print(f"✅ Database created: {DB_FILE}")


@app.route('/receive', methods=['POST'])
def receive_data():
    try:
        data = request.json

        if not data:
            return jsonify({"error": "No data"}), 400
        env_name = get_env_from_token(request)
        if not env_name:
            return jsonify({"error": "Missing or invalid X-Env-Token"}), 401

        info = data['info']
        computer_name = info['computer_name']
        timestamp = datetime.now()
        security_data = data.get('security_data', {})

        conn = sqlite3.connect(DB_FILE)
        c = conn.cursor()

        # Провери дали компјутерот веќе постои
        c.execute("SELECT id FROM computers WHERE name = ?", (computer_name,))
        result = c.fetchone()

        if result:
            # Компјутерот постои - ажурирај го
            computer_id = result[0]
            c.execute('''UPDATE computers 
                        SET user = ?, ip = ?, os = ?, last_seen = ?, sysmon_available = ?, env_name = ?
                        WHERE id = ?''',
                      (info['user'], info['ip_address'], info['os'],
                       timestamp.isoformat(), info.get('is_sysmon_available', 0),
                       env_name, computer_id))
        else:
            # Нов компјутер - додади го
            c.execute('''INSERT INTO computers 
                        (name, user, ip, os, first_seen, last_seen, sysmon_available, env_name) 
                        VALUES (?, ?, ?, ?, ?, ?, ?, ?)''',
                      (computer_name, info['user'], info['ip_address'],
                       info['os'], timestamp.isoformat(), timestamp.isoformat(),
                       info.get('is_sysmon_available', 0), env_name))

            computer_id = c.lastrowid

        # Додади во историја
        c.execute('''INSERT INTO computer_history 
                    (computer_id, cpu_usage, ram_usage, disk_usage,
                     network_sent_mb, network_recv_mb, timestamp)
                    VALUES (?, ?, ?, ?, ?, ?, ?)''',
                  (computer_id, info['cpu_usage'], info['ram_usage'],
                   info['disk_usage'], info.get('network_sent_mb', 0),
                   info.get('network_recv_mb', 0), info['timestamp']))

        # Зачувај ги процесите
        for proc in data.get('processes', []):
            c.execute('''INSERT INTO computer_processes 
                        (computer_id, pid, name, cpu_percent, memory_mb, 
                         username, cmdline, timestamp)
                        VALUES (?, ?, ?, ?, ?, ?, ?, ?)''',
                      (computer_id, proc.get('pid'), proc.get('name'),
                       proc.get('cpu_percent', 0), proc.get('memory_mb', 0),
                       proc.get('user'), proc.get('cmdline'), info['timestamp']))

        # ЗАЧУВАЈ SYSMON НАСТАНИ
        sysmon_events_count = 0
        for event in security_data.get('sysmon_events', []):
            try:
                c.execute('''INSERT INTO sysmon_events 
                            (computer_id, event_id, event_type, message, 
                             timestamp, details)
                            VALUES (?, ?, ?, ?, ?, ?)''',
                          (computer_id, event.get('event_id'),
                           event.get('event_type', 'Unknown'),
                           event.get('message', ''),
                           event.get('timestamp', info['timestamp']),
                           json.dumps(event)))
                sysmon_events_count += 1
            except Exception as e:
                print(f"Error saving Sysmon event: {e}")

        # ЗАЧУВАЈ МРЕЖНИ КОНЕКЦИИ
        for conn_data in security_data.get('network_connections', []):
            try:
                c.execute('''INSERT INTO network_connections 
                            (computer_id, pid, local_address, remote_address,
                             status, process_name, timestamp)
                            VALUES (?, ?, ?, ?, ?, ?, ?)''',
                          (computer_id, conn_data.get('pid'),
                           conn_data.get('local_address'),
                           conn_data.get('remote_address'),
                           conn_data.get('status'),
                           conn_data.get('process_name'),
                           info['timestamp']))
            except Exception as e:
                print(f"Error saving network connection: {e}")

        conn.commit()
        conn.close()

        # Зачувај во JSON
        save_json_file(data)

        print(f"[{timestamp.strftime('%H:%M:%S')}] 📥 {computer_name}: "
              f"CPU {info['cpu_usage']}% | Sysmon: {sysmon_events_count} events")

        return jsonify({
            "status": "success",
            "message": f"Data saved for {computer_name}",
            "computer_id": computer_id,
            "event_count": sysmon_events_count,
            "timestamp": timestamp.isoformat()
        })

    except Exception as e:
        print(f"[-] Грешка: {e}")
        return jsonify({"error": str(e)}), 500


def save_json_file(data):
    """Зачувај во JSON"""
    info = data['info']
    computer_name = info['computer_name']
    date_str = datetime.now().strftime("%Y%m%d_%H")

    # Креирај folder за компјутерот
    computer_dir = os.path.join(LOG_DIR, computer_name)
    os.makedirs(computer_dir, exist_ok=True)

    # Фајл за секој час (за подобро организирање)
    filepath = os.path.join(computer_dir, f"{date_str}.json")

    # Додади во постоечки фајл или креирај нов
    if os.path.exists(filepath):
        with open(filepath, 'r', encoding='utf-8') as f:
            existing_data = json.load(f)
    else:
        existing_data = []

    # Додади нов запис
    existing_data.append({
        "timestamp": info['timestamp'],
        "info": info,
        "processes_count": len(data.get('processes', [])),
        "sysmon_events_count": len(data.get('security_data', {}).get('sysmon_events', []))
    })

    # Зачувај
    with open(filepath, 'w', encoding='utf-8') as f:
        json.dump(existing_data, f, indent=2, ensure_ascii=False)


@app.route('/')
def dashboard():
    """Главен dashboard"""
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    # Земaj ги сите компјутери
    c.execute('''SELECT name, user, ip, os, first_seen, last_seen, sysmon_available, env_name
                 FROM computers
                 ORDER BY last_seen DESC''')

    computers = []
    for row in c.fetchall():
        computer_name = row[0]

        # Пресметaj колку записи има во последните 24 часа
        c.execute('''SELECT COUNT(*) FROM computer_history 
                     WHERE computer_id = (SELECT id FROM computers WHERE name = ?)
                     AND timestamp > datetime('now', '-24 hours')''',
                  (computer_name,))
        recent_logs = c.fetchone()[0]

        # Земaj ги последните 5 записи за CPU/RAM
        c.execute('''SELECT cpu_usage, ram_usage, timestamp 
                     FROM computer_history 
                     WHERE computer_id = (SELECT id FROM computers WHERE name = ?)
                     ORDER BY timestamp DESC LIMIT 5''',
                  (computer_name,))
        recent_metrics = c.fetchall()

        # Sysmon настани за последните 24 часа
        c.execute('''SELECT COUNT(*) FROM sysmon_events 
                     WHERE computer_id = (SELECT id FROM computers WHERE name = ?)
                     AND timestamp > datetime('now', '-24 hours')''',
                  (computer_name,))
        recent_sysmon = c.fetchone()[0]

        # Пресметaj просек
        avg_cpu = sum(m[0] for m in recent_metrics) / len(recent_metrics) if recent_metrics else 0
        avg_ram = sum(m[1] for m in recent_metrics) / len(recent_metrics) if recent_metrics else 0

        # Статус
        last_seen = datetime.fromisoformat(row[5])
        time_diff = (datetime.now() - last_seen).seconds

        if time_diff < 60:
            status = 'online'
            status_color = 'green'
        elif time_diff < 300:
            status = 'idle'
            status_color = 'orange'
        else:
            status = 'offline'
            status_color = 'gray'

        computers.append({
            'name': row[0],
            'user': row[1],
            'ip': row[2],
            'os': row[3],
            'first_seen': row[4],
            'last_seen': row[5],
            'sysmon_available': bool(row[6]),
            'recent_logs': recent_logs,
            'recent_sysmon': recent_sysmon,
            'avg_cpu': round(avg_cpu, 1),
            'avg_ram': round(avg_ram, 1),
            'status': status,
            'status_color': status_color,
            'env_name': row[7],
        })

    conn.close()

    # Генерирај HTML
    return render_template_string('''
    <!DOCTYPE html>
    <html>
    <head>
        <title>LAN Log Server - Sysmon Dashboard</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
        <style>
            :root {
                --primary-color: #2c3e50;
                --secondary-color: #3498db;
                --danger-color: #e74c3c;
                --warning-color: #f39c12;
                --success-color: #27ae60;
            }

            body { 
                font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 
                margin: 0; 
                padding: 20px; 
                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                min-height: 100vh;
            }

            .container {
                max-width: 1400px;
                margin: 0 auto;
                background: white;
                border-radius: 15px;
                box-shadow: 0 20px 40px rgba(0,0,0,0.1);
                overflow: hidden;
            }

            .header {
                background: linear-gradient(to right, var(--primary-color), #1a2530);
                color: white;
                padding: 30px 40px;
                border-radius: 15px 15px 0 0;
            }

            .header h1 {
                margin: 0;
                font-size: 2.5em;
                display: flex;
                align-items: center;
                gap: 15px;
            }

            .stats-grid {
                display: grid;
                grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
                gap: 20px;
                padding: 30px;
            }

            .stat-card {
                background: white;
                padding: 25px;
                border-radius: 10px;
                box-shadow: 0 5px 15px rgba(0,0,0,0.08);
                border-left: 5px solid var(--secondary-color);
                transition: transform 0.3s ease;
            }

            .stat-card:hover {
                transform: translateY(-5px);
            }

            .stat-card.sysmon {
                border-left-color: var(--danger-color);
            }

            .stat-card.network {
                border-left-color: var(--success-color);
            }

            .stat-value {
                font-size: 2.8em;
                font-weight: bold;
                margin: 10px 0;
            }

            .stat-label {
                color: #666;
                font-size: 0.9em;
                text-transform: uppercase;
                letter-spacing: 1px;
            }

            .computers-grid {
                display: grid;
                grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
                gap: 25px;
                padding: 30px;
            }

            .computer-card {
                background: white;
                border-radius: 12px;
                padding: 25px;
                box-shadow: 0 8px 20px rgba(0,0,0,0.1);
                cursor: pointer;
                transition: all 0.3s ease;
                border: 2px solid transparent;
                position: relative;
                overflow: hidden;
            }

            .computer-card:hover {
                transform: translateY(-8px);
                box-shadow: 0 15px 30px rgba(0,0,0,0.15);
                border-color: var(--secondary-color);
            }

            .computer-card::before {
                content: '';
                position: absolute;
                top: 0;
                left: 0;
                right: 0;
                height: 4px;
                background: linear-gradient(to right, #667eea, #764ba2);
            }

            .computer-name {
                font-size: 1.4em;
                font-weight: bold;
                color: var(--primary-color);
                margin-bottom: 10px;
                display: flex;
                justify-content: space-between;
                align-items: center;
            }

            .status-indicator {
                display: inline-block;
                width: 12px;
                height: 12px;
                border-radius: 50%;
                margin-right: 8px;
            }

            .computer-info {
                color: #555;
                margin: 8px 0;
                font-size: 0.95em;
                display: flex;
                align-items: center;
                gap: 10px;
            }

            .computer-info i {
                width: 20px;
                color: #777;
            }

            .stats-row {
                display: flex;
                justify-content: space-between;
                margin-top: 20px;
                padding-top: 20px;
                border-top: 1px solid #eee;
            }

            .stat-item {
                text-align: center;
            }

            .stat-number {
                font-size: 1.6em;
                font-weight: bold;
                color: var(--primary-color);
            }

            .stat-text {
                font-size: 0.8em;
                color: #777;
                margin-top: 5px;
            }

            .sysmon-badge {
                background: var(--danger-color);
                color: white;
                padding: 3px 10px;
                border-radius: 20px;
                font-size: 0.8em;
                display: inline-block;
                margin-left: 10px;
            }

            /* Модал */
            .modal {
                display: none;
                position: fixed;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background: rgba(0,0,0,0.7);
                z-index: 1000;
                overflow-y: auto;
            }

            .modal-content {
                background: white;
                margin: 50px auto;
                width: 90%;
                max-width: 1200px;
                border-radius: 15px;
                animation: modalSlideIn 0.3s ease;
            }

            @keyframes modalSlideIn {
                from {
                    transform: translateY(-50px);
                    opacity: 0;
                }
                to {
                    transform: translateY(0);
                    opacity: 1;
                }
            }

            .modal-header {
                padding: 25px 30px;
                background: var(--primary-color);
                color: white;
                border-radius: 15px 15px 0 0;
                display: flex;
                justify-content: space-between;
                align-items: center;
            }

            .close-btn {
                background: none;
                border: none;
                color: white;
                font-size: 1.8em;
                cursor: pointer;
                width: 40px;
                height: 40px;
                border-radius: 50%;
                display: flex;
                align-items: center;
                justify-content: center;
                transition: background 0.2s;
            }

            .close-btn:hover {
                background: rgba(255,255,255,0.1);
            }

            .tabs {
                display: flex;
                border-bottom: 1px solid #ddd;
                padding: 0 30px;
                background: #f8f9fa;
            }

            .tab-btn {
                padding: 15px 25px;
                background: none;
                border: none;
                cursor: pointer;
                font-size: 1em;
                color: #666;
                position: relative;
                transition: all 0.3s;
            }

            .tab-btn:hover {
                color: var(--primary-color);
            }

            .tab-btn.active {
                color: var(--primary-color);
                font-weight: bold;
            }

            .tab-btn.active::after {
                content: '';
                position: absolute;
                bottom: -1px;
                left: 0;
                right: 0;
                height: 3px;
                background: var(--secondary-color);
            }

            .tab-content {
                padding: 30px;
                display: none;
            }

            .tab-content.active {
                display: block;
            }

            .events-table {
                width: 100%;
                border-collapse: collapse;
                margin-top: 20px;
            }

            .events-table th {
                background: #f8f9fa;
                padding: 15px;
                text-align: left;
                border-bottom: 2px solid #dee2e6;
                color: var(--primary-color);
            }

            .events-table td {
                padding: 12px 15px;
                border-bottom: 1px solid #eee;
            }

            .events-table tr:hover {
                background: #f8f9fa;
            }

            .severity-high {
                background: #ffe6e6;
                color: var(--danger-color);
                padding: 3px 10px;
                border-radius: 3px;
                font-weight: bold;
            }

            .severity-medium {
                background: #fff3cd;
                color: var(--warning-color);
                padding: 3px 10px;
                border-radius: 3px;
            }

            .event-details {
                max-width: 500px;
                word-wrap: break-word;
                font-family: monospace;
                font-size: 0.9em;
            }

            .filter-bar {
                padding: 20px 30px;
                background: #f8f9fa;
                border-bottom: 1px solid #ddd;
            }

            .search-box {
                padding: 10px 15px;
                border: 1px solid #ddd;
                border-radius: 5px;
                width: 300px;
            }

            .btn {
                padding: 10px 20px;
                background: var(--secondary-color);
                color: white;
                border: none;
                border-radius: 5px;
                cursor: pointer;
                transition: background 0.3s;
            }

            .btn:hover {
                background: #2980b9;
            }

            .chart-container {
                height: 300px;
                margin: 20px 0;
            }

            @media (max-width: 768px) {
                .computers-grid {
                    grid-template-columns: 1fr;
                }

                .modal-content {
                    width: 95%;
                    margin: 20px auto;
                }
            }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="header">
                <h1>
                    <span>🛡️ LAN Security Monitor</span>
                    <small style="font-size: 0.5em; opacity: 0.8;">Sysmon Edition</small>
                </h1>
                <p>Server: {{ socket.gethostbyname(socket.gethostname()) }}:5555 | Total Computers: {{ computers|length }}</p>
            </div>

            <div class="stats-grid">
                <div class="stat-card">
                    <div class="stat-label">Total Computers</div>
                    <div class="stat-value">{{ computers|length }}</div>
                    <div class="stat-text">Monitored Systems</div>
                </div>

                <div class="stat-card sysmon">
                    <div class="stat-label">Sysmon Events (24h)</div>
                    <div class="stat-value" id="total-sysmon">0</div>
                    <div class="stat-text">Security Events</div>
                </div>

                <div class="stat-card network">
                    <div class="stat-label">Network Connections</div>
                    <div class="stat-value" id="total-network">0</div>
                    <div class="stat-text">Active Connections</div>
                </div>
            </div>

            <div style="padding: 0 30px;">
                <h2>Connected Computers</h2>
                <div class="computers-grid" id="computers-grid">
                    {% for comp in computers %}
                    <div class="computer-card" onclick="showComputerDetails('{{ comp.name }}')">
                        <div class="computer-name">
                            {{ comp.name }}
                            <span class="status-indicator" style="background: {{ comp.status_color }}"></span>
                        </div>

                        <div class="computer-info">
                            <i>👤</i> {{ comp.user }}
                        </div>

                        <div class="computer-info">
                            <i>🌐</i> {{ comp.ip }}
                        </div>
                        <div class="computer-info">
                        <i>🏷️</i> Env: {{ comp.env_name }}</div>


                        <div class="computer-info">
                            <i>💻</i> {{ comp.os[:40] }}
                        </div>

                        <div class="computer-info">
                            <i>⏰</i> Last seen: {{ comp.last_seen[11:19] }}
                        </div>

                        {% if comp.sysmon_available %}
                        <div class="computer-info">
                            <i>🛡️</i> Sysmon Available
                            <span class="sysmon-badge">{{ comp.recent_sysmon }} events</span>
                        </div>
                        {% endif %}

                        <div class="stats-row">
                            <div class="stat-item">
                                <div class="stat-number">{{ comp.avg_cpu }}%</div>
                                <div class="stat-text">CPU</div>
                            </div>
                            <div class="stat-item">
                                <div class="stat-number">{{ comp.avg_ram }}%</div>
                                <div class="stat-text">RAM</div>
                            </div>
                            <div class="stat-item">
                                <div class="stat-number">{{ comp.recent_logs }}</div>
                                <div class="stat-text">Logs (24h)</div>
                            </div>
                        </div>
                    </div>
                    {% endfor %}
                </div>
            </div>
        </div>

        <!-- Детален модал -->
        <div class="modal" id="computer-modal">
            <div class="modal-content">
                <div class="modal-header">
                    <h2 id="modal-title">Computer Details</h2>
                    <button class="close-btn" onclick="closeModal()">×</button>
                </div>

                <div class="filter-bar">
                    <input type="text" id="event-search" class="search-box" placeholder="Search events..." 
                           onkeyup="filterEvents()">
                    <button class="btn" onclick="exportData()">Export Data</button>
                </div>

                <div class="tabs">
                    <button class="tab-btn active" onclick="switchTab('overview')">Overview</button>
                    <button class="tab-btn" onclick="switchTab('sysmon')">Sysmon Events</button>
                    <button class="tab-btn" onclick="switchTab('processes')">Processes</button>
                    <button class="tab-btn" onclick="switchTab('network')">Network</button>
                    <button class="tab-btn" onclick="switchTab('charts')">Charts</button>
                </div>

                <!-- Overview Tab -->
                <div class="tab-content active" id="overview-tab">
                    <h3>System Overview</h3>
                    <div id="overview-content"></div>
                </div>

                <!-- Sysmon Events Tab -->
                <div class="tab-content" id="sysmon-tab">
                    <h3>Security Events</h3>
                    <table class="events-table" id="sysmon-table">
                        <thead>
                            <tr>
                                <th>Time</th>
                                <th>Event ID</th>
                                <th>Type</th>
                                <th>Severity</th>
                                <th>Message</th>
                                <th>Actions</th>
                            </tr>
                        </thead>
                        <tbody id="sysmon-events">
                            <!-- Events will be populated here -->
                        </tbody>
                    </table>
                </div>

                <!-- Processes Tab -->
                <div class="tab-content" id="processes-tab">
                    <h3>Running Processes</h3>
                    <table class="events-table">
                        <thead>
                            <tr>
                                <th>PID</th>
                                <th>Name</th>
                                <th>User</th>
                                <th>CPU %</th>
                                <th>Memory</th>
                                <th>Command Line</th>
                            </tr>
                        </thead>
                        <tbody id="processes-list">
                            <!-- Processes will be populated here -->
                        </tbody>
                    </table>
                </div>

                <!-- Network Tab -->
                <div class="tab-content" id="network-tab">
                    <h3>Network Connections</h3>
                    <table class="events-table">
                        <thead>
                            <tr>
                                <th>PID</th>
                                <th>Process</th>
                                <th>Local Address</th>
                                <th>Remote Address</th>
                                <th>Status</th>
                                <th>Timestamp</th>
                            </tr>
                        </thead>
                        <tbody id="network-connections">
                            <!-- Connections will be populated here -->
                        </tbody>
                    </table>
                </div>

                <!-- Charts Tab -->
                <div class="tab-content" id="charts-tab">
                    <h3>Performance Analytics</h3>
                    <div class="chart-container">
                        <canvas id="performance-chart"></canvas>
                    </div>
                </div>
            </div>
        </div>

        <!-- Event Details Modal -->
        <div class="modal" id="event-modal" style="display: none;">
            <div class="modal-content" style="max-width: 800px;">
                <div class="modal-header">
                    <h2>Event Details</h2>
                    <button class="close-btn" onclick="closeEventModal()">×</button>
                </div>
                <div style="padding: 30px;">
                    <pre id="event-details-content" style="background: #f5f5f5; padding: 20px; border-radius: 5px; overflow: auto; max-height: 500px;"></pre>
                </div>
            </div>
        </div>

        <script>
            let currentComputer = null;
            let allSysmonEvents = [];

            function updateStats() {
                // Ажурирај ги вкупните статистики
                fetch('/api/stats')
                    .then(r => r.json())
                    .then(data => {
                        document.getElementById('total-sysmon').textContent = data.total_sysmon_events;
                        document.getElementById('total-network').textContent = data.total_network_connections;
                    });
            }

            function showComputerDetails(computerName) {
                currentComputer = computerName;

                // Покажи модал
                document.getElementById('computer-modal').style.display = 'block';
                document.getElementById('modal-title').textContent = computerName;

                // Вчитувај податоци
                loadComputerDetails(computerName);
            }

            function loadComputerDetails(computerName) {
                // Вчитувај целосни податоци за компјутерот
                fetch(`/api/computer/${encodeURIComponent(computerName)}`)
                    .then(response => response.json())
                    .then(data => {
                        populateOverview(data);
                        populateSysmonEvents(data);
                        populateProcesses(data);
                        populateNetwork(data);
                        updateCharts(data);
                    })
                    .catch(error => {
                        console.error('Error loading details:', error);
                    });
            }

            function populateOverview(data) {
                const overview = document.getElementById('overview-content');
                overview.innerHTML = `
                    <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px;">
                        <div>
                            <h4>System Information</h4>
                            <p><strong>User:</strong> ${data.computer.user}</p>
                            <p><strong>IP:</strong> ${data.computer.ip}</p>
                            <p><strong>OS:</strong> ${data.computer.os}</p>
                            <p><strong>First Seen:</strong> ${new Date(data.computer.first_seen).toLocaleString()}</p>
                            <p><strong>Last Seen:</strong> ${new Date(data.computer.last_seen).toLocaleString()}</p>
                            <p><strong>Total Logs:</strong> ${data.computer.total_logs}</p>
                        </div>
                        <div>
                            <h4>Current Status</h4>
                            <p><strong>CPU Usage:</strong> ${data.current_metrics?.cpu_usage || 0}%</p>
                            <p><strong>RAM Usage:</strong> ${data.current_metrics?.ram_usage || 0}%</p>
                            <p><strong>Disk Usage:</strong> ${data.current_metrics?.disk_usage || 0}%</p>
                            <p><strong>Network Sent:</strong> ${data.current_metrics?.network_sent_mb || 0} MB</p>
                            <p><strong>Network Received:</strong> ${data.current_metrics?.network_recv_mb || 0} MB</p>
                        </div>
                    </div>
                `;
            }

            function populateSysmonEvents(data) {
                const tableBody = document.getElementById('sysmon-events');
                tableBody.innerHTML = '';
                allSysmonEvents = data.sysmon_events || [];

                allSysmonEvents.forEach(event => {
                    const row = tableBody.insertRow();
                    const time = new Date(event.timestamp).toLocaleTimeString();
                    const severity = getSeverityForEvent(event.event_id);

                    row.innerHTML = `
                        <td>${time}</td>
                        <td>${event.event_id}</td>
                        <td>${event.event_type}</td>
                        <td><span class="severity-${severity}">${severity.toUpperCase()}</span></td>
                        <td class="event-details">${event.message.substring(0, 100)}...</td>
                        <td>
                            <button class="btn" style="padding: 5px 10px; font-size: 0.9em;" 
                                    onclick="showEventDetails(${JSON.stringify(event).replace(/"/g, '&quot;')})">
                                View Details
                            </button>
                        </td>
                    `;
                });
            }

            function populateProcesses(data) {
                const tableBody = document.getElementById('processes-list');
                tableBody.innerHTML = '';

                (data.recent_processes || []).forEach(proc => {
                    const row = tableBody.insertRow();
                    row.innerHTML = `
                        <td>${proc.pid}</td>
                        <td>${proc.name}</td>
                        <td>${proc.username}</td>
                        <td>${proc.cpu_percent || 0}</td>
                        <td>${proc.memory_mb || 0} MB</td>
                        <td class="event-details">${proc.cmdline || ''}</td>
                    `;
                });
            }

            function populateNetwork(data) {
                const tableBody = document.getElementById('network-connections');
                tableBody.innerHTML = '';

                (data.network_connections || []).forEach(conn => {
                    const row = tableBody.insertRow();
                    const time = new Date(conn.timestamp).toLocaleTimeString();
                    row.innerHTML = `
                        <td>${conn.pid}</td>
                        <td>${conn.process_name || 'N/A'}</td>
                        <td>${conn.local_address || 'N/A'}</td>
                        <td>${conn.remote_address || 'N/A'}</td>
                        <td>${conn.status}</td>
                        <td>${time}</td>
                    `;
                });
            }

            function updateCharts(data) {
                const ctx = document.getElementById('performance-chart').getContext('2d');
                const history = data.history || [];

                const labels = history.slice(-20).map(h => 
                    new Date(h.timestamp).toLocaleTimeString()
                );
                const cpuData = history.slice(-20).map(h => h.cpu_usage);
                const ramData = history.slice(-20).map(h => h.ram_usage);

                if(window.performanceChart) {
                    window.performanceChart.destroy();
                }

                window.performanceChart = new Chart(ctx, {
                    type: 'line',
                    data: {
                        labels: labels,
                        datasets: [
                            {
                                label: 'CPU Usage %',
                                data: cpuData,
                                borderColor: 'rgb(255, 99, 132)',
                                backgroundColor: 'rgba(255, 99, 132, 0.2)',
                                tension: 0.4
                            },
                            {
                                label: 'RAM Usage %',
                                data: ramData,
                                borderColor: 'rgb(54, 162, 235)',
                                backgroundColor: 'rgba(54, 162, 235, 0.2)',
                                tension: 0.4
                            }
                        ]
                    },
                    options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        scales: {
                            y: {
                                beginAtZero: true,
                                max: 100
                            }
                        }
                    }
                });
            }

            function getSeverityForEvent(eventId) {
                const highSeverity = [1, 3, 8, 10]; // Process creation, network, remote thread, process access
                const mediumSeverity = [5, 6, 7, 11, 22]; // Process termination, driver/image load, file create, DNS

                if (highSeverity.includes(parseInt(eventId))) return 'high';
                if (mediumSeverity.includes(parseInt(eventId))) return 'medium';
                return 'low';
            }

            function showEventDetails(event) {
                document.getElementById('event-details-content').textContent = 
                    JSON.stringify(event, null, 2);
                document.getElementById('event-modal').style.display = 'block';
            }

            function closeEventModal() {
                document.getElementById('event-modal').style.display = 'none';
            }

            function filterEvents() {
                const searchTerm = document.getElementById('event-search').value.toLowerCase();
                const tableBody = document.getElementById('sysmon-events');
                tableBody.innerHTML = '';

                allSysmonEvents
                    .filter(event => 
                        event.message.toLowerCase().includes(searchTerm) ||
                        event.event_type.toLowerCase().includes(searchTerm) ||
                        event.event_id.toString().includes(searchTerm)
                    )
                    .forEach(event => {
                        const row = tableBody.insertRow();
                        const time = new Date(event.timestamp).toLocaleTimeString();
                        const severity = getSeverityForEvent(event.event_id);

                        row.innerHTML = `
                            <td>${time}</td>
                            <td>${event.event_id}</td>
                            <td>${event.event_type}</td>
                            <td><span class="severity-${severity}">${severity.toUpperCase()}</span></td>
                            <td class="event-details">${event.message.substring(0, 100)}...</td>
                            <td>
                                <button class="btn" style="padding: 5px 10px; font-size: 0.9em;" 
                                        onclick="showEventDetails(${JSON.stringify(event).replace(/"/g, '&quot;')})">
                                    View Details
                                </button>
                            </td>
                        `;
                    });
            }

            function switchTab(tabName) {
                // Деактивирај сите tab-ови
                document.querySelectorAll('.tab-btn').forEach(btn => {
                    btn.classList.remove('active');
                });
                document.querySelectorAll('.tab-content').forEach(tab => {
                    tab.classList.remove('active');
                });

                // Активирај избраниот tab
                document.querySelector(`[onclick="switchTab('${tabName}')"]`).classList.add('active');
                document.getElementById(`${tabName}-tab`).classList.add('active');
            }

            function closeModal() {
                document.getElementById('computer-modal').style.display = 'none';
                currentComputer = null;
                allSysmonEvents = [];
            }

            function exportData() {
                if (!currentComputer) return;

                fetch(`/api/export/${encodeURIComponent(currentComputer)}`)
                    .then(response => response.blob())
                    .then(blob => {
                        const url = window.URL.createObjectURL(blob);
                        const a = document.createElement('a');
                        a.href = url;
                        a.download = `${currentComputer}_export_${new Date().toISOString().slice(0,10)}.json`;
                        document.body.appendChild(a);
                        a.click();
                        document.body.removeChild(a);
                    });
            }

            // Auto-refresh
            setInterval(() => {
                updateStats();

                // Ажурирај детали ако модал е отворен
                if (currentComputer && document.getElementById('computer-modal').style.display === 'block') {
                    loadComputerDetails(currentComputer);
                }
            }, 30000);

            // Затвори модал со Escape
            document.addEventListener('keydown', (e) => {
                if (e.key === 'Escape') {
                    closeModal();
                    closeEventModal();
                }
            });

            // Иницијализирај статистики при старт
            updateStats();
        </script>
    </body>
    </html>
    ''', computers=computers, socket=socket, datetime=datetime)


@app.route('/api/computer/<computer_name>')
def get_computer_details(computer_name):
    """Добиј сите детални информации за еден компјутер"""
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    # Основни информации
    c.execute('''SELECT id, name, user, ip, os, first_seen, last_seen 
                 FROM computers WHERE name = ?''', (computer_name,))
    computer_data = c.fetchone()

    if not computer_data:
        conn.close()
        return jsonify({"error": "Computer not found"}), 404

    computer_id = computer_data[0]

    # Број на сите записи
    c.execute('SELECT COUNT(*) FROM computer_history WHERE computer_id = ?', (computer_id,))
    total_logs = c.fetchone()[0]

    # Сите history записи
    c.execute('''SELECT cpu_usage, ram_usage, disk_usage, network_sent_mb, network_recv_mb, timestamp 
                 FROM computer_history 
                 WHERE computer_id = ? 
                 ORDER BY timestamp DESC LIMIT 100''', (computer_id,))
    history = []
    for row in c.fetchall():
        history.append({
            'cpu_usage': row[0],
            'ram_usage': row[1],
            'disk_usage': row[2],
            'network_sent_mb': row[3],
            'network_recv_mb': row[4],
            'timestamp': row[5]
        })

    # Последни метрики
    current_metrics = history[0] if history else {}

    # Последни процеси
    c.execute('''SELECT pid, name, username, cpu_percent, memory_mb, cmdline, timestamp 
                 FROM computer_processes 
                 WHERE computer_id = ? 
                 ORDER BY timestamp DESC LIMIT 100''', (computer_id,))
    recent_processes = []
    for row in c.fetchall():
        recent_processes.append({
            'pid': row[0],
            'name': row[1],
            'username': row[2],
            'cpu_percent': row[3],
            'memory_mb': row[4],
            'cmdline': row[5],
            'timestamp': row[6]
        })

    # SYSMON НАСТАНИ
    c.execute('''SELECT event_id, event_type, message, timestamp, details 
                 FROM sysmon_events 
                 WHERE computer_id = ? 
                 ORDER BY timestamp DESC LIMIT 200''', (computer_id,))
    sysmon_events = []
    for row in c.fetchall():
        try:
            details = json.loads(row[4]) if row[4] else {}
        except:
            details = {}

        sysmon_events.append({
            'event_id': row[0],
            'event_type': row[1],
            'message': row[2],
            'timestamp': row[3],
            'details': details
        })

    # Мрежни конекции
    c.execute('''SELECT pid, process_name, local_address, remote_address, status, timestamp 
                 FROM network_connections 
                 WHERE computer_id = ? 
                 ORDER BY timestamp DESC LIMIT 100''', (computer_id,))
    network_connections = []
    for row in c.fetchall():
        network_connections.append({
            'pid': row[0],
            'process_name': row[1],
            'local_address': row[2],
            'remote_address': row[3],
            'status': row[4],
            'timestamp': row[5]
        })

    conn.close()

    return jsonify({
        'computer': {
            'id': computer_data[0],
            'name': computer_data[1],
            'user': computer_data[2],
            'ip': computer_data[3],
            'os': computer_data[4],
            'first_seen': computer_data[5],
            'last_seen': computer_data[6],
            'total_logs': total_logs
        },
        'history': history,
        'current_metrics': current_metrics,
        'recent_processes': recent_processes,
        'sysmon_events': sysmon_events,
        'network_connections': network_connections
    })

@app.route('/api/computers')
def get_computers():
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    env = request.headers.get("X-Env", "default")

    c.execute('''SELECT name, user, ip, os, first_seen, last_seen, sysmon_available 
                 FROM computers 
                 WHERE env_name = ?
                 ORDER BY last_seen DESC''', (env,))

    computers = []
    for row in c.fetchall():
        computer_name = row[0]

        # recent logs
        c.execute('''SELECT COUNT(*) FROM computer_history 
                     WHERE computer_id = (SELECT id FROM computers WHERE name = ?)
                     AND timestamp > datetime('now', '-24 hours')''',
                  (computer_name,))
        recent_logs = c.fetchone()[0]

        # last 5 metrics
        c.execute('''SELECT cpu_usage, ram_usage, timestamp 
                     FROM computer_history 
                     WHERE computer_id = (SELECT id FROM computers WHERE name = ?)
                     ORDER BY timestamp DESC LIMIT 5''',
                  (computer_name,))
        recent_metrics = c.fetchall()

        c.execute('''SELECT COUNT(*) FROM sysmon_events 
                     WHERE computer_id = (SELECT id FROM computers WHERE name = ?)
                     AND timestamp > datetime('now', '-24 hours')''',
                  (computer_name,))
        recent_sysmon = c.fetchone()[0]

        avg_cpu = sum(m[0] for m in recent_metrics) / len(recent_metrics) if recent_metrics else 0
        avg_ram = sum(m[1] for m in recent_metrics) / len(recent_metrics) if recent_metrics else 0

        last_seen = datetime.fromisoformat(row[5])
        time_diff = (datetime.now() - last_seen).seconds

        if time_diff < 60:
            status = 'online'
            status_color = 'green'
        elif time_diff < 300:
            status = 'idle'
            status_color = 'orange'
        else:
            status = 'offline'
            status_color = 'gray'

        computers.append({
            'name': row[0],
            'user': row[1],
            'ip': row[2],
            'os': row[3],
            'first_seen': row[4],
            'last_seen': row[5],
            'sysmon_available': bool(row[6]),
            'recent_logs': recent_logs,
            'recent_sysmon': recent_sysmon,
            'avg_cpu': round(avg_cpu, 1),
            'avg_ram': round(avg_ram, 1),
            'status': status,
            'status_color': status_color
        })

    conn.close()
    return jsonify(computers)

@app.route('/api/stats')
def get_stats():
    """Добиј глобални статистики"""
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    # Вкупно Sysmon настани за последните 24 часа
    c.execute('''SELECT COUNT(*) FROM sysmon_events 
                 WHERE timestamp > datetime('now', '-24 hours')''')
    total_sysmon_events = c.fetchone()[0]

    # Вкупно мрежни конекции за последните 24 часа
    c.execute('''SELECT COUNT(*) FROM network_connections 
                 WHERE timestamp > datetime('now', '-24 hours')''')
    total_network_connections = c.fetchone()[0]

    conn.close()

    return jsonify({
        'total_sysmon_events': total_sysmon_events,
        'total_network_connections': total_network_connections,
        'server_time': datetime.now().isoformat()
    })

def build_rag_context(question, computer_name=None, limit_per_table=10):
    try:
        conn = sqlite3.connect(DB_FILE)
        c = conn.cursor()

        params = []
        comp_filter = ""
        if computer_name:
            comp_filter = "AND computer_id = (SELECT id FROM computers WHERE name = ?)"
            params.append(computer_name)

        # Sysmon настани
        c.execute(
            f"""
            SELECT timestamp, event_id, event_type, message
            FROM sysmon_events
            WHERE 1=1 {comp_filter}
            ORDER BY timestamp DESC
            LIMIT ?
            """,
            params + [limit_per_table],
        )
        sysmon_rows = c.fetchall()

        # Перформанс историја
        c.execute(
            f"""
            SELECT timestamp, cpu_usage, ram_usage, disk_usage,
                   network_sent_mb, network_recv_mb
            FROM computer_history
            WHERE 1=1 {comp_filter}
            ORDER BY timestamp DESC
            LIMIT ?
            """,
            params + [limit_per_table],
        )
        perf_rows = c.fetchall()

        # Процеси
        c.execute(
            f"""
            SELECT timestamp, pid, name, cpu_percent, memory_mb 
            FROM computer_processes
            WHERE 1=1 {comp_filter}
            ORDER BY timestamp DESC
            LIMIT ?
            """,
            params + [limit_per_table],
        )
        proc_rows = c.fetchall()

        conn.close()

        print("[RAG] sysmon:", len(sysmon_rows),
              "| perf:", len(perf_rows),
              "| proc:", len(proc_rows))

        lines = []

        for ts, eid, etype, msg in sysmon_rows:
            lines.append(f"[SYSMON] {ts} | Event {eid} ({etype}): {msg}")

        for ts, cpu, ram, disk, nsent, nrecv in perf_rows:
            lines.append(
                f"[PERF] {ts} | CPU {cpu}% | RAM {ram}% | Disk {disk}% | "
                f"Net sent {nsent}MB / recv {nrecv}MB"
            )

        for ts, pid, name, cpu, mem in proc_rows:
            lines.append(f"[PROC] {ts} | PID {pid} | {name} | CPU {cpu}% | RAM {mem}MB")

        context = "\n".join(lines)
        print("[RAG] sample context:\n", "\n".join(lines[:5]))
        return context

    except Exception as e:
        traceback.print_exc()
        return ""

# def ask_llm_with_context(question, context, language="mk"):
#     if not client:
#         return "Немаш поставено OPENAI_API_KEY на серверот."
#
#     system_msg = (
#         "Ти си асистент за безбедност и систем мониторинг. "
#         "Одговараш базирано ИСКЛУЧИВО на дадените логови што ти се дадени. "
#         "Ако нема доволно информации, кажи дека нема доволно податоци. "
#         "Објаснувај кратко и јасно."
#     )
#
#     user_msg = f"Прашање: {question}\n\nЛогови:\n{context or 'Нема логови.'}"
#
#     try:
#         completion = client.chat.completions.create(
#             model="gpt-4.1-mini",
#             messages=[
#                 {"role": "system", "content": system_msg},
#                 {"role": "user", "content": user_msg},
#             ],
#             temperature=0.2,
#         )
#         return completion.choices[0].message.content
#     except Exception as e:
#         # Може попрецизно: openai.APITimeoutError, openai.APIConnectionError итн.
#         return f"Грешка при повик кон LLM: {e}"

def ask_llm_with_context(question, context, language="mk"):
    """
    Вика OpenAI модел и враќа одговор базиран на контекстот од логови.
    """
    if not client:
        return "Немаш поставено OPENAI_API_KEY на серверот."

    system_msg = (
        "Ти си асистент за безбедност и систем мониторинг. "
        "Одговараш базирано ИСКЛУЧИВО на дадените логови што ти се дадени. "
        "Типови редови во логовите:\n"
        "- [SYSMON] ... Sysmon безбедносни настани.\n"
        "- [PERF] ... Општи перформанси (CPU, RAM, диск, мрежа).\n"
        "- [PROC] ... Информации за поединечни процеси: PID, име, CPU%, RAM MB.\n"
        "Кога корисникот прашува за процеси и нивна потрошувачка, "
        "СЕКОГАШ користи ги [PROC] редовите. "
        "Никогаш не кажувај дека 'нема информации за процеси' ако постои барем еден [PROC] ред. "
        "Ако навистина НЕМА [PROC] редови, тогаш можеш да кажеш дека нема доволно податоци. "
        "Објаснувај кратко и јасно."
    )

    user_msg = f"Прашање: {question}\n\nЛогови:\n{context or 'Нема логови.'}"

    try:
        print("[LLM] Calling OpenAI…")
        completion = client.chat.completions.create(
            model="gpt-4.1-mini",
            messages=[
                {"role": "system", "content": system_msg},
                {"role": "user", "content": user_msg},
            ],
            temperature=0.2,
        )
        print("[LLM] Got response")
        return completion.choices[0].message.content

    except Exception as e:
        print("[LLM] ERROR:", e)
        return f"Грешка при повик кон LLM: {e}"



#
# def ask_llm_with_context(question, context, language="mk"):
#     payload = {
#         "model": "deepseek-r1:1.5b",
#         "prompt": f"Прашање: {question}\n\nКонтекст:\n{context}",
#         "stream": False
#     }
#
#     try:
#         r = requests.post("http://localhost:11434/api/generate", json=payload)
#         r.raise_for_status()
#         data = r.json()
#         return data.get("response", "")
#     except Exception as e:
#         return f"Грешка при повик кон Ollama: {e}"


@app.route('/api/export/<computer_name>')
def export_computer_data(computer_name):
    """Експортирај ги сите податоци за еден компјутер"""
    data = {}

    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    # Основни информации за компјутерот
    c.execute('''SELECT * FROM computers WHERE name = ?''', (computer_name,))
    columns = [description[0] for description in c.description]
    computer_data = c.fetchone()

    if computer_data:
        data['computer'] = dict(zip(columns, computer_data))

        # Историја
        computer_id = computer_data[0]
        c.execute('''SELECT * FROM computer_history WHERE computer_id = ? ORDER BY timestamp''', (computer_id,))
        data['history'] = [dict(zip([d[0] for d in c.description], row)) for row in c.fetchall()]

        # Sysmon настани
        c.execute('''SELECT * FROM sysmon_events WHERE computer_id = ? ORDER BY timestamp''', (computer_id,))
        data['sysmon_events'] = [dict(zip([d[0] for d in c.description], row)) for row in c.fetchall()]

        # Процеси
        c.execute('''SELECT * FROM computer_processes WHERE computer_id = ? ORDER BY timestamp''', (computer_id,))
        data['processes'] = [dict(zip([d[0] for d in c.description], row)) for row in c.fetchall()]

        # Мрежни конекции
        c.execute('''SELECT * FROM network_connections WHERE computer_id = ? ORDER BY timestamp''', (computer_id,))
        data['network_connections'] = [dict(zip([d[0] for d in c.description], row)) for row in c.fetchall()]

    conn.close()

    # Креирај JSON одговор
    from flask import Response
    response = Response(
        json.dumps(data, indent=2, default=str),
        mimetype='application/json',
        headers={'Content-Disposition': f'attachment; filename={computer_name}_export.json'}
    )

    return response


@app.route('/ping')
def ping():
    return jsonify({
        'status': 'alive',
        'server_time': datetime.now().isoformat(),
        'version': '2.0_sysmon',
        'database': DB_FILE
    })


def get_local_ip():
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("8.8.8.8", 80))
        local_ip = s.getsockname()[0]
        s.close()
        return local_ip
    except:
        return "127.0.0.1"


def cleanup_old_data():
    """Чисти стари податоци од базата (стари од 30 дена)"""
    while True:
        time.sleep(3600)  # Чисти на секој час
        try:
            conn = sqlite3.connect(DB_FILE)
            c = conn.cursor()

            cutoff_date = (datetime.now() - timedelta(days=30)).isoformat()

            # Избриши стари записи
            c.execute("DELETE FROM computer_history WHERE timestamp < ?", (cutoff_date,))
            c.execute("DELETE FROM computer_processes WHERE timestamp < ?", (cutoff_date,))
            c.execute("DELETE FROM sysmon_events WHERE timestamp < ?", (cutoff_date,))
            c.execute("DELETE FROM network_connections WHERE timestamp < ?", (cutoff_date,))

            conn.commit()
            conn.close()

            print(f"[Cleanup] Избришани стари записи пред {cutoff_date}")

        except Exception as e:
            print(f"[Cleanup] Грешка: {e}")

import time
@app.route("/api/chat", methods=["POST"])
def api_chat():
    try:
        t0 = time.time()
        data = request.get_json(force=True) or {}
        question = data.get("question", "").strip()
        computer_name = data.get("computer_name") or None

        if not question:
            return jsonify({"error": "No question provided"}), 400

        context = build_rag_context(question, computer_name=computer_name)
        t1 = time.time()

        answer = ask_llm_with_context(question, context)
        t2 = time.time()

        print(f"[CHAT] build_rag_context: {t1 - t0:.2f}s, LLM: {t2 - t1:.2f}s")

        return jsonify({"answer": answer})
    except Exception as e:
        traceback.print_exc()
        return jsonify({"error": str(e)}), 500


@app.route('/api/computer/<computer_name>/sysmon')
def get_sysmon_processes(computer_name):
    """Добиј Sysmon процеси за компјутер"""
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    # Прво најди го computer_id
    c.execute('SELECT id FROM computers WHERE name = ?', (computer_name,))
    result = c.fetchone()

    if not result:
        conn.close()
        return jsonify({"error": "Computer not found"}), 404

    computer_id = result[0]

    # Земaj ги Sysmon процесите (последни 100)
    c.execute('''SELECT 
                 event_id, 
                 event_type, 
                 message, 
                 timestamp, 
                 details
                 FROM sysmon_events 
                 WHERE computer_id = ? 
                 ORDER BY timestamp DESC LIMIT 100''', (computer_id,))

    processes = []
    for row in c.fetchall():
        try:
            details = json.loads(row[4]) if row[4] else {}
        except:
            details = {}

        processes.append({
            'process_id': row[0],  # Event ID како PID
            'process_name': row[1],  # Event type како име
            'timestamp': row[3],
            'message': row[2],
            'details': details
        })

    conn.close()

    return jsonify({
        'computer_name': computer_name,
        'processes': processes,
        'count': len(processes)
    })


@app.route('/api/computer/<computer_name>/network')
def get_network_connections(computer_name):
    """Добиј мрежни конекции за компјутер"""
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    # Прво најди го computer_id
    c.execute('SELECT id FROM computers WHERE name = ?', (computer_name,))
    result = c.fetchone()

    if not result:
        conn.close()
        return jsonify({"error": "Computer not found"}), 404

    computer_id = result[0]

    # Земaj ги мрежните конекции (последни 100)
    c.execute('''SELECT 
                 pid, 
                 process_name, 
                 local_address, 
                 remote_address,
                 status, 
                 timestamp
                 FROM network_connections 
                 WHERE computer_id = ? 
                 ORDER BY timestamp DESC LIMIT 100''', (computer_id,))

    connections = []
    for row in c.fetchall():
        # Парсирај IP и порта
        local = row[2] or "N/A"
        remote = row[3] or "N/A"

        connections.append({
            'pid': row[0],
            'process_name': row[1] or 'Unknown',
            'local_address': local,
            'remote_address': remote,
            'local_port': local.split(':')[-1] if ':' in local else '',
            'remote_port': remote.split(':')[-1] if ':' in remote else '',
            'protocol': 'TCP' if ':443' in local or ':80' in local else 'Unknown',
            'state': row[4] or 'ESTABLISHED',
            'timestamp': row[5]
        })

    conn.close()

    return jsonify({
        'computer_name': computer_name,
        'connections': connections,
        'count': len(connections)
    })


@app.route('/api/computer/<computer_name>/detailed-sysmon')
def get_detailed_sysmon(computer_name):
    """Добиј детални Sysmon процеси со повеќе информации"""
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    c.execute('SELECT id FROM computers WHERE name = ?', (computer_name,))
    result = c.fetchone()

    if not result:
        conn.close()
        return jsonify({"error": "Computer not found"}), 404

    computer_id = result[0]

    c.execute('''SELECT event_id, event_type, message, timestamp, details
                 FROM sysmon_events 
                 WHERE computer_id = ? 
                 ORDER BY timestamp DESC LIMIT 50''', (computer_id,))

    detailed_processes = []

    for row in c.fetchall():
        event_id = row[0]
        event_type = row[1]
        message = row[2]
        timestamp = row[3]
        details_str = row[4]

        # Пробај да го парсираш details JSON
        try:
            details = json.loads(details_str) if details_str else {}
        except:
            details = {}

        # Екстрактирај информации од details
        process_info = {
            'event_id': event_id,
            'event_type': event_type,
            'timestamp': timestamp,
            'message': message,
            'process_name': details.get('ProcessName', 'Unknown'),
            'process_id': details.get('ProcessId', event_id),
            'command_line': details.get('CommandLine', ''),
            'parent_process': details.get('ParentProcessName', ''),
            'parent_pid': details.get('ParentProcessId', ''),
            'user': details.get('User', ''),
            'details': details
        }

        # Додади дополнителни полиња за различни типови на настани
        if event_id in [3, 22]:  # Network connection or DNS
            process_info['source_ip'] = details.get('SourceIp', '')
            process_info['dest_ip'] = details.get('DestinationIp', '')
            process_info['dest_port'] = details.get('DestinationPort', '')

        detailed_processes.append(process_info)

    conn.close()

    return jsonify({
        'computer_name': computer_name,
        'processes': detailed_processes,
        'count': len(detailed_processes)
    })
@app.route("/api/admin/login", methods=["POST"])
def admin_login():
    data = request.get_json(force=True) or {}
    key = (data.get("admin_key") or "").strip()
    if not ADMIN_KEY or key != ADMIN_KEY:
        return jsonify({"error": "Unauthorized"}), 401

    session_token = secrets.token_urlsafe(32)
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    c.execute("INSERT INTO admin_sessions(token, created_at) VALUES(?, datetime('now'))", (session_token,))
    conn.commit()
    conn.close()

    return jsonify({"ok": True, "session": session_token})


@app.route("/api/admin/environments", methods=["GET"])
def admin_list_envs():
    if not require_admin_session():
        return jsonify({"error": "Unauthorized"}), 401

    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    c.execute("SELECT name FROM environments ORDER BY name")
    envs = [r[0] for r in c.fetchall()]
    conn.close()

    return jsonify({"environments": envs})


@app.route("/api/admin/environments", methods=["POST"])
def admin_create_env():
    if not require_admin_session():
        return jsonify({"error": "Unauthorized"}), 401

    data = request.get_json(force=True) or {}
    name = (data.get("name") or "").strip()
    if not name:
        return jsonify({"error": "Missing env name"}), 400

    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    try:
        c.execute("INSERT INTO environments(name, created_at) VALUES(?, datetime('now'))", (name,))
        conn.commit()
    except Exception as e:
        conn.close()
        return jsonify({"error": str(e)}), 400
    conn.close()

    return jsonify({"ok": True, "name": name})


@app.route("/api/admin/tokens", methods=["POST"])
def admin_generate_token():
    if not require_admin_session():
        return jsonify({"error": "Unauthorized"}), 401

    data = request.get_json(force=True) or {}
    env = (data.get("env") or "").strip()
    if not env:
        return jsonify({"error": "Missing env"}), 400

    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    c.execute("SELECT 1 FROM environments WHERE name = ?", (env,))
    if not c.fetchone():
        conn.close()
        return jsonify({"error": "Environment not found"}), 404

    token = secrets.token_urlsafe(32)
    c.execute("""
        INSERT INTO env_tokens(env_name, token, created_at, expires_at)
        VALUES(?, ?, datetime('now'), datetime('now', '+15 minutes'))
    """, (env, token))

    conn.commit()
    conn.close()

    return jsonify({"ok": True, "env": env, "token": token})

if __name__ == '__main__':
    init_database()
    init_admin_tables()


    # Стартувај cleanup thread
    cleanup_thread = threading.Thread(target=cleanup_old_data, daemon=True)
    cleanup_thread.start()

    local_ip = get_local_ip()

    print("\n" + "=" * 70)
    print("🚀 ENHANCED LAN LOG SERVER со Sysmon")
    print("=" * 70)
    print(f"🌐 Server IP: {local_ip}:5555")
    print(f"📊 Dashboard: http://{local_ip}:5555/")
    print(f"📊 Alternative: http://localhost:5555/")
    print(f"🏥 Health check: http://{local_ip}:5555/ping")
    print("\n🛡️  Sysmon monitoring е активирано")
    print("✅ Кликни на секој компјутер за детални информации")
    print("✅ Сите Sysmon настани се прикажани во табла")
    print("✅ Кликни на секој настан за детали")
    print("=" * 70 + "\n")

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