// screens-book.jsx — schedule with day-swipe & session cards
//
// Day strip across the top (today + next 6). Tap or swipe horizontally to
// change the active day. A filter row lets the user pin a class type or a
// teacher. Sessions render as scrollable cards under sticky time bands.

const { fmtIDR, findClass, findCoach, findFriend, minutesUntil, fmtCountdown,
        DAYS_SHORT, DAYS_LONG, DATES_THIS_WEEK, TODAY_DAY } = window.NADI_HELPERS;

function BookScreen({ user, openClassSheet, setTab, upcomingBookings }) {
  const getAppToday = window.NADI_HELPERS.getAppToday;
  const parseLocalDate = window.NADI_HELPERS.parseLocalDate;
  const formatLocalDateISO = window.NADI_HELPERS.formatLocalDateISO;

  const minWS = new Date(2026, 4, 25); // May 25, 2026

  const [activeDate, setActiveDate] = useState(() => {
    return getAppToday();
  });

  const [weekStart, setWeekStart] = useState(() => {
    const d = new Date(activeDate);
    const day = d.getDay();
    const diff = d.getDate() - day + (day === 0 ? -6 : 1); // Monday
    return new Date(d.setDate(diff));
  });

  useEffect(() => {
    const d = new Date(activeDate);
    const day = d.getDay();
    const diff = d.getDate() - day + (day === 0 ? -6 : 1);
    setWeekStart(new Date(d.setDate(diff)));
  }, [activeDate]);

  const weekDates = Array.from({ length: 7 }, (_, i) => {
    const d = new Date(weekStart);
    d.setDate(weekStart.getDate() + i);
    return d;
  });

  const activeDateStr = formatLocalDateISO(activeDate);
  const weekEnd = weekDates[6];

  const prevWeek = () => {
    const nextWS = new Date(weekStart.getTime() - 7 * 24 * 60 * 60 * 1000);
    if (nextWS < minWS) return;
    setWeekStart(nextWS);
    setActiveDate(nextWS);
  };

  const nextWeek = () => {
    const nextWS = new Date(weekStart.getTime() + 7 * 24 * 60 * 60 * 1000);
    setWeekStart(nextWS);
    setActiveDate(nextWS);
  };

  const handlePrevDay = () => {
    setActiveDate((curr) => {
      const prev = new Date(curr.getTime() - 24 * 60 * 60 * 1000);
      if (prev < minWS) return curr;
      return prev;
    });
  };

  const handleNextDay = () => {
    setActiveDate((curr) => {
      const next = new Date(curr.getTime() + 24 * 60 * 60 * 1000);
      return next;
    });
  };

  const [filterClass, setFilterClass] = useState(null);
  const [filterCoach, setFilterCoach] = useState(null);
  const [filterFav, setFilterFav] = useState(false);

  const activeDayIndex = (activeDate.getDay() + 6) % 7; // Monday = 0

  // Sessions on this day
  const all = window.NADI.SCHEDULE.filter((s) => s.date === activeDateStr);
  const filtered = all.filter((s) => {
    if (filterClass && s.classId !== filterClass) return false;
    if (filterCoach && s.coachId !== filterCoach) return false;
    if (filterFav) {
      const f1 = user.savedClasses.includes(s.classId);
      const f2 = user.savedCoaches.includes(s.coachId);
      if (!f1 && !f2) return false;
    }
    return true;
  }).sort((a, b) => a.time.localeCompare(b.time));

  // Filter sheet state
  const [filtersOpen, setFiltersOpen] = useState(false);

  // Swipe gestures on the schedule body
  const swipeRef = useRef(null);
  useEffect(() => {
    const el = swipeRef.current;
    if (!el) return;
    let startX = 0, startY = 0, deltaX = 0, locked = false, captured = false;
    const onStart = (e) => {
      const t = e.touches ? e.touches[0] : e;
      startX = t.clientX; startY = t.clientY; deltaX = 0; locked = false; captured = false;
    };
    const onMove = (e) => {
      const t = e.touches ? e.touches[0] : e;
      const dx = t.clientX - startX, dy = t.clientY - startY;
      if (!locked) {
        if (Math.abs(dx) > 14 || Math.abs(dy) > 14) {
          locked = true;
          captured = Math.abs(dx) > Math.abs(dy);
        }
      }
      if (captured) { deltaX = dx; if (e.cancelable) e.preventDefault(); }
    };
    const onEnd = () => {
      if (captured && Math.abs(deltaX) > 60) {
        if (deltaX < 0) {
          handleNextDay();
        } else {
          handlePrevDay();
        }
      }
      captured = false; locked = false;
    };
    el.addEventListener("touchstart", onStart, { passive: true });
    el.addEventListener("touchmove", onMove, { passive: false });
    el.addEventListener("touchend", onEnd);
    return () => {
      el.removeEventListener("touchstart", onStart);
      el.removeEventListener("touchmove", onMove);
      el.removeEventListener("touchend", onEnd);
    };
  }, [activeDate, weekStart]);

  // Filter active count
  const activeFilters = (filterClass ? 1 : 0) + (filterCoach ? 1 : 0) + (filterFav ? 1 : 0);

  const activeDayIsToday = activeDateStr === formatLocalDateISO(getAppToday());

  return (
    <div className="screen-fade" style={{ flex: 1, display: "flex", flexDirection: "column", minHeight: 0 }}>
      {/* Header */}
      <div style={{
        padding: "8px 22px 12px",
        background: "color-mix(in srgb, var(--bg) 96%, transparent)",
        backdropFilter: "blur(12px)", WebkitBackdropFilter: "blur(12px)",
        zIndex: 5,
      }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
            <Eyebrow>
              {weekStart.getDate()} {weekStart.toLocaleDateString("en-GB", { month: "short" }).toLowerCase()} — {weekEnd.getDate()} {weekEnd.toLocaleDateString("en-GB", { month: "short" }).toLowerCase()}
            </Eyebrow>
            <div style={{ display: "flex", gap: 4 }}>
              <button disabled={weekStart <= minWS} onClick={prevWeek} className="press" style={{
                padding: "2px 8px", background: "transparent", border: "1px solid var(--rule)",
                fontFamily: "monospace", fontSize: 11, opacity: weekStart <= minWS ? 0.3 : 1
              }}>←</button>
              <button onClick={nextWeek} className="press" style={{
                padding: "2px 8px", background: "transparent", border: "1px solid var(--rule)",
                fontFamily: "monospace", fontSize: 11
              }}>→</button>
            </div>
          </div>
          <button onClick={() => setFiltersOpen(true)} className="press" style={{
            display: "inline-flex", alignItems: "center", gap: 6,
            padding: "6px 12px", border: `1px solid ${activeFilters ? "var(--primary)" : "var(--rule)"}`,
            background: activeFilters ? "var(--primary)" : "transparent",
            color: activeFilters ? "var(--primary-ink)" : "var(--ink)",
            fontFamily: "'JetBrains Mono', monospace", fontSize: 10.5, letterSpacing: "0.08em",
            textTransform: "lowercase",
          }}>
            <svg width="11" height="11" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"><path d="M1 3h10M3 6h6M5 9h2"/></svg>
            filter{activeFilters > 0 ? ` · ${activeFilters}` : ""}
          </button>
        </div>
        <h1 className="display" style={{ fontSize: 38, marginTop: 14, marginBottom: 18 }}>
          {activeDayIsToday ? (
            <>Today, <em style={{ fontStyle: "italic", color: "var(--primary)" }}>{DAYS_LONG[activeDayIndex].toLowerCase()}.</em></>
          ) : (
            <>{DAYS_LONG[activeDayIndex]}, <em style={{ fontStyle: "italic", color: "var(--ink-soft)" }}>{String(activeDate.getDate()).padStart(2, "0")} {activeDate.toLocaleDateString("en-GB", { month: "short" }).toLowerCase()}.</em></>
          )}
        </h1>
        {/* Day strip */}
        <DayStrip activeDate={activeDate} setActiveDate={setActiveDate} weekDates={weekDates} />
      </div>

      {/* Schedule body */}
      <PullToRefresh>
        <div ref={swipeRef} style={{ flex: 1, padding: "16px 22px 24px", touchAction: "pan-y" }}>
          {filtered.length === 0 ? (
            <div style={{ padding: "60px 0", textAlign: "center" }}>
              <Mono>nothing scheduled for this day.</Mono>
              <div style={{ marginTop: 16 }}>
                <Button variant="ghost" size="sm" onClick={() => { setFilterClass(null); setFilterCoach(null); setFilterFav(false); }}>Clear filters</Button>
              </div>
            </div>
          ) : (
            <ScheduleBands sessions={filtered} user={user} upcomingBookings={upcomingBookings} activeDateStr={activeDateStr} openClassSheet={openClassSheet} />
          )}
        </div>
      </PullToRefresh>

      {/* Filter sheet */}
      <Sheet open={filtersOpen} onClose={() => setFiltersOpen(false)} maxHeight="80%">
        <FilterSheet
          filterClass={filterClass} setFilterClass={setFilterClass}
          filterCoach={filterCoach} setFilterCoach={setFilterCoach}
          filterFav={filterFav} setFilterFav={setFilterFav}
          onClose={() => setFiltersOpen(false)}
          user={user}
        />
      </Sheet>
    </div>
  );
}

// ── Day strip ─────────────────────────────────────────────────────────
function DayStrip({ activeDate, setActiveDate, weekDates }) {
  const getAppToday = window.NADI_HELPERS.getAppToday;
  const formatLocalDateISO = window.NADI_HELPERS.formatLocalDateISO;
  const todayStr = formatLocalDateISO(getAppToday());

  return (
    <div className="scroll" style={{
      display: "flex", gap: 6, paddingBottom: 4, overflowX: "auto",
      margin: "0 -22px", padding: "0 22px 4px",
    }}>
      {weekDates.map((d, i) => {
        const dStr = formatLocalDateISO(d);
        const isToday = dStr === todayStr;
        const active = dStr === formatLocalDateISO(activeDate);
        return (
          <button key={i} onClick={() => setActiveDate(d)} className="press" style={{
            flexShrink: 0,
            width: 50, height: 64,
            border: `1px solid ${active ? "var(--ink)" : "var(--rule)"}`,
            background: active ? "var(--ink)" : "transparent",
            color: active ? "var(--bg)" : "var(--ink)",
            display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: 4,
            position: "relative",
          }}>
            <span style={{
              fontFamily: "'JetBrains Mono', monospace", fontSize: 10, letterSpacing: "0.08em",
              opacity: active ? 0.7 : 0.6, textTransform: "lowercase",
            }}>{DAYS_SHORT[i].toLowerCase()}</span>
            <span style={{
              fontFamily: "Newsreader, serif", fontSize: 22, fontWeight: 400, lineHeight: 1,
              letterSpacing: "-0.02em",
            }}>{d.getDate()}</span>
            {isToday && !active && (
              <span style={{ position: "absolute", bottom: 6, width: 4, height: 4, borderRadius: "50%", background: "var(--primary)" }} />
            )}
          </button>
        );
      })}
    </div>
  );
}

// ── Time-band groups ─────────────────────────────────────────────────
function ScheduleBands({ sessions, user, upcomingBookings, activeDateStr, openClassSheet }) {
  const bands = [
    { label: "morning",   range: ["00:00", "11:59"] },
    { label: "afternoon", range: ["12:00", "16:59"] },
    { label: "evening",   range: ["17:00", "23:59"] },
  ];
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 26 }}>
      {bands.map((b) => {
        const items = sessions.filter((s) => s.time >= b.range[0] && s.time <= b.range[1]);
        if (items.length === 0) return null;
        return (
          <div key={b.label}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 12 }}>
              <Eyebrow color="var(--primary)">{b.label}</Eyebrow>
              <Mono>{b.range[0]} — {b.range[1]}</Mono>
            </div>
            <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
              {items.map((s) => <SessionCard key={s.id} s={s} user={user} upcomingBookings={upcomingBookings} activeDateStr={activeDateStr} onClick={() => openClassSheet({ ...s, date: activeDateStr })} />)}
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ── Session card (the heart of Book) ─────────────────────────────────
function SessionCard({ s, user, upcomingBookings, activeDateStr, onClick }) {
  const c = findClass(s.classId), co = findCoach(s.coachId);
  const left = s.capacity - s.booked;
  const full = left === 0;
  const fav = user.savedClasses.includes(s.classId) || user.savedCoaches.includes(s.coachId);
  const friends = s.friends.map(findFriend).filter(Boolean);
  const booked = (upcomingBookings || []).some(b => b.session_id === s.id && b.date === activeDateStr);
  const mine = booked;

  // Accent line color based on class color token
  const accent = c.color === "primary" ? "var(--primary)"
              : c.color === "accent"  ? "var(--accent)"
              : "var(--muted)";

  return (
    <button onClick={onClick} className="press" style={{
      width: "100%", textAlign: "left",
      display: "grid", gridTemplateColumns: "78px 1fr",
      gap: 16,
      padding: "16px 18px",
      background: mine ? "var(--ink)" : "var(--bg)",
      color: mine ? "var(--bg)" : "var(--ink)",
      border: `1px solid ${mine ? "var(--ink)" : "var(--rule)"}`,
      borderLeft: `3px solid ${mine ? "var(--primary)" : accent}`,
      position: "relative",
      opacity: full && !mine ? 0.7 : 1,
    }}>
      {/* Time block */}
      <div>
        <div style={{ fontFamily: "Newsreader, serif", fontWeight: 400, fontSize: 26, lineHeight: 1, letterSpacing: "-0.01em" }}>
          {s.time}
        </div>
        <Mono color={mine ? "rgba(248,241,225,0.6)" : "var(--ink-soft)"} style={{ marginTop: 4 }}>
          {c.duration} min
        </Mono>
        {fav && !mine && (
          <span style={{ marginTop: 8, display: "inline-flex" }}>
            <FavIcon size={11} active />
          </span>
        )}
      </div>
      {/* Body */}
      <div style={{ minWidth: 0 }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 10 }}>
          <h3 style={{
            fontFamily: "Newsreader, serif", fontSize: 22, fontWeight: 400,
            lineHeight: 1.1, letterSpacing: "-0.01em",
            textWrap: "nowrap",
            color: mine ? "var(--bg)" : "var(--ink)",
          }}>{c.name}</h3>
          {mine && <Mono color="var(--primary)" style={{ flexShrink: 0 }}>booked</Mono>}
        </div>

        <div style={{ marginTop: 8, display: "flex", alignItems: "center", gap: 8 }}>
          <Avatar name={co.name} initials={co.initials} tone={co.tone} size={20} />
          <Mono color={mine ? "rgba(248,241,225,0.7)" : "var(--ink-soft)"}>
            {co.firstName.toLowerCase()} · {s.roomShort.toLowerCase()}
          </Mono>
        </div>

        <div style={{ marginTop: 12, display: "flex", justifyContent: "space-between", alignItems: "center", gap: 10 }}>
          {friends.length > 0 ? (
            <span style={{ display: "inline-flex", alignItems: "center", gap: 8 }}>
              <FriendStack friends={friends} anonCount={s?.anonCount || 0} size={20} max={3} border={mine ? "var(--ink)" : "var(--bg)"} />
              <Mono color={mine ? "rgba(248,241,225,0.6)" : "var(--ink-soft)"}>{friends.length} going</Mono>
            </span>
          ) : <span />}
          <Mono color={full ? "var(--primary)" : left < 3 ? "var(--primary)" : (mine ? "rgba(248,241,225,0.6)" : "var(--ink-soft)")}>
            {full ? "full · waitlist" : left < 3 ? `${left} left` : `${left}/${s.capacity}`}
          </Mono>
        </div>
      </div>
    </button>
  );
}

function FavIcon({ size = 12, active }) {
  return (
    <svg width={size} height={size} viewBox="0 0 12 12" fill={active ? "var(--primary)" : "none"} stroke={active ? "var(--primary)" : "var(--ink-soft)"} strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M3 1.5h6V11l-3-2-3 2z"/>
    </svg>
  );
}

// ── Filter sheet ─────────────────────────────────────────────────────
function FilterSheet({ filterClass, setFilterClass, filterCoach, setFilterCoach, filterFav, setFilterFav, onClose, user }) {
  return (
    <div style={{ padding: "12px 24px 28px" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 10 }}>
        <Eyebrow>filter</Eyebrow>
        <button onClick={onClose} className="press" style={{ background: "transparent", padding: 6 }}>
          <Mono>done ×</Mono>
        </button>
      </div>

      <h2 className="display" style={{ fontSize: 32, marginBottom: 18 }}>Refine the week.</h2>

      <div style={{ marginBottom: 22 }}>
        <Mono>show only my favourites</Mono>
        <div style={{ marginTop: 8 }}>
          <button onClick={() => setFilterFav(!filterFav)} className="press" style={{
            display: "inline-flex", alignItems: "center", gap: 10,
            padding: "10px 14px",
            border: `1px solid ${filterFav ? "var(--primary)" : "var(--rule)"}`,
            background: filterFav ? "var(--primary)" : "transparent",
            color: filterFav ? "var(--primary-ink)" : "var(--ink)",
          }}>
            <FavIcon size={12} active={filterFav} />
            <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 11, letterSpacing: "0.08em", textTransform: "lowercase" }}>
              saved classes & teachers
            </span>
          </button>
        </div>
      </div>

      <div style={{ marginBottom: 22 }}>
        <Mono>class type</Mono>
        <div style={{ display: "flex", flexWrap: "wrap", gap: 6, marginTop: 10 }}>
          <Chip active={!filterClass} onClick={() => setFilterClass(null)}>all classes</Chip>
          {window.NADI.CLASS_TYPES.map((c) => (
            <Chip key={c.id} active={filterClass === c.id} onClick={() => setFilterClass(c.id === filterClass ? null : c.id)}>
              {c.name.toLowerCase()}
            </Chip>
          ))}
        </div>
      </div>

      <div style={{ marginBottom: 30 }}>
        <Mono>teacher</Mono>
        <div style={{ display: "flex", flexWrap: "wrap", gap: 6, marginTop: 10 }}>
          <Chip active={!filterCoach} onClick={() => setFilterCoach(null)}>all teachers</Chip>
          {window.NADI.COACHES.map((co) => (
            <Chip key={co.id} active={filterCoach === co.id} onClick={() => setFilterCoach(co.id === filterCoach ? null : co.id)}>
              {co.firstName.toLowerCase()}
            </Chip>
          ))}
        </div>
      </div>

      <div style={{ display: "flex", gap: 8 }}>
        <Button variant="ghost" size="md" fullWidth onClick={() => { setFilterClass(null); setFilterCoach(null); setFilterFav(false); }}>Clear</Button>
        <Button variant="primary" size="md" fullWidth onClick={onClose}>Show results</Button>
      </div>
    </div>
  );
}

Object.assign(window, { BookScreen, SessionCard, FavIcon });
