import paramiko
import re
import smtplib
import threading
import unicodedata
from email.mime.text import MIMEText
from flask import Flask, render_template, Response, stream_with_context

# Flask aplikace
app = Flask(__name__)

# Inicializace proměnných
keywords = ["loop", "lbd", "llbd"]
event_counts = {keyword: 0 for keyword in keywords}
threshold = 10

# Nastavení pro SSH připojení
ssh_host = "syslog.starnet.cz"
ssh_port = 22009
ssh_user = "bosman"
ssh_key_file = "/home/st31200/id_rsa_nat"

# Nastavení pro e-mailové upozornění
email_sender = "bosman@mbos.cz"
email_recipient = "bosman@mbos.cz"
smtp_server = "mail.mbos.cz"
smtp_port = 25
smtp_user = "unms"
smtp_password = "UnmS102030!"

# Funkce pro odesílání e-mailu
def send_email_in_thread(keyword, count, log_line):
    def send_email():
        try:
            subject = f"PRAVDĚPODOBNĚ SMYČKA!!!"
            body = (
                f"PRAVDĚPODOBNĚ SMYČKA, klíčové slovo '{keyword}' bylo zaznamenáno {count} krát v syslogu.\n\n"
                f"Detail:\n{log_line}"
            )
            msg = MIMEText(body, _charset="utf-8")
            msg["Subject"] = subject
            msg["From"] = email_sender
            msg["To"] = email_recipient

            with smtplib.SMTP(smtp_server, smtp_port) as server:
                server.starttls()
                server.login(smtp_user, smtp_password)
                server.sendmail(email_sender, email_recipient, msg.as_string())
            print(f"E-mail odeslán na {email_recipient}: {subject}")
        except Exception as e:
            print(f"Chyba při odesílání e-mailu: {e}")

    threading.Thread(target=send_email).start()

# Funkce pro odstranění diakritiky
def remove_diacritics(text):
    nfkd_form = unicodedata.normalize('NFKD', text)
    return ''.join([c for c in nfkd_form if not unicodedata.combining(c)])

# Funkce pro analýzu řádku (s odstraněním diakritiky)
def analyze_event(line):
    global event_counts
    print(f"Analyzing line: {line}")
    line = remove_diacritics(line)

    for keyword in keywords:
        if re.search(keyword, line, re.IGNORECASE):
            print(f"Keyword '{keyword}' found in line: {line}")
            event_counts[keyword] += 1
            if event_counts[keyword] == threshold:
                print(f"Threshold reached for keyword: {keyword}. Sending email...")
                send_email_in_thread(keyword, event_counts[keyword], line)
                event_counts[keyword] = 0


# Funkce pro streamování syslogu
def stream_syslog():
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
        client.connect(hostname=ssh_host, port=ssh_port, username=ssh_user, key_filename=ssh_key_file)
        command = "sudo tail -f /var/log/syslog"
        stdin, stdout, stderr = client.exec_command(command)

        for raw_line in iter(stdout.readline, ""):  # Surový výstup
            try:
                # Bezpečné dekódování
                if isinstance(raw_line, bytes):
                    line = raw_line.decode("utf-8", errors="replace")  # Používáme replace pro neplatné znaky
                else:
                    line = raw_line.strip()

                line = line.strip()  # Odstranění bílých znaků

            except Exception as e:
                # Detailní log chyby
                print(f"Chyba při dekódování řádku: {repr(raw_line)} -> {e}")
                yield f"data: Chybný řádek: {repr(raw_line)}\n\n"
                continue

            try:
                if any(re.search(keyword, line, re.IGNORECASE) for keyword in keywords):
                    analyze_event(line)  # Analýza klíčových slov
                    yield f"data: {line}\n\n"  # SSE streamování dat
            except Exception as e:
                print(f"Chyba při analýze nebo zpracování řádku: {line} -> {e}")
                yield f"data: Chybný obsah: {repr(line)}\n\n"

    except Exception as e:
        # Obecná chyba během připojení
        print(f"Chyba při připojení: {e}")
        yield f"data: Chyba při připojení: {e}\n\n"
    finally:
        client.close()


# Route pro HTML stránku
@app.route("/")
def index():
    return render_template("index.html")

# Route pro streamování
@app.route("/stream")
def stream():
    return Response(stream_with_context(stream_syslog()), content_type="text/event-stream")
