#!/usr/bin/env python3
"""
POPRAVEN SERVER - So azhuriranje na postoechki zapisi i detalni informacii
"""

from flask import Flask, request, jsonify
import json
import sqlite3
from datetime import datetime, timedelta
import os
import socket

app = Flask(__name__)

DB_FILE = "lan_logs_fixed.db"
LOG_DIR = "received_data_fixed"


def init_database():
    """Kreiraј pobolshana baza"""
    os.makedirs(LOG_DIR, exist_ok=True)

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

    # Tabela za kompjuteri (SEGA so edinstveno ime)
    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)''')

    # Tabela za history (site podatoci)
    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,
                  process_count INTEGER,
                  timestamp TIMESTAMP,
                  FOREIGN KEY(computer_id) REFERENCES computers(id))''')

    # Tabela za procesi (so vremenska oznaka)
    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,
                  timestamp TIMESTAMP,
                  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

        info = data['info']
        computer_name = info['computer_name']
        timestamp = datetime.now()

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

        # Proveri dali kompjuterot veќe postoi
        c.execute("SELECT id FROM computers WHERE name = ?", (computer_name,))
        result = c.fetchone()

        if result:
            # Kompjuterot postoi - azhuriraј go
            computer_id = result[0]
            c.execute('''UPDATE computers 
                        SET user = ?, ip = ?, os = ?, last_seen = ?
                        WHERE id = ?''',
                      (info['user'], info['ip_address'], info['os'],
                       timestamp.isoformat(), computer_id))
        else:
            # Nov kompjuter - dodadi go
            c.execute('''INSERT INTO computers 
                        (name, user, ip, os, first_seen, last_seen) 
                        VALUES (?, ?, ?, ?, ?, ?)''',
                      (computer_name, info['user'], info['ip_address'],
                       info['os'], timestamp.isoformat(), timestamp.isoformat()))
            computer_id = c.lastrowid

        # Dodadi vo history
        c.execute('''INSERT INTO computer_history 
                    (computer_id, cpu_usage, ram_usage, disk_usage, 
                     process_count, timestamp)
                    VALUES (?, ?, ?, ?, ?, ?)''',
                  (computer_id, info['cpu_usage'], info['ram_usage'],
                   info['disk_usage'], len(data.get('processes', [])),
                   info['timestamp']))

        # Zachuvaj gi procesite
        for proc in data.get('processes', []):
            c.execute('''INSERT INTO computer_processes 
                        (computer_id, pid, name, username, timestamp)
                        VALUES (?, ?, ?, ?, ?)''',
                      (computer_id, proc.get('pid'), proc.get('name'),
                       proc.get('user'), info['timestamp']))

        conn.commit()
        conn.close()

        # Zachuvaj vo JSON
        save_json_file(data)

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

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

    except Exception as e:
        print(f"[-] Greshka: {e}")
        return jsonify({"error": str(e)}), 500


def save_json_file(data):
    """Zachuvaj vo JSON"""
    info = data['info']
    computer_name = info['computer_name']
    date_str = datetime.now().strftime("%Y%m%d")

    # Kreiraј folder za kompjuterot
    computer_dir = os.path.join(LOG_DIR, computer_name)
    os.makedirs(computer_dir, exist_ok=True)

    # Fajl za denes
    filepath = os.path.join(computer_dir, f"{date_str}.json")

    # Dodadi vo postoechki fajl ili kreiraј nov
    if os.path.exists(filepath):
        with open(filepath, 'r', encoding='utf-8') as f:
            existing_data = json.load(f)
    else:
        existing_data = []

    # Dodadi nov zapis
    existing_data.append({
        "timestamp": info['timestamp'],
        "data": info,
        "processes_count": len(data.get('processes', []))
    })

    # Zachuvaj
    with open(filepath, 'w', encoding='utf-8') as f:
        json.dump(existing_data, f, indent=2, ensure_ascii=False)


