import os
import time
import paramiko

# SSH-Zugangsdaten zum Windows Server
SSH_HOST = "159.195.77.90"       # IP des Windows-Servers
SSH_PORT = 22
SSH_USER = "IllTec_WBR"      # Windows SSH-Benutzer
SSH_KEY_PATH = "/root/.ssh/wbr_win_server"

# Pfade zu den Log-Dateien auf dem Windows-Server
SERVER_PATHS = {
    "d54b7791": "C:/WF2_WBR_EU1/save/log.txt",
    "6a131ded": "C:/WF2_WBR_EU2/save/log.txt",
    "eba78aaa": "C:/WF2_WBR_EU3/save/log.txt",
}

DEPENDENCY_DIR = "/var/www/smt/SMT_dependency"
SERVERS = ["d54b7791", "6a131ded", "eba78aaa"]
POLL_INTERVAL = 2.0
ANCHOR_LEN = 300

known_tail = {sid: "" for sid in SERVERS}
known_size = {sid: None for sid in SERVERS}

def get_sftp_client():
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(SSH_HOST, port=SSH_PORT, username=SSH_USER, key_filename=SSH_KEY_PATH, timeout=10)
    return ssh, ssh.open_sftp()

def check_size_changed(server_id, sftp):
    remote_path = SERVER_PATHS.get(server_id)
    if not remote_path:
        return True
    try:
        size = sftp.stat(remote_path).st_size
    except Exception as e:
        print(f"[!] {server_id}: SFTP Stat fehlgeschlagen: {e}")
        return True

    changed = (known_size[server_id] != size)
    known_size[server_id] = size
    return changed

def fetch_and_write(server_id, sftp):
    if not check_size_changed(server_id, sftp):
        return

    remote_path = SERVER_PATHS.get(server_id)
    target = os.path.join(DEPENDENCY_DIR, f"central_live_log_{server_id}.txt")

    try:
        with sftp.open(remote_path, "r") as remote_file:
            full_content = remote_file.read().decode("utf-8", errors="ignore")
    except Exception as e:
        print(f"[!] {server_id}: SFTP Lesen fehlgeschlagen: {e}")
        return

    if not full_content:
        return

    anchor = known_tail[server_id]

    if anchor:
        pos = full_content.find(anchor)
        if pos != -1:
            new_part = full_content[pos + len(anchor):]
            if not new_part:
                return
            try:
                with open(target, "a", encoding="utf-8", errors="ignore") as f:
                    f.write(new_part)
            except OSError as e:
                print(f"[!] {server_id}: Anhaengen fehlgeschlagen: {e}")
                return
            known_tail[server_id] = full_content[-ANCHOR_LEN:]
            return

    tmp = target + ".tmp"
    try:
        with open(tmp, "w", encoding="utf-8", errors="ignore") as f:
            f.write(full_content)
        os.replace(tmp, target)
        known_tail[server_id] = full_content[-ANCHOR_LEN:]
    except OSError as e:
        print(f"[!] {server_id}: Neuschreiben fehlgeschlagen: {e}")

def main():
    if not os.path.isdir(DEPENDENCY_DIR):
        raise SystemExit(f"FEHLER: {DEPENDENCY_DIR} existiert nicht.")

    for sid in SERVERS:
        target = os.path.join(DEPENDENCY_DIR, f"central_live_log_{sid}.txt")
        if os.path.exists(target):
            try:
                with open(target, "r", encoding="utf-8", errors="ignore") as f:
                    f.seek(max(0, os.path.getsize(target) - ANCHOR_LEN * 4))
                    known_tail[sid] = f.read()[-ANCHOR_LEN:]
            except OSError:
                pass

    print("=== Shadow-Log-Writer V4 (SSH/SFTP Edition) gestartet ===")

    gap = POLL_INTERVAL / len(SERVERS)
    ssh, sftp = None, None
    while True:
        round_start = time.time()
        try:
            if sftp is None:
                ssh, sftp = get_sftp_client()
            for sid in SERVERS:
                fetch_and_write(sid, sftp)
                time.sleep(gap)
        except Exception as e:
            print(f"[!] SSH Verbindungsfehler: {e}, verbinde neu...")
            if sftp: sftp.close()
            if ssh: ssh.close()
            ssh, sftp = None, None
            time.sleep(2)

        elapsed = time.time() - round_start
        if elapsed < POLL_INTERVAL:
            time.sleep(0)

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        pass
