import socket
import sys
import time
import xml.etree.ElementTree as ET
from datetime import datetime
from collections import defaultdict

# ========================= CONFIG =========================
HOST = '192.168.16.100'
PORT = 6771

xml_request = '''<?xml version="1.0" encoding="utf-8"?>
<package>
  <header>
    <name>LockerELSNETInfo</name>
    <version>1.0</version>
  </header>
  <parameters>
    <item>00001</item>
  </parameters>
  <userdata>xyz</userdata>
</package>'''

frame = chr(2) + xml_request + chr(3)

# ======================= VERBINDUNG =======================
print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Verbinde mit Metra {HOST}:{PORT} ...")

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
sock.settimeout(15)

try:
    sock.connect((HOST, PORT))
    print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Erfolgreich verbunden.")
except Exception as e:
    print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Verbindungsfehler: {e}")
    sys.exit(1)

try:
    print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Sende Anfrage...")
    sock.sendall(frame.encode('utf-8'))
except Exception as e:
    print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Sendefehler: {e}")
    sock.close()
    sys.exit(1)

# ======================= ANTWORT EMPFANGEN =======================
print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Warte auf Antwort...")
response = b''
try:
    while True:
        data = sock.recv(8192)
        if not data:
            break
        response += data
except socket.timeout:
    print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Timeout beim Empfangen.")
except Exception as e:
    print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Empfangsfehler: {e}")

sock.close()

# ======================= ANTWORT VERARBEITEN =======================
response_str = response.decode('utf-8', errors='ignore')

if response_str.startswith(chr(2)):
    response_str = response_str[1:]
if response_str.endswith(chr(3)):
    response_str = response_str[:-1]

# ======================= XML PARSEN & GRUPPIEREN =======================
try:
    root = ET.fromstring(response_str)
except Exception as e:
    print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] XML-Parsing-Fehler: {e}")
    sys.exit(1)

print(f"\n{'='*90}")
print("   METRA SCHRANK-RESERVIERUNGEN – MEHRFACHBUCHUNGEN ERKANNT")
print(f"{'='*90}\n")

# Gruppiere Buchungen pro Schrank
lockers = defaultdict(list)

for locker in root.findall(".//locker"):
    number = locker.find("number").text if locker.find("number") is not None else "???"
    name   = locker.find("name").text if locker.find("name") is not None else "-"
    
    datetimefrom = locker.find("datetimefrom").text if locker.find("datetimefrom") is not None else None
    datetimeto   = locker.find("datetimeto").text if locker.find("datetimeto") is not None else None
    cards = [card.text for card in locker.findall(".//card")]

    if datetimefrom and datetimeto:
        try:
            from_dt = datetime.fromisoformat(datetimefrom.replace("T", " "))
            to_dt   = datetime.fromisoformat(datetimeto.replace("T", " "))
            period = f"{from_dt.strftime('%d.%m.%Y %H:%M')} – {to_dt.strftime('%d.%m.%Y %H:%M')}"
        except:
            period = f"{datetimefrom} – {datetimeto}"
    else:
        period = "Keine Reservierung"

    lockers[number].append({
        "name": name,
        "period": period,
        "cards": cards
    })

# ======================= AUSGABE =======================
total_bookings = 0

for number in sorted(lockers.keys(), key=lambda x: int(x) if x.isdigit() else 9999):
    bookings = lockers[number]
    total_bookings += len(bookings)

    if len(bookings) > 1:
        print(f"Schrank Nr.: {number:4} | {len(bookings)} Buchungen gefunden")
    else:
        print(f"Schrank Nr.: {number:4} | 1 Buchung")

    for i, b in enumerate(bookings, 1):
        print(f"   {i}. {b['name']}")
        print(f"      Zeitraum : {b['period']}")
        if b['cards']:
            print(f"      Dummy-ID : {b['cards'][0]}")   # meistens nur eine pro Buchung
        print()

print(f"\nZusammenfassung:")
print(f"   {len(lockers)} verschiedene Schränke")
print(f"   {total_bookings} Buchungen insgesamt")
print(f"   davon mit Mehrfachbuchungen: {sum(1 for b in lockers.values() if len(b) > 1)} Schränke\n")