@app.route('/')
def dashboard():
    """Glaven dashboard so site kompjuteri"""
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    # Zemaj gi site kompjuteri
    c.execute('''SELECT name, user, ip, os, first_seen, last_seen 
                 FROM computers 
                 ORDER BY last_seen DESC''')

    computers = []
    for row in c.fetchall():
        # Presmetaj kolku zapisi ima vo poslednite 24 chasa
        c.execute('''SELECT COUNT(*) FROM computer_history 
                     WHERE computer_id = (SELECT id FROM computers WHERE name = ?)
                     AND timestamp > datetime('now', '-24 hours')''',
                  (row[0],))
        recent_logs = c.fetchone()[0]

        # Zemaj gi poslednite 5 zapisi za 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''',
                  (row[0],))
        recent_metrics = c.fetchall()

        # Presmetaj prosek
        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

        computers.append({
            'name': row[0],
            'user': row[1],
            'ip': row[2],
            'os': row[3],
            'first_seen': row[4],
            'last_seen': row[5],
            'recent_logs': recent_logs,
            'avg_cpu': round(avg_cpu, 1),
            'avg_ram': round(avg_ram, 1),
            'status': 'online' if (datetime.now() - datetime.fromisoformat(row[5])).seconds < 60 else 'offline'
        })

    conn.close()

    # Generiraј HTML
    html = '''
    <!DOCTYPE html>
    <html>
    <head>
        <title>LAN Log Server - Fixed Dashboard</title>
        <meta charset="utf-8">
        <style>
            body { font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }
            .header { background: #2c3e50; color: white; padding: 20px; border-radius: 10px; margin-bottom: 20px; }
            .computers-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; }
            .computer-card { background: white; padding: 20px; border-radius: 10px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
            .computer-card:hover { box-shadow: 0 4px 10px rgba(0,0,0,0.2); cursor: pointer; }
            .computer-name { font-size: 18px; font-weight: bold; margin-bottom: 10px; color: #2c3e50; }
            .computer-info { color: #666; margin: 5px 0; }
            .online { color: green; }
            .offline { color: gray; }
            .stats { display: flex; justify-content: space-between; margin-top: 15px; padding-top: 15px; border-top: 1px solid #eee; }
            .stat { text-align: center; }
            .stat-value { font-size: 20px; font-weight: bold; }
            .stat-label { font-size: 12px; color: #888; }
            .details-panel { display: none; position: fixed; top: 0; right: 0; width: 600px; height: 100%; background: white; box-shadow: -2px 0 10px rgba(0,0,0,0.1); padding: 20px; overflow-y: auto; z-index: 1000; }
            .close-btn { float: right; cursor: pointer; font-size: 24px; }
            .tab { display: none; }
            .tab.active { display: block; }
            .tab-buttons { display: flex; border-bottom: 1px solid #ddd; margin-bottom: 20px; }
            .tab-button { padding: 10px 20px; cursor: pointer; border: none; background: none; }
            .tab-button.active { border-bottom: 3px solid #2c3e50; font-weight: bold; }
            table { width: 100%; border-collapse: collapse; margin-top: 10px; }
            th, td { padding: 8px; text-align: left; border-bottom: 1px solid #ddd; }
            th { background: #f5f5f5; }
        </style>
        <script>
            function showComputerDetails(computerName) {
                fetch(`/api/computer/${encodeURIComponent(computerName)}`)
                    .then(response => response.json())
                    .then(data => {
                        document.getElementById('details-panel').style.display = 'block';
                        populateDetails(data);
                    });
            }

            function populateDetails(data) {
                // Popolni osnovni informacii
                document.getElementById('details-title').textContent = data.computer.name;
                document.getElementById('details-user').textContent = data.computer.user;
                document.getElementById('details-ip').textContent = data.computer.ip;
                document.getElementById('details-os').textContent = data.computer.os;
                document.getElementById('details-first-seen').textContent = new Date(data.computer.first_seen).toLocaleString();
                document.getElementById('details-last-seen').textContent = new Date(data.computer.last_seen).toLocaleString();
                document.getElementById('details-total-logs').textContent = data.computer.total_logs;

                // Popolni tabela za history
                let historyTable = document.getElementById('history-table');
                historyTable.innerHTML = '';
                data.history.forEach(log => {
                    let row = historyTable.insertRow();
                    row.innerHTML = `
                        <td>${new Date(log.timestamp).toLocaleString()}</td>
                        <td>${log.cpu_usage}%</td>
                        <td>${log.ram_usage}%</td>
                        <td>${log.disk_usage}%</td>
                        <td>${log.process_count}</td>
                    `;
                });

                // Popolni tabela za procesi (posledni)
                let processTable = document.getElementById('process-table');
                processTable.innerHTML = '';
                data.recent_processes.forEach(proc => {
                    let row = processTable.insertRow();
                    row.innerHTML = `
                        <td>${proc.pid}</td>
                        <td>${proc.name}</td>
                        <td>${proc.username}</td>
                        <td>${new Date(proc.timestamp).toLocaleTimeString()}</td>
                    `;
                });

                // Popolni chart (simple)
                updateChart(data.history);
            }

            function updateChart(history) {
                const ctx = document.getElementById('performance-chart').getContext('2d');

                // Grupiraј po chas (za podobar prikaz)
                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.myChart) {
                    window.myChart.destroy();
                }

                window.myChart = 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,
                        scales: {
                            y: {
                                beginAtZero: true,
                                max: 100
                            }
                        }
                    }
                });
            }

            function closeDetails() {
                document.getElementById('details-panel').style.display = 'none';
            }

            function switchTab(tabName) {
                // Deaktiviraј site tabovi
                document.querySelectorAll('.tab').forEach(tab => {
                    tab.classList.remove('active');
                });
                document.querySelectorAll('.tab-button').forEach(btn => {
                    btn.classList.remove('active');
                });

                // Aktiviraј izbraniot tab
                document.getElementById(tabName + '-tab').classList.add('active');
                document.querySelector(`[onclick="switchTab('${tabName}')"]`).classList.add('active');
            }

            // Aktiviraј prv tab na start
            document.addEventListener('DOMContentLoaded', function() {
                switchTab('history');
            });
        </script>
    </head>
    <body>
        <div class="header">
            <h1>🖥️ LAN Log Server - Fixed Dashboard</h1>
            <p>Connected Computers: <span id="computer-count">''' + str(len(computers)) + '''</span></p>
            <p>Server IP: ''' + socket.gethostbyname(socket.gethostname()) + ''':5555</p>
        </div>

        <h2>Connected Computers</h2>
        <div class="computers-grid">
    '''

    for comp in computers:
        html += f'''
            <div class="computer-card" onclick="showComputerDetails('{comp['name']}')">
                <div class="computer-name">{comp['name']}</div>
                <div class="computer-info">👤 User: {comp['user']}</div>
                <div class="computer-info">🌐 IP: {comp['ip']}</div>
                <div class="computer-info">💻 OS: {comp['os']}</div>
                <div class="computer-info">⏰ Last seen: {datetime.fromisoformat(comp['last_seen']).strftime('%H:%M:%S')}</div>
                <div class="computer-info {'online' if comp['status'] == 'online' else 'offline'}">
                    ● {comp['status'].upper()}
                </div>
                <div class="stats">
                    <div class="stat">
                        <div class="stat-value">{comp['avg_cpu']}%</div>
                        <div class="stat-label">CPU</div>
                    </div>
                    <div class="stat">
                        <div class="stat-value">{comp['avg_ram']}%</div>
                        <div class="stat-label">RAM</div>
                    </div>
                    <div class="stat">
                        <div class="stat-value">{comp['recent_logs']}</div>
                        <div class="stat-label">Logs (24h)</div>
                    </div>
                </div>
            </div>
        '''

    html += '''
        </div>

        <!-- Details Panel -->
        <div id="details-panel" class="details-panel">
            <div class="close-btn" onclick="closeDetails()">×</div>
            <h2 id="details-title">Computer Details</h2>

            <div class="computer-info">
                <p><strong>👤 User:</strong> <span id="details-user"></span></p>
                <p><strong>🌐 IP:</strong> <span id="details-ip"></span></p>
                <p><strong>💻 OS:</strong> <span id="details-os"></span></p>
                <p><strong>📅 First Seen:</strong> <span id="details-first-seen"></span></p>
                <p><strong>⏰ Last Seen:</strong> <span id="details-last-seen"></span></p>
                <p><strong>📊 Total Logs:</strong> <span id="details-total-logs"></span></p>
            </div>

            <div class="tab-buttons">
                <button class="tab-button active" onclick="switchTab('history')">History</button>
                <button class="tab-button" onclick="switchTab('processes')">Processes</button>
                <button class="tab-button" onclick="switchTab('charts')">Charts</button>
            </div>

            <div id="history-tab" class="tab active">
                <h3>Performance History</h3>
                <table>
                    <thead>
                        <tr>
                            <th>Time</th>
                            <th>CPU %</th>
                            <th>RAM %</th>
                            <th>Disk %</th>
                            <th>Processes</th>
                        </tr>
                    </thead>
                    <tbody id="history-table"></tbody>
                </table>
            </div>

            <div id="processes-tab" class="tab">
                <h3>Recent Processes</h3>
                <table>
                    <thead>
                        <tr>
                            <th>PID</th>
                            <th>Name</th>
                            <th>User</th>
                            <th>Time</th>
                        </tr>
                    </thead>
                    <tbody id="process-table"></tbody>
                </table>
            </div>

            <div id="charts-tab" class="tab">
                <h3>Performance Chart</h3>
                <canvas id="performance-chart" width="400" height="200"></canvas>
            </div>
        </div>

        <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
        <script>
            // Auto-refresh na dashboard sekoj 30 sekundi
            setInterval(() => {
                location.reload();
            }, 30000);
        </script>
    </body>
    </html>
    '''

    return html


