#!/usr/bin/env python3
import serial
import subprocess
import time
import re
from datetime import datetime

MODEM_PORT = "/dev/ttyUSB2"
MODEM_BAUD = 115200
MAX_ZEICHEN = 200

def drucken(inhalt):
    with open("/tmp/eingang.txt", "w", encoding="utf-8") as f:
        f.write(inhalt)
    subprocess.run(["lp", "-d", "NEC-P20", "/tmp/eingang.txt"])

def at_befehl(ser, befehl, wartezeit=1):
    ser.write((befehl + "\r\n").encode())
    time.sleep(wartezeit)
    antwort = ser.read(ser.in_waiting).decode("utf-8", errors="ignore")
    print(f">> {befehl}")
    print(f"<< {antwort.strip()}")
    return antwort

def sanitize(text):
    text = text[:MAX_ZEICHEN]
    text = re.sub(r'[^\x20-\x7E\xC0-\xFF\n]', '', text)
    text = text.replace('\x1b', '')
    text = text.replace('\x0c', '')
    text = text.replace('\x08', '')
    text = re.sub(r'\n{3,}', '\n\n', text)
    text = "\n".join(z for z in text.splitlines()
                     if z.strip() not in ["AT", "OK", "AT+CMGF=1"])
    return text.strip()

def alle_nachrichten_verarbeiten(ser):
    antwort = at_befehl(ser, "AT+CMGL=\"ALL\"", wartezeit=2)
    zeilen = antwort.strip().splitlines()

    if "+CMGL:" not in antwort:
        return

    index = None
    nummer = "Unbekannt"
    text_zeilen = []

    for zeile in zeilen:
        if "+CMGL:" in zeile:
            if index is not None and text_zeilen:
                text = "\n".join(text_zeilen).strip()
                if text:
                    sms_verarbeiten(nummer, text)
                at_befehl(ser, f"AT+CMGD={index}")
                text_zeilen = []
            try:
                teile = zeile.split(",")
                index = int(teile[0].replace("+CMGL:", "").strip())
                nummer = teile[2].replace('"', '').strip()
            except:
                index = None
                nummer = "Unbekannt"
        elif zeile in ["OK", ""]:
            continue
        elif index is not None:
            text_zeilen.append(zeile)

    if index is not None and text_zeilen:
        text = "\n".join(text_zeilen).strip()
        if text:
            sms_verarbeiten(nummer, text)
        at_befehl(ser, f"AT+CMGD={index}")

def sms_verarbeiten(nummer, text):
    gekuerzt = len(text) > MAX_ZEICHEN
    text = sanitize(text)
    zeitstempel = datetime.now().strftime("%d.%m.%Y %H:%M")
    inhalt = (
        f"SMS - {zeitstempel}\n"
        f"--------------------------------\n"
        f"{text}\n"
    )
    if gekuerzt:
        inhalt += f"[Gekuerzt auf {MAX_ZEICHEN} Zeichen]\n"
    inhalt += f"\n\n\n"
    print(f"SMS von {nummer}: {text[:50]}")
    drucken(inhalt)

def main():
    print("Starte SMS-Drucker...")
    ser = serial.Serial(MODEM_PORT, MODEM_BAUD, timeout=1)
    time.sleep(2)

    at_befehl(ser, "AT")
    at_befehl(ser, "AT+CMGF=1")
    at_befehl(ser, "AT+CPMS=\"ME\",\"ME\",\"ME\"")
    at_befehl(ser, "AT+CNMI=2,1,0,0,0")

    alle_nachrichten_verarbeiten(ser)

    netz = at_befehl(ser, "AT+COPS?")
    print(f"Netz: {netz.strip()}")
    print("Warte auf Nachrichten...")

    while True:
        try:
            zeile = ser.readline().decode("utf-8", errors="ignore").strip()
            if not zeile:
                continue

            if zeile not in ["AT", "OK", "AT+CMGF=1"]:
                print(f"[MODEM] {zeile}")

            if "SMS FULL" in zeile or "SMSFULL" in zeile:
                print("[SMS] Speicher voll - leere...")
                at_befehl(ser, "AT+CMGD=1,4", wartezeit=3)

            if "+CMTI:" in zeile:
                print("Neue Nachricht erkannt!")
                time.sleep(2)
                alle_nachrichten_verarbeiten(ser)

        except KeyboardInterrupt:
            print("\nBeende...")
            ser.close()
            break
        except Exception as e:
            print(f"Fehler: {e}")
            time.sleep(1)

if __name__ == "__main__":
    main()