/* AZIS 6.0 · Kalender-Tab ================================================
   Dienstliche Terminverwaltung — Übungen, Lehrgänge, Urlaub, Sonstiges.
   Speicherung liegt im verschlüsselten Pool (state.events) via app.js CRUD.
   Dieser Screen ist reines UI + Bridge-Aufrufe.

   6.8 · Komplett-Redesign des Kalender-Tabs:
   - Monats-Grid mit fester Zellenhöhe → nichts springt beim Monatswechsel
     oder Tag-Wechsel. Kategorie-Punkte statt abgeschnittener Text-Chips.
   - Ein einziger Tages-Detailblock (fixe Mindesthöhe) statt dreifacher
     Wiederholung (Chip + Detail + „Alle Termine"-Liste).
   - Aufgeräumter EventDialog mit farbcodierter Kategorie-Auswahl.
   EventDialog wird von root.jsx auf .app-Ebene gerendert (überdeckt AppBar).
   ======================================================================= */

(function () {
  "use strict";

  const CATS = {
    uebung:     { label: "Übung",      short: "Üb", color: "var(--danger)"  },
    lehrgang:   { label: "Lehrgang",   short: "Lg", color: "var(--info)"    },
    urlaub:     { label: "Urlaub",     short: "Ur", color: "var(--warning)" },
    sonstiges:  { label: "Sonstiges",  short: "So", color: "var(--accent)"  },
  };
  const CAT_KEYS = ["uebung", "lehrgang", "urlaub", "sonstiges"];
  const ANZUG_PRESETS = ["Feldanzug", "Kampfanzug", "Dienstanzug", "gr. Dienstanzug", "Sportanzug", "Zivil"];
  const DOW_SHORT = ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"];
  const DOW_LONG = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"];

  function pad(n) { return String(n).padStart(2, "0"); }
  function isoOf(date) {
    return date.getFullYear() + "-" + pad(date.getMonth() + 1) + "-" + pad(date.getDate());
  }
  function dateFromIso(iso) {
    if (!iso || typeof iso !== "string") return null;
    const [y, m, d] = iso.split("-").map(Number);
    if (!y || !m || !d) return null;
    return new Date(y, m - 1, d);
  }
  function isoAddDays(iso, delta) {
    const d = dateFromIso(iso);
    if (!d) return iso;
    d.setDate(d.getDate() + delta);
    return isoOf(d);
  }
  function fmtDay(iso) {
    const d = dateFromIso(iso);
    if (!d) return iso;
    return DOW_SHORT[d.getDay()] + " " + pad(d.getDate()) + "." + pad(d.getMonth() + 1) + "." + d.getFullYear();
  }
  function monthName(m) {
    return (typeof AZIS !== "undefined" && Array.isArray(AZIS.MONTHS)) ? AZIS.MONTHS[m] : "";
  }
  // „Freitag, 4. Juli" — Kopfzeile des Detailblocks.
  function fmtDayLong(iso) {
    const d = dateFromIso(iso);
    if (!d) return iso;
    return DOW_LONG[d.getDay()] + ", " + d.getDate() + ". " + monthName(d.getMonth());
  }
  function fmtRange(fromIso, toIso, fromTime, toTime) {
    if (!fromIso) return "";
    const single = !toIso || toIso === fromIso;
    const label = single ? fmtDay(fromIso) : (fmtDay(fromIso) + " – " + fmtDay(toIso));
    if (fromTime || toTime) {
      const t = fromTime && toTime ? (fromTime + "–" + toTime)
              : fromTime ? ("ab " + fromTime)
              : ("bis " + toTime);
      return label + " · " + t;
    }
    return label;
  }
  // Nur die Zeit/Dauer-Zeile (Datum steht schon in der Detail-Kopfzeile).
  function fmtTime(fromTime, toTime) {
    if (fromTime && toTime) return fromTime + "–" + toTime + " Uhr";
    if (fromTime) return "ab " + fromTime + " Uhr";
    if (toTime) return "bis " + toTime + " Uhr";
    return "ganztägig";
  }

  const EMPTY_EVENT = {
    id: "", category: "uebung", title: "",
    fromDate: "", toDate: "", fromTime: "", toTime: "",
    anzug: "", ort: "", notes: "",
  };

  /* ---------- Kompakte Event-Karte (im Detailblock) ---------- */
  function EventCard({ evt, onOpen }) {
    const cat = CATS[evt.category] || CATS.sonstiges;
    return (
      <button className="kal__evt" onClick={() => onOpen(evt)}>
        <span className="kal__evt-stripe" style={{ background: cat.color }} />
        <div className="kal__evt-body">
          <div className="kal__evt-top">
            <span className="kal__evt-title">{evt.title}</span>
            <span className="kal__evt-cat" style={{ "--cat": cat.color }}>{cat.label}</span>
          </div>
          <div className="kal__evt-when">
            <Icon name="clock" />{fmtTime(evt.fromTime, evt.toTime)}
          </div>
          {(evt.anzug || evt.ort) && (
            <div className="kal__evt-meta">
              {evt.anzug ? (<span><Icon name="shirt" />{evt.anzug}</span>) : null}
              {evt.ort ? (<span><Icon name="map-pin" />{evt.ort}</span>) : null}
            </div>
          )}
        </div>
        <span className="kal__evt-chev" aria-hidden="true">›</span>
      </button>
    );
  }

  /* ---------- KalenderScreen ---------- */
  function KalenderScreen() {
    const now = new Date();
    const [viewY, setViewY] = useState(now.getFullYear());
    const [viewM, setViewM] = useState(now.getMonth());
    const [selectedIso, setSelectedIso] = useState(isoOf(now));
    // 6.7.27: Merge echte Kalender-Events + synthetische Vacation-Ranges
    // aus state.entries. Der User bucht Urlaub im Monat-Tab (DaySheet) —
    // hier zeigen wir das readonly mit.
    const loadAll = () => {
      const real = (window.AZIS?.getEvents?.() || []);
      const vac = (window.AZIS?.getVacationRanges?.() || []);
      return [...real, ...vac];
    };
    const [events, setEvents] = useState(loadAll);

    const refresh = React.useCallback(() => {
      try { setEvents(loadAll()); } catch { setEvents([]); }
    }, []);
    useEffect(() => {
      const onChange = () => refresh();
      window.addEventListener("kal:events-changed", onChange);
      // 6.7.27: DaySheet-Speicher triggert diesen Event via app.js.
      window.addEventListener("azis:entries-changed", onChange);
      return () => {
        window.removeEventListener("kal:events-changed", onChange);
        window.removeEventListener("azis:entries-changed", onChange);
      };
    }, [refresh]);

    const cycleMonth = (dir) => {
      const d = new Date(viewY, viewM + dir, 1);
      setViewY(d.getFullYear());
      setViewM(d.getMonth());
    };
    const jumpToday = () => {
      const t = new Date();
      setViewY(t.getFullYear());
      setViewM(t.getMonth());
      setSelectedIso(isoOf(t));
    };

    const todayIso = isoOf(new Date());

    const cells = React.useMemo(() => {
      const first = new Date(viewY, viewM, 1);
      const firstDow = (first.getDay() + 6) % 7; // Mo=0..So=6
      const start = new Date(viewY, viewM, 1 - firstDow);
      const out = [];
      for (let i = 0; i < 42; i++) {
        const d = new Date(start);
        d.setDate(start.getDate() + i);
        out.push({
          iso: isoOf(d), dom: d.getDate(),
          inMonth: d.getMonth() === viewM,
          weekend: d.getDay() === 0 || d.getDay() === 6,
        });
      }
      return out;
    }, [viewY, viewM]);

    // Map iso -> Events (mehrtägige Events auf alle Tage verteilt).
    const eventsPerDay = React.useMemo(() => {
      const map = new Map();
      events.forEach((e) => {
        if (!e.fromDate) return;
        let cur = e.fromDate;
        const to = e.toDate || e.fromDate;
        let guard = 0;
        while (cur <= to && guard < 400) {
          const arr = map.get(cur) || [];
          arr.push(e);
          map.set(cur, arr);
          cur = isoAddDays(cur, 1);
          guard++;
        }
      });
      return map;
    }, [events]);

    // Distinkte Kategorien pro Tag (für die Punkte) — geordnet nach CAT_KEYS.
    const catsForDay = (iso) => {
      const evts = eventsPerDay.get(iso) || [];
      const set = new Set(evts.map((e) => e.category));
      return CAT_KEYS.filter((k) => set.has(k));
    };

    const selectedEvents = React.useMemo(
      () => (eventsPerDay.get(selectedIso) || []).slice().sort((a, b) => (a.fromTime || "99").localeCompare(b.fromTime || "99")),
      [eventsPerDay, selectedIso]
    );

    const requestOpenEvent = (evt) => {
      // 6.7.27: Synthetische Vacation-Events sind readonly. Klick wechselt
      // zurück zum Monat-Tab und öffnet den Tag im DaySheet (dort kommt
      // der volle Editier-Flow).
      if (evt && evt._synthetic === "vacation") {
        try {
          const iso = evt.fromDate || selectedIso;
          window.dispatchEvent(new CustomEvent("azis:tour-go-tab", { detail: { tabKey: "monat" } }));
          setTimeout(() => {
            window.dispatchEvent(new CustomEvent("kal:open-day-in-monat", { detail: { iso } }));
          }, 60);
        } catch {}
        return;
      }
      try {
        window.dispatchEvent(new CustomEvent("kal:open-event", {
          detail: { event: evt, defaultIso: selectedIso },
        }));
      } catch {}
    };

    const selCount = selectedEvents.length;

    return (
      <div className="kal stagger" style={{ animationDelay: "40ms" }}>

        {/* Kopfleiste: Monat + Aktionen */}
        <div className="kal__bar">
          <div className="kal__nav">
            <button className="kal__navbtn" onClick={() => cycleMonth(-1)} aria-label="Vorheriger Monat">‹</button>
            <div className="kal__title">
              <span className="kal__title-month">{monthName(viewM)}</span>
              <span className="kal__title-year">{viewY}</span>
            </div>
            <button className="kal__navbtn" onClick={() => cycleMonth(1)} aria-label="Nächster Monat">›</button>
          </div>
          <button className="kal__today" onClick={jumpToday}>Heute</button>
        </div>

        {/* Monats-Grid */}
        <div className="kal__cal card">
          <div className="kal__dowrow">
            {["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"].map((d, i) => (
              <div key={d} className={"kal__dow" + (i >= 5 ? " kal__dow--we" : "")}>{d}</div>
            ))}
          </div>
          <div className="kal__days">
            {cells.map((c) => {
              const cats = catsForDay(c.iso);
              const isSel = c.iso === selectedIso;
              const isToday = c.iso === todayIso;
              return (
                <button key={c.iso}
                  className={"kal__day"
                    + (c.inMonth ? "" : " kal__day--out")
                    + (c.weekend ? " kal__day--we" : "")
                    + (isSel ? " kal__day--sel" : "")
                    + (isToday ? " kal__day--today" : "")}
                  onClick={() => setSelectedIso(c.iso)}
                  aria-label={c.dom + ". " + (cats.length ? cats.length + " Termine" : "keine Termine")}>
                  <span className="kal__day-num">{c.dom}</span>
                  <span className="kal__day-dots" aria-hidden="true">
                    {cats.map((k) => (
                      <span key={k} className="kal__dot" style={{ background: CATS[k].color }} />
                    ))}
                  </span>
                </button>
              );
            })}
          </div>
        </div>

        {/* Tages-Detailblock — fixe Mindesthöhe, springt nicht */}
        <div className="kal__panel card">
          <div className="kal__panel-head">
            <div className="kal__panel-headtext">
              <div className="kal__panel-date">{fmtDayLong(selectedIso)}</div>
              <div className="kal__panel-count">
                {selCount === 0 ? "Keine Termine"
                  : selCount === 1 ? "1 Termin"
                  : selCount + " Termine"}
              </div>
            </div>
            <button className="kal__panel-add" onClick={() => requestOpenEvent(null)}>
              <Icon name="plus" /><span>Neu</span>
            </button>
          </div>

          {selCount === 0 ? (
            <button className="kal__panel-empty" onClick={() => requestOpenEvent(null)}>
              <span className="kal__panel-empty-icon"><Icon name="plus" /></span>
              <span>Termin für diesen Tag anlegen</span>
            </button>
          ) : (
            <div className="kal__panel-list">
              {selectedEvents.map((e) => <EventCard key={e.id} evt={e} onOpen={requestOpenEvent} />)}
            </div>
          )}
        </div>

        {/* Legende */}
        <div className="kal__legend">
          {CAT_KEYS.map((k) => (
            <span key={k} className="kal__legend-item">
              <span className="kal__dot" style={{ background: CATS[k].color }} />{CATS[k].label}
            </span>
          ))}
        </div>
      </div>
    );
  }

  /* ---------- EventDialog ---------- */
  function EventDialog({ open, initial, onClose }) {
    const src = initial || EMPTY_EVENT;
    const [category, setCategory] = useState(src.category || "uebung");
    const [title, setTitle] = useState(src.title || "");
    const [fromDate, setFromDate] = useState(src.fromDate || "");
    const [toDate, setToDate] = useState(src.toDate || src.fromDate || "");
    const [fromTime, setFromTime] = useState(src.fromTime || "");
    const [toTime, setToTime] = useState(src.toTime || "");
    const isPreset = ANZUG_PRESETS.includes(src.anzug);
    const [anzugPreset, setAnzugPreset] = useState(isPreset ? src.anzug : (src.anzug ? "custom" : ""));
    const [anzugCustom, setAnzugCustom] = useState(!isPreset && src.anzug ? src.anzug : "");
    const [ort, setOrt] = useState(src.ort || "");
    const [notes, setNotes] = useState(src.notes || "");

    useEffect(() => {
      const s = initial || EMPTY_EVENT;
      setCategory(s.category || "uebung");
      setTitle(s.title || "");
      setFromDate(s.fromDate || "");
      setToDate(s.toDate || s.fromDate || "");
      setFromTime(s.fromTime || "");
      setToTime(s.toTime || "");
      const preset = ANZUG_PRESETS.includes(s.anzug);
      setAnzugPreset(preset ? s.anzug : (s.anzug ? "custom" : ""));
      setAnzugCustom(!preset && s.anzug ? s.anzug : "");
      setOrt(s.ort || "");
      setNotes(s.notes || "");
    }, [initial]);

    useEffect(() => {
      if (fromDate && toDate && toDate < fromDate) setToDate(fromDate);
    }, [fromDate, toDate]);

    const multiDay = fromDate && toDate && toDate !== fromDate;

    const handleSaveClick = () => {
      if (!title.trim()) { alert("Titel eingeben."); return; }
      if (!fromDate) { alert("Startdatum eingeben."); return; }
      const anzugFinal = anzugPreset === "custom" ? anzugCustom.trim() : (anzugPreset || "");
      const patch = {
        id: src.id || "", category, title: title.trim(),
        fromDate, toDate: toDate || fromDate, fromTime, toTime,
        anzug: anzugFinal, ort: ort.trim(), notes,
      };
      try {
        if (patch.id) window.AZIS.updateEvent(patch.id, patch);
        else window.AZIS.addEvent(patch);
        window.dispatchEvent(new CustomEvent("kal:events-changed"));
        onClose();
      } catch (e) { alert("Speichern fehlgeschlagen: " + (e?.message || e)); }
    };
    const handleDeleteClick = () => {
      if (!src.id) return;
      if (!confirm("Diesen Termin wirklich löschen?")) return;
      try {
        window.AZIS.deleteEvent(src.id);
        window.dispatchEvent(new CustomEvent("kal:events-changed"));
        onClose();
      } catch (e) { alert("Löschen fehlgeschlagen: " + (e?.message || e)); }
    };

    return (
      <div className={"subscreen kal-dialog" + (open ? " show" : "")}>
        <div className="sub-head">
          <button className="sub-head__back" onClick={onClose} aria-label="Zurück"><Icon name="arrow" /></button>
          <div>
            <div className="sub-head__title">{src.id ? "Termin bearbeiten" : "Neuer Termin"}</div>
            <div className="sub-head__sub">Erscheint im Kalender + als Marker im Monat</div>
          </div>
        </div>

        <div className="sub-body">
          {/* Kategorie — farbcodierte Karten */}
          <div className="kdlg__cats">
            {CAT_KEYS.map((k) => (
              <button key={k}
                className={"kdlg__cat" + (category === k ? " active" : "")}
                style={{ "--cat": CATS[k].color }}
                onClick={() => setCategory(k)}>
                <span className="kdlg__cat-dot" />
                <span className="kdlg__cat-label">{CATS[k].label}</span>
              </button>
            ))}
          </div>

          <div className="sfield">
            <label htmlFor="kalTitle">Titel</label>
            <input id="kalTitle" className="ainput" value={title}
              onChange={(e) => setTitle(e.target.value)}
              placeholder={category === "urlaub" ? "z. B. Jahresurlaub" : "z. B. Übung Wachtruppe"} />
          </div>

          <div className="section-title">Zeitraum</div>
          <div className="sfield-2">
            <div className="sfield">
              <label htmlFor="kalFrom">Von</label>
              <input id="kalFrom" className="ainput" type="date" value={fromDate}
                onChange={(e) => setFromDate(e.target.value)} />
            </div>
            <div className="sfield">
              <label htmlFor="kalTo">Bis</label>
              <input id="kalTo" className="ainput" type="date" value={toDate}
                onChange={(e) => setToDate(e.target.value)} />
            </div>
          </div>
          <div className="sfield-2">
            <div className="sfield">
              <label htmlFor="kalFromT">Uhrzeit von</label>
              <input id="kalFromT" className="ainput mono" type="time" step="60"
                value={fromTime} onChange={(e) => setFromTime(e.target.value)} />
            </div>
            <div className="sfield">
              <label htmlFor="kalToT">Uhrzeit bis</label>
              <input id="kalToT" className="ainput mono" type="time" step="60"
                value={toTime} onChange={(e) => setToTime(e.target.value)} />
            </div>
          </div>
          {multiDay && <p className="kdlg__hint">Mehrtägiger Termin — wird auf alle Tage im Zeitraum markiert.</p>}

          <div className="section-title">Anzugordnung</div>
          <div className="kdlg__chips">
            {ANZUG_PRESETS.map((a) => (
              <button key={a}
                className={"kdlg__chip" + (anzugPreset === a ? " active" : "")}
                onClick={() => setAnzugPreset(a)}>{a}</button>
            ))}
            <button
              className={"kdlg__chip" + (anzugPreset === "custom" ? " active" : "")}
              onClick={() => setAnzugPreset("custom")}>Anderer</button>
          </div>
          {anzugPreset === "custom" && (
            <div className="sfield" style={{ marginTop: 10 }}>
              <label htmlFor="kalAnzug">Freitext</label>
              <input id="kalAnzug" className="ainput" value={anzugCustom}
                onChange={(e) => setAnzugCustom(e.target.value)}
                placeholder="z. B. Sportanzug" />
            </div>
          )}

          <div className="sfield" style={{ marginTop: 14 }}>
            <label htmlFor="kalOrt">Ort</label>
            <input id="kalOrt" className="ainput" value={ort}
              onChange={(e) => setOrt(e.target.value)}
              placeholder="z. B. TrÜbPl Grafenwöhr" />
          </div>

          <div className="sfield">
            <label htmlFor="kalNotes">Notizen</label>
            <textarea id="kalNotes" className="ainput" rows="3" value={notes}
              onChange={(e) => setNotes(e.target.value)}
              placeholder="Weitere Infos zum Termin" />
          </div>

          {category === "urlaub" && (
            <p className="sub-note">
              Urlaub wird zusätzlich als Tagesstatus in den Stundenzettel geschrieben — Werktage im Zeitraum bekommen automatisch Status „Urlaub". Wochenenden und Feiertage bleiben unangetastet.
            </p>
          )}

          {src.id && (
            <button className="abtn abtn--danger" style={{ marginTop: 18, width: "100%" }} onClick={handleDeleteClick}>
              <Icon name="trash" /> Termin löschen
            </button>
          )}
        </div>

        <div className="sub-save">
          <button onClick={handleSaveClick}>Speichern</button>
        </div>
      </div>
    );
  }

  window.KalenderScreen = KalenderScreen;
  window.KalenderEventDialog = EventDialog;
  window.KALENDER_CATS = CATS;
})();