@app.route('/api/computer/<computer_name>')
def get_computer_details(computer_name):
    """Dobi site detalni informacii za eden kompjuter"""
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    # Osnovni informacii
    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]

    # Broj na site zapisi
    c.execute('SELECT COUNT(*) FROM computer_history WHERE computer_id = ?', (computer_id,))
    total_logs = c.fetchone()[0]

    # Site history zapisi
    c.execute('''SELECT cpu_usage, ram_usage, disk_usage, process_count, 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],
            'process_count': row[3],
            'timestamp': row[4]
        })

    # Posledni procesi
    c.execute('''SELECT pid, name, username, timestamp 
                 FROM computer_processes 
                 WHERE computer_id = ? 
                 ORDER BY timestamp DESC LIMIT 50''', (computer_id,))
    recent_processes = []
    for row in c.fetchall():
        recent_processes.append({
            'pid': row[0],
            'name': row[1],
            'username': row[2],
            'timestamp': row[3]
        })

    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,
        'recent_processes': recent_processes
    })


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


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"


if __name__ == '__main__':
    init_database()

    local_ip = get_local_ip()

    print("\n" + "=" * 70)
    print("🚀 FIXED LAN LOG SERVER")
    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📡 Data will be grouped by computer name")
    print("✅ Each computer appears only once")
    print("✅ Click on computer to see all collected data")
    print("=" * 70 + "\n")

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