# Display contract shared with the ESPHome calendar page: compact German labels,
# a bounded number of events, and strings sized for the e-paper layout.
CALENDAR_NAMES = {
    "calendar.tkrz_kalender": "Arbeit",
    "calendar.privat": "Privat",
}
DAY_NAMES = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"]
MAX_ENTRIES = 8
# Reserve the right side of each row for start and end times.
MAX_TITLE_LENGTH = 22
MAX_META_LENGTH = 35


# Keep variable event text within the fixed-width e-paper agenda columns.
def shorten(value, maximum):
    value = (value or "").strip()
    if len(value) <= maximum:
        return value
    return value[: maximum - 3].rstrip() + "..."


# Convert one Home Assistant calendar event into the small JSON shape consumed
# by ESPHome, separating all-day, start-time, end-time, and metadata display data.
def compact_event(event, calendar_name):
    start = event.get("start", "")
    all_day = "T" not in start
    end = event.get("end", "")
    time = "ganzt." if all_day else start[11:16]
    end_time = "" if all_day or "T" not in end else end[11:16]

    location = (event.get("location") or "").split("\n")[0].strip()
    meta = calendar_name
    if location:
        meta += " / " + location

    return {
        "title": shorten(event.get("summary", "Ohne Titel"), MAX_TITLE_LENGTH),
        "time": time,
        "end": end_time,
        "meta": shorten(meta, MAX_META_LENGTH),
        "all_day": int(all_day),
    }


# Read the calendar.get_events response supplied by the calling template sensor
# and collect events under the date on which they should appear in the agenda.
calendar_data = data.get("calendar", {})
today = str(data.get("now", ""))[:10]
events_by_date = {}

for calendar_id, calendar in calendar_data.items():
    calendar_name = CALENDAR_NAMES.get(calendar_id, calendar_id.split(".")[-1].capitalize())
    for event in calendar.get("events", []):
        start = event.get("start", "")
        end = event.get("end", "")
        event_date = start[:10]
        end_date = end[:10]

        # Ignore malformed or already finished entries. All-day event end dates
        # are exclusive in Home Assistant; timed events ending today may still be
        # active. Multi-day entries remain visible on today's date rail.
        all_day = "T" not in start
        if not event_date or (all_day and end_date <= today) or (not all_day and end_date < today):
            continue
        if event_date < today:
            event_date = today

        events_by_date.setdefault(event_date, []).append(
            compact_event(event, calendar_name)
        )

# Sort day groups and events, put all-day entries first, and cap the payload so
# deserializing it stays safe on the ESP32 without PSRAM.
entries = []
entry_count = 0
for date in sorted(events_by_date):
    if entry_count >= MAX_ENTRIES:
        break

    events = events_by_date[date]
    events.sort(key=lambda item: (item["all_day"] == 0, item["time"]))
    remaining = MAX_ENTRIES - entry_count
    events = events[:remaining]
    entry_count += len(events)

    parsed_date = dt_util.parse_datetime(date)
    entries.append(
        {
            "day": parsed_date.day,
            "weekday": DAY_NAMES[parsed_date.weekday()],
            "today": int(date == today),
            "events": events,
        }
    )

# Return only the normalized agenda payload to the Home Assistant template sensor.
output["entries"] = entries
