// booking.jsx — public booking page + confirmation

const MONTHS = ["January","February","March","April","May","June","July","August","September","October","November","December"];
const DOW = ["SUN","MON","TUE","WED","THU","FRI","SAT"];

const TIMES = [
  "9:00 AM","9:30 AM","10:00 AM","10:30 AM","11:00 AM","11:30 AM",
  "12:00 PM","12:30 PM","1:00 PM","1:30 PM","2:00 PM","2:30 PM",
  "3:00 PM","3:30 PM","4:00 PM","4:30 PM"
];

// pre-seeded "available" days (1-31). Booked-out days return false.
function isAvailable(year, month, day, data, event) {
  return getAvailableTimes({ data, event, dateIso: datePartsToIso({ year, month, day }) }).length > 0;
}

function Calendar({ year, month, data, event, selectedDate, onSelectDate, onPrev, onNext }) {
  const firstOfMonth = new Date(year, month, 1);
  const startDay = firstOfMonth.getDay();
  const daysInMonth = new Date(year, month + 1, 0).getDate();
  const daysInPrev = new Date(year, month, 0).getDate();

  // build 6 weeks of cells
  const cells = [];
  for (let i = 0; i < 42; i++) {
    const dayOffset = i - startDay;
    let cellDay, cellMonth, cellYear, otherMonth;
    if (dayOffset < 0) {
      cellDay = daysInPrev + dayOffset + 1;
      cellMonth = month - 1; cellYear = year;
      otherMonth = true;
    } else if (dayOffset >= daysInMonth) {
      cellDay = dayOffset - daysInMonth + 1;
      cellMonth = month + 1; cellYear = year;
      otherMonth = true;
    } else {
      cellDay = dayOffset + 1;
      cellMonth = month; cellYear = year;
      otherMonth = false;
    }
    if (cellMonth < 0) { cellMonth = 11; cellYear -= 1; }
    if (cellMonth > 11) { cellMonth = 0; cellYear += 1; }
    cells.push({ day: cellDay, month: cellMonth, year: cellYear, otherMonth });
  }
  // trim trailing all-other-month rows
  while (cells.length > 35 && cells.slice(35).every(c => c.otherMonth)) cells.length = 35;

  return (
    <div className="cal-section">
      <h4 className="cal-section-label">Select a date &amp; time</h4>
      <div className="cal-h">
        <div className="cal-nav">
          <button onClick={onPrev} aria-label="Prev"><I.chevL size={14}/></button>
        </div>
        <div className="month">{MONTHS[month]} {year}</div>
        <div className="cal-nav">
          <button onClick={onNext} aria-label="Next"><I.chev size={14}/></button>
        </div>
      </div>
      <div className="cal-grid">
        {DOW.map(d => <div key={d} className="dow">{d}</div>)}
        {cells.map((c, i) => {
          const avail = !c.otherMonth && isAvailable(c.year, c.month, c.day, data, event);
          const isSelected = selectedDate &&
            selectedDate.year === c.year && selectedDate.month === c.month && selectedDate.day === c.day;
          return (
            <button
              key={i}
              disabled={!avail}
              onClick={() => avail && onSelectDate({year: c.year, month: c.month, day: c.day})}
              className={[
                "cal-day",
                c.otherMonth ? "is-other-month" : "",
                avail ? "has-slots" : "",
                isSelected ? "is-selected" : "",
              ].join(" ")}>
              {c.day}
            </button>
          );
        })}
      </div>
    </div>
  );
}

function TimesList({ selectedDate, event, data, selectedTime, onSelectTime }) {
  const dateIso = selectedDate ? datePartsToIso(selectedDate) : null;
  const times = dateIso ? getAvailableTimes({ data, event, dateIso }) : [];
  const isClassMode = Number(event?.maxSpaces || 0) > 0;
  return (
    <div className="times-section">
      <h4 className="bk-section-h">Available times</h4>
      <div className="times">
        {!selectedDate && <div className="empty-inline">Choose a date to see times.</div>}
        {selectedDate && times.length === 0 && <div className="empty-inline">No open times for this date.</div>}
        {times.map(t => {
          const info = isClassMode ? getSlotInfo({ data, event, dateIso, time: t }) : null;
          return (
            <button key={t}
              className={"time-btn " + (selectedTime === t ? "is-selected" : "") + (isClassMode ? " has-capacity" : "")}
              onClick={() => onSelectTime(t)}>
              <span className="time-label">{t}</span>
              {info && (
                <span className={"slot-spaces " + (info.available <= 2 ? "is-low" : "")}>
                  {info.booked}/{info.total}
                </span>
              )}
            </button>
          );
        })}
      </div>
    </div>
  );
}

function getPaymentDue(event) {
  if (!event || Number(event.price || 0) <= 0 || (event.paymentMode || "none") === "none") return 0;
  if (event.paymentMode === "deposit") return Number(event.depositAmount || 0);
  return Number(event.price || 0); // covers "full" and "term"
}

function computeDiscount(coupon, originalAmount) {
  if (!coupon || originalAmount <= 0) return 0;
  if (coupon.discountType === "percent")
    return Math.round((originalAmount * coupon.discountValue) / 100 * 100) / 100;
  if (coupon.discountType === "fixed")
    return Math.min(originalAmount, coupon.discountValue);
  if (coupon.discountType === "free" || coupon.discountType === "trial")
    return originalAmount; // fully covers
  return 0;
}

function couponDiscountLabel(coupon) {
  if (!coupon) return "";
  if (coupon.discountType === "percent") return `${coupon.discountValue}% off`;
  if (coupon.discountType === "fixed")   return `£${coupon.discountValue} off`;
  if (coupon.discountType === "trial")   return `${coupon.trialDays}-day free trial`;
  if (coupon.discountType === "free")    return "Free access";
  return "Discount";
}

function priceLabel(event, currency) {
  if (!event || Number(event.price || 0) <= 0) return "Free";
  const money = formatMoney(event.price, currency);
  if (event.paymentMode === "term" && Number(event.termWeeks || 0) > 0) {
    const saving = (Number(event.classPrice || 0) * Number(event.termWeeks)) - Number(event.price);
    const savingStr = saving > 0 ? ` · Save ${formatMoney(saving, currency)}` : "";
    return `${money} / ${event.termWeeks}-week term${savingStr}`;
  }
  if (event.paymentMode === "deposit")
    return `${formatMoney(event.depositAmount || 0, currency)} deposit`;
  return `${money} per class`;
}

function PaymentSection({ data, event, form, setForm, errors, amountOverride }) {
  const baseAmount = getPaymentDue(event);
  if (!baseAmount) return null; // free service

  const amount = amountOverride !== undefined ? amountOverride : baseAmount;

  // Coupon covered the whole thing
  if (amount === 0) {
    return (
      <div className="coupon-free-notice">
        <I.check size={14}/> Fully covered by coupon — no payment required
      </div>
    );
  }

  const providers = ["Stripe", "PayPal"].filter((name) => data.integrations?.[name]?.connected);
  const update = (patch) => setForm((f) => ({ ...f, ...patch }));
  return (
    <div className="payment-box">
      <div className="payment-head">
        <div>
          <h4>Payment</h4>
          <p>
            {event.paymentMode === "deposit" ? "Deposit due now" :
             event.paymentMode === "term" ? `${Number(event.termWeeks || 0)}-week term — due now` :
             "Due now"}
            {" · "}{formatMoney(amount, data.profile.currency)}
            {amountOverride !== undefined && amountOverride < baseAmount && (
              <span style={{marginLeft:6,textDecoration:"line-through",color:"var(--text-faint)",fontSize:12}}>
                {formatMoney(baseAmount, data.profile.currency)}
              </span>
            )}
          </p>
        </div>
        {form.paymentComplete && <span className="payment-paid"><I.check size={12}/> Paid</span>}
      </div>
      {providers.length === 0 ? (
        <div className="empty-inline">Connect Stripe or PayPal before taking online payments.</div>
      ) : (
        <>
          <div className={"payment-options " + (errors.payment ? "invalid" : "")}>
            {providers.map((provider) => (
              <button
                key={provider}
                className={"payment-option " + (form.paymentProvider === provider ? "is-selected" : "")}
                onClick={() => update({ paymentProvider: provider, paymentComplete: false })}
                type="button">
                <span className={"pay-logo " + provider.toLowerCase()}>{provider[0]}</span>
                <span>{provider}</span>
              </button>
            ))}
          </div>
          <button
            className="payment-button"
            type="button"
            disabled={!form.paymentProvider}
            onClick={() => update({ paymentComplete: true, paymentAmount: amount })}>
            {form.paymentProvider ? `Pay ${formatMoney(amount, data.profile.currency)} with ${form.paymentProvider}` : "Choose payment method"}
          </button>
        </>
      )}
    </div>
  );
}

function YourDetails({ form, setForm, event, data, errors, onSubmit, canSubmit,
  coupon, couponInput, setCouponInput, couponError, couponBusy,
  onApplyCoupon, onRemoveCoupon, effectiveAmount }) {
  const update = (k, v) => setForm(f => ({...f, [k]: v}));
  const updateAnswer = (id, value) => setForm(f => ({...f, answers: { ...(f.answers || {}), [id]: value }}));
  const questions = event?.questions || [];
  const hasPaidEvent = getPaymentDue(event) > 0;

  return (
    <div>
      <h4 className="bk-section-h">Your details</h4>
      <div className="bk-form">
        <div className="bk-field">
          <label>Full name <span className="req">*</span></label>
          <input className={"bk-input " + (errors.name ? "invalid" : "")}
            placeholder="Enter your full name"
            value={form.name} onChange={e => update("name", e.target.value)}/>
        </div>
        <div className="bk-field">
          <label>Email <span className="req">*</span></label>
          <input className={"bk-input " + (errors.email ? "invalid" : "")}
            type="text" inputMode="email" placeholder="Enter your email address"
            value={form.email} onChange={e => update("email", e.target.value)}/>
        </div>
        <div className="bk-field">
          <label>Phone <span className="opt">(optional)</span></label>
          <input className="bk-input" type="tel" placeholder="+44 7700 900000"
            value={form.phone} onChange={e => update("phone", e.target.value)}/>
        </div>
        <div className="bk-field">
          <label>Notes <span className="opt">(optional)</span></label>
          <textarea className="bk-textarea" maxLength={500}
            placeholder="Anything we should know ahead of time?"
            value={form.notes} onChange={e => update("notes", e.target.value)}/>
          <div className="bk-counter">{form.notes.length}/500</div>
        </div>
        {questions.length > 0 && (
          <div className="bk-extra-questions">
            <h4 className="bk-section-h">Booking questions</h4>
            {questions.map((question) => (
              <div className="bk-field" key={question.id}>
                <label>{question.label} {question.required && <span className="req">*</span>}</label>
                {question.type === "textarea" ? (
                  <textarea
                    className={"bk-textarea " + (errors[`answer-${question.id}`] ? "invalid" : "")}
                    value={form.answers?.[question.id] || ""}
                    onChange={(e) => updateAnswer(question.id, e.target.value)}
                  />
                ) : (
                  <input
                    className={"bk-input " + (errors[`answer-${question.id}`] ? "invalid" : "")}
                    value={form.answers?.[question.id] || ""}
                    onChange={(e) => updateAnswer(question.id, e.target.value)}
                  />
                )}
              </div>
            ))}
          </div>
        )}
        {event?.requireTerms && (
          <label className={"terms-check " + (errors.terms ? "invalid" : "")}>
            <input type="checkbox" checked={!!form.acceptedTerms} onChange={() => update("acceptedTerms", !form.acceptedTerms)}/>
            <span>{event.termsText || "I agree to the booking terms."}</span>
          </label>
        )}

        {/* ── Coupon code ── */}
        <div className="bk-field">
          <label>Coupon code <span className="opt">(optional)</span></label>
          {coupon ? (
            <div className="coupon-applied-badge">
              <I.check size={13}/>
              <span><strong>{coupon.code}</strong> — {couponDiscountLabel(coupon)} applied</span>
              <button onClick={onRemoveCoupon} aria-label="Remove coupon">✕</button>
            </div>
          ) : (
            <>
              <div className="coupon-input-row">
                <input
                  className={"bk-input " + (couponError ? "invalid" : "")}
                  style={{textTransform:"uppercase", letterSpacing:"0.06em", fontWeight:600}}
                  placeholder="Enter code…"
                  value={couponInput}
                  onChange={e => { setCouponInput(e.target.value.toUpperCase()); }}
                  onKeyDown={e => e.key === "Enter" && onApplyCoupon()}
                />
                <button className="btn ghost" onClick={onApplyCoupon}
                  disabled={!couponInput.trim() || couponBusy}>
                  {couponBusy ? "…" : "Apply"}
                </button>
              </div>
              {couponError && <div className="coupon-error">{couponError}</div>}
            </>
          )}
        </div>

        <PaymentSection data={data} event={event} form={form} setForm={setForm}
          errors={errors} amountOverride={hasPaidEvent ? effectiveAmount : undefined}/>
        <button className="bk-confirm-btn" onClick={onSubmit} disabled={!canSubmit}>
          Confirm booking
        </button>
        <div className="bk-secure">
          <I.shield size={13}/>
          <span>Your information is secure and will only be used for this booking.</span>
        </div>
      </div>
    </div>
  );
}

function dateLabel(d) {
  if (!d) return "—";
  const obj = new Date(d.year, d.month, d.day);
  return obj.toLocaleDateString("en-US", { weekday: "long", month: "long", day: "numeric", year: "numeric" });
}

function isPhysicalLocation(location) {
  const value = String(location || "").trim();
  if (!value) return false;
  return !/(zoom|google meet|teams|meet|phone|online|video|call)/i.test(value);
}

function mapsUrl(location) {
  return `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(location)}`;
}

function LocationMap({ location }) {
  if (!isPhysicalLocation(location)) return null;
  return (
    <div className="location-map-card">
      <div className="location-map">
        <div className="map-grid-lines"/>
        <div className="map-road main"/>
        <div className="map-road cross"/>
        <div className="map-pin">
          <I.location size={18}/>
        </div>
      </div>
      <div className="location-map-info">
        <div>
          <div className="location-map-label">Location</div>
          <div className="location-map-address">{location}</div>
        </div>
        <a className="map-link" href={mapsUrl(location)} target="_blank" rel="noreferrer">
          Open in Maps
        </a>
      </div>
    </div>
  );
}

function EventSummary({ events, selectedEventId, selectedEvent, currency, onSelectEvent }) {
  return (
    <div className="booking-event-card">
      <label>Appointment type</label>
      <select className="bk-input" value={selectedEventId} onChange={(e) => onSelectEvent(e.target.value)}>
        {events.map((event) => (
          <option key={event.id} value={event.id}>
            {event.name} · {event.duration} min · {priceLabel(event, currency)}
          </option>
        ))}
      </select>
      {selectedEvent?.location && !isPhysicalLocation(selectedEvent.location) && (
        <div className="event-location-line"><I.location size={13}/>{selectedEvent.location}</div>
      )}
      <LocationMap location={selectedEvent?.location}/>
    </div>
  );
}

function BookingPage({ onBack, data, onConfirmed }) {
  const today = new Date();
  const bookableEvents = data.events.filter((event) => event.enabled);
  const [selectedEventId, setSelectedEventId] = React.useState(bookableEvents[0]?.id || "");
  const [year, setYear] = React.useState(today.getFullYear());
  const [month, setMonth] = React.useState(today.getMonth());
  const [selectedDate, setSelectedDate] = React.useState(null);
  const [selectedTime, setSelectedTime] = React.useState(null);
  const [form, setForm] = React.useState({ name: "", email: "", phone: "", notes: "", answers: {}, acceptedTerms: false, paymentProvider: "", paymentComplete: false, paymentAmount: 0 });
  const [errors, setErrors] = React.useState({});

  // Coupon state
  const [coupon,       setCoupon]       = React.useState(null);
  const [couponInput,  setCouponInput]  = React.useState("");
  const [couponError,  setCouponError]  = React.useState("");
  const [couponBusy,   setCouponBusy]   = React.useState(false);

  const selectedEvent  = bookableEvents.find((event) => event.id === selectedEventId) || bookableEvents[0];
  const baseAmount     = getPaymentDue(selectedEvent);
  const discountAmount = coupon ? computeDiscount(coupon, baseAmount) : 0;
  const effectiveAmount = Math.max(0, baseAmount - discountAmount);

  const handlePrev = () => {
    setMonth(m => { if (m === 0) { setYear(y => y - 1); return 11; } return m - 1; });
  };
  const handleNext = () => {
    setMonth(m => { if (m === 11) { setYear(y => y + 1); return 0; } return m + 1; });
  };

  const handleApplyCoupon = async () => {
    if (!couponInput.trim()) return;
    setCouponBusy(true); setCouponError("");
    const result = await validateCoupon(couponInput);
    if (result.valid) {
      setCoupon(result.coupon);
      // Reset payment if the effective amount changed
      setForm(f => ({ ...f, paymentComplete: false, paymentAmount: 0 }));
    } else {
      setCouponError(result.error);
    }
    setCouponBusy(false);
  };

  const handleRemoveCoupon = () => {
    setCoupon(null); setCouponInput(""); setCouponError("");
    setForm(f => ({ ...f, paymentComplete: false, paymentAmount: 0 }));
  };

  const validEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.email.trim());
  const requiredAnswersDone = (selectedEvent?.questions || [])
    .filter((q) => q.required)
    .every((q) => String(form.answers?.[q.id] || "").trim().length > 0);
  const termsDone   = !selectedEvent?.requireTerms || !!form.acceptedTerms;
  const paymentDone = !effectiveAmount || !!form.paymentComplete;
  const canSubmit   = !!selectedEvent && !!selectedDate && !!selectedTime && form.name.trim().length > 1 && validEmail && requiredAnswersDone && termsDone && paymentDone;

  const submit = () => {
    const errs = {};
    if (form.name.trim().length < 2) errs.name = true;
    if (!validEmail) errs.email = true;
    (selectedEvent?.questions || []).forEach((q) => {
      if (q.required && !String(form.answers?.[q.id] || "").trim()) errs[`answer-${q.id}`] = true;
    });
    if (selectedEvent?.requireTerms && !form.acceptedTerms) errs.terms = true;
    if (effectiveAmount && !form.paymentComplete) errs.payment = true;
    setErrors(errs);
    if (Object.keys(errs).length === 0 && selectedDate && selectedTime) {
      onConfirmed({
        date: datePartsToIso(selectedDate), time: selectedTime,
        name: form.name, email: form.email, phone: form.phone, notes: form.notes, answers: form.answers,
        paymentStatus: effectiveAmount > 0 ? "Paid" : (baseAmount > 0 ? "Free (coupon)" : "Not required"),
        paymentProvider: form.paymentProvider,
        paymentAmount: effectiveAmount,
        couponCode:  coupon?.code   || "",
        couponId:    coupon?.id     || "",
        discountApplied: discountAmount,
        eventId: selectedEvent.id,
        service: selectedEvent.name,
      });
    }
  };

  return (
    <div className="public">
      <div className="public-bar">
        <div className="brand">
          <div className="sb-mark" style={{width:24, height:24, fontSize:12}}>{data.profile.logoUrl ? <img src={data.profile.logoUrl} alt=""/> : getLogoText(data.profile)}</div>
          <span>{data.profile.brandName}</span>
        </div>
        <button className="public-back" onClick={onBack}>
          <I.chevL size={13}/> Back to dashboard
        </button>
      </div>

      <div className="public-body">
        <div className="bk-hero">
          <div className="avatar lg">{data.profile.initials}</div>
          <h2>Book with {data.profile.name}</h2>
          <p>{data.profile.bio}</p>
        </div>

        {bookableEvents.length > 0 ? (
          <EventSummary events={bookableEvents} selectedEventId={selectedEventId} selectedEvent={selectedEvent} currency={data.profile.currency}
            onSelectEvent={(id) => {
              setSelectedEventId(id);
              setSelectedDate(null);
              setSelectedTime(null);
              setForm((f) => ({ ...f, paymentProvider: "", paymentComplete: false, paymentAmount: 0 }));
            }}/>
        ) : (
          <div className="booking-event-card">No appointment types are currently available.</div>
        )}

        <div className="bk-grid">
          <Calendar year={year} month={month} data={data} event={selectedEvent}
            selectedDate={selectedDate}
            onSelectDate={(d) => { setSelectedDate(d); setSelectedTime(null); }}
            onPrev={handlePrev} onNext={handleNext}/>
          <TimesList selectedDate={selectedDate} event={selectedEvent} data={data} selectedTime={selectedTime}
            onSelectTime={(t) => selectedDate && setSelectedTime(t)}/>
          <YourDetails form={form} setForm={setForm} event={selectedEvent} data={data} errors={errors}
            onSubmit={submit} canSubmit={canSubmit}
            coupon={coupon} couponInput={couponInput} setCouponInput={setCouponInput}
            couponError={couponError} setCouponError={setCouponError}
            couponBusy={couponBusy} onApplyCoupon={handleApplyCoupon} onRemoveCoupon={handleRemoveCoupon}
            effectiveAmount={effectiveAmount}/>
        </div>

        {(selectedDate || selectedTime) && (
          <div style={{maxWidth:600, margin:"24px auto 0", textAlign:"center"}}>
            <div className="muted" style={{fontSize:12, marginBottom:6}}>You're booking</div>
            <div style={{fontSize:14, fontWeight:500}}>
              {selectedEvent?.name} · {selectedDate ? dateLabel(selectedDate) : "—"}{selectedTime ? ` · ${selectedTime}` : ""}
            </div>
          </div>
        )}
      </div>

      {!data.profile.whiteLabel && (
        <div className="public-foot">
          <div>Powered by <strong style={{color:"var(--text)"}}>Nexus Booking</strong></div>
          <div className="links">
            <a>Privacy</a><a>Terms</a>
          </div>
        </div>
      )}
    </div>
  );
}

function Confirmation({ booking, profile, onAnother, onBack }) {
  if (!booking) return null;
  return (
    <div className="public">
      <div className="public-bar">
        <div className="brand">
          <div className="sb-mark" style={{width:24, height:24, fontSize:12}}>{profile.logoUrl ? <img src={profile.logoUrl} alt=""/> : getLogoText(profile)}</div>
          <span>{profile.brandName}</span>
        </div>
        <button className="public-back" onClick={onBack}>
          <I.chevL size={13}/> Back to dashboard
        </button>
      </div>
      <div className="public-body" style={{display:"flex", alignItems:"center"}}>
        <div className="confirm-card">
          <div className="confirm-icon"><I.check size={32}/></div>
          <h2>You're booked in.</h2>
          <p className="sub">A confirmation has been sent to <strong style={{color:"var(--text)"}}>{booking.guestEmail}</strong>.</p>
          <dl className="confirm-detail">
            <dt>Service</dt><dd>{booking.eventName}</dd>
            <dt>Date</dt><dd>{formatIsoDate(booking.date, { weekday: "long", year: true })}</dd>
            <dt>Time</dt><dd>{booking.time}</dd>
            <dt>With</dt><dd>{profile.name}</dd>
            {booking.location && <><dt>Location</dt><dd>{booking.location}</dd></>}
            {booking.paymentStatus && <><dt>Payment</dt><dd>{booking.paymentStatus}{booking.paymentProvider ? ` · ${booking.paymentProvider}` : ""}{booking.paymentAmount ? ` · ${formatMoney(booking.paymentAmount, profile.currency)}` : ""}</dd></>}
          </dl>
          <LocationMap location={booking.location}/>
          {booking.manageToken && (
            <div className="manage-link-box">
              <I.cal size={14}/>
              <div>
                <div style={{fontWeight:600, marginBottom:2}}>Need to change your booking?</div>
                <a href={`${window.location.origin}/?manage=${booking.manageToken}`} target="_blank" rel="noopener noreferrer" style={{color:"var(--accent)", fontSize:13}}>Reschedule or cancel →</a>
              </div>
            </div>
          )}
          <div className="confirm-actions">
            <button onClick={onAnother}>Book another</button>
            <button className="primary" onClick={onBack}>Done</button>
          </div>
        </div>
      </div>
      {!profile.whiteLabel && (
        <div className="public-foot">
          <div>Powered by <strong style={{color:"var(--text)"}}>Nexus Booking</strong></div>
          <div className="links"><a>Privacy</a><a>Terms</a></div>
        </div>
      )}
    </div>
  );
}

// ── Customer manage page (?manage=TOKEN) ─────────────────────
function ManageBookingPage({ token }) {
  const [state, setState]   = React.useState("loading"); // loading | ready | rescheduling | done | error
  const [result, setResult] = React.useState(null);      // { booking, publicData }
  const [action, setAction] = React.useState(null);      // "cancel" | "reschedule"

  // Reschedule picker state
  const today = new Date();
  const [year, setYear]   = React.useState(today.getFullYear());
  const [month, setMonth] = React.useState(today.getMonth());
  const [newDate, setNewDate] = React.useState(null);
  const [newTime, setNewTime] = React.useState(null);
  const [saving, setSaving]   = React.useState(false);
  const [doneMsg, setDoneMsg] = React.useState("");

  React.useEffect(() => {
    fetchBookingByToken(token).then(r => {
      if (!r) setState("error");
      else { setResult(r); setState("ready"); }
    });
  }, [token]);

  if (state === "loading") return <div className="loading-shell"><div className="loading-dots"><span/><span/><span/></div></div>;
  if (state === "error")   return (
    <div className="login-shell">
      <div className="login-card" style={{textAlign:"center"}}>
        <div className="sb-mark" style={{margin:"0 auto 16px"}}>N</div>
        <h2>Booking not found</h2>
        <p style={{color:"var(--text-muted)", marginTop:8}}>This link may have expired or the booking no longer exists.</p>
      </div>
    </div>
  );

  const { booking, publicData } = result;
  const { profile } = publicData;
  const isCancelled = booking.status === "Cancelled";

  if (state === "done") return (
    <div style={getBrandStyle(profile)}>
      <div className="public">
        <div className="public-bar">
          <div className="brand">
            <div className="sb-mark" style={{width:24,height:24,fontSize:12}}>{profile.logoUrl ? <img src={profile.logoUrl} alt=""/> : getLogoText(profile)}</div>
            <span>{profile.brandName}</span>
          </div>
        </div>
        <div className="public-body" style={{display:"flex", alignItems:"center"}}>
          <div className="confirm-card">
            <div className="confirm-icon"><I.check size={32}/></div>
            <h2>{doneMsg}</h2>
            {action === "reschedule" && (
              <dl className="confirm-detail">
                <dt>Service</dt><dd>{booking.eventName}</dd>
                <dt>New date</dt><dd>{formatIsoDate(newDate, { weekday:"long", year:true })}</dd>
                <dt>New time</dt><dd>{newTime}</dd>
              </dl>
            )}
            <div className="confirm-actions" style={{marginTop:24}}>
              <button className="primary" onClick={() => window.location.href = window.location.origin + "/?book=" + profile.bookingUrl}>Book again</button>
            </div>
          </div>
        </div>
      </div>
    </div>
  );

  // Reschedule flow
  const event = publicData.events.find(e => e.id === booking.eventId) || publicData.events[0];
  const dataWithoutBooking = { ...publicData, bookings: publicData.bookings.filter(b => b.id !== booking.id) };

  const daysInMonth = new Date(year, month + 1, 0).getDate();
  const firstDay    = (new Date(year, month, 1).getDay() + 6) % 7; // Mon=0
  const MONTHS      = ["January","February","March","April","May","June","July","August","September","October","November","December"];
  const todayIsoStr = todayIso();

  const handleCancel = async () => {
    if (!confirm("Are you sure you want to cancel this booking?")) return;
    setSaving(true);
    await sb.from("bookings").update({ status: "Cancelled" }).eq("manage_token", token);
    setResult(r => ({ ...r, booking: { ...r.booking, status: "Cancelled" } }));
    setAction("cancel");
    setDoneMsg("Your booking has been cancelled.");
    setState("done");
    setSaving(false);
  };

  const handleReschedule = async () => {
    if (!newDate || !newTime) return;
    setSaving(true);
    await sb.from("bookings").update({ date: newDate, time: newTime, status: "Rescheduled" }).eq("manage_token", token);
    setAction("reschedule");
    setDoneMsg("Your booking has been rescheduled.");
    setState("done");
    setSaving(false);
  };

  const slots = React.useMemo(() => {
    if (!event || !newDate) return [];
    return getAvailableTimes({ data: dataWithoutBooking, event, dateIso: newDate });
  }, [newDate, event]);

  return (
    <div style={getBrandStyle(profile)}>
      <div className="public">
        <div className="public-bar">
          <div className="brand">
            <div className="sb-mark" style={{width:24,height:24,fontSize:12}}>{profile.logoUrl ? <img src={profile.logoUrl} alt=""/> : getLogoText(profile)}</div>
            <span>{profile.brandName}</span>
          </div>
        </div>
        <div className="public-body" style={{display:"flex", alignItems:"center"}}>
          <div className="confirm-card" style={{maxWidth:480}}>
            <h2 style={{marginBottom:4}}>Manage your booking</h2>
            <p className="sub" style={{marginBottom:20}}>with {profile.brandName}</p>

            <dl className="confirm-detail" style={{marginBottom:20}}>
              <dt>Service</dt><dd>{booking.eventName}</dd>
              <dt>Date</dt><dd>{formatIsoDate(booking.date, { weekday:"long", year:true })}</dd>
              <dt>Time</dt><dd>{booking.time}</dd>
              <dt>Status</dt><dd><span className={"pill " + booking.status.toLowerCase()}>{booking.status}</span></dd>
            </dl>

            {isCancelled ? (
              <p style={{color:"var(--text-muted)", textAlign:"center", padding:"12px 0"}}>This booking has already been cancelled.</p>
            ) : action !== "reschedule" ? (
              <div style={{display:"flex", gap:10, marginTop:8}}>
                <button className="bk-confirm-btn" style={{background:"var(--surface-2)", color:"var(--text)", flex:1}} onClick={() => setAction("reschedule")}>
                  <I.cal size={14}/> Reschedule
                </button>
                <button className="bk-confirm-btn" style={{background:"#fee2e2", color:"#dc2626", flex:1}} onClick={handleCancel} disabled={saving}>
                  {saving ? "Cancelling…" : "Cancel booking"}
                </button>
              </div>
            ) : (
              <>
                <h3 style={{marginBottom:12}}>Pick a new date & time</h3>
                <div className="bk-calendar">
                  <div className="bk-cal-nav">
                    <button onClick={() => { if (month===0){setYear(y=>y-1);setMonth(11);}else setMonth(m=>m-1); }}><I.chevL size={14}/></button>
                    <span>{MONTHS[month]} {year}</span>
                    <button onClick={() => { if (month===11){setYear(y=>y+1);setMonth(0);}else setMonth(m=>m+1); }}><I.chev size={14}/></button>
                  </div>
                  <div className="bk-cal-grid">
                    {["Mo","Tu","We","Th","Fr","Sa","Su"].map(d=><div key={d} className="bk-cal-head">{d}</div>)}
                    {Array.from({length: firstDay}, (_,i) => <div key={"e"+i}/>)}
                    {Array.from({length: daysInMonth}, (_,i) => {
                      const d = i + 1;
                      const iso = `${year}-${String(month+1).padStart(2,"0")}-${String(d).padStart(2,"0")}`;
                      const isPast = iso < todayIsoStr;
                      const isSelected = iso === newDate;
                      const hasTimes = !isPast && event && getAvailableTimes({ data: dataWithoutBooking, event, dateIso: iso }).length > 0;
                      return (
                        <button key={d}
                          className={"bk-cal-day" + (isSelected?" is-selected":"") + (isPast||!hasTimes?" is-disabled":"")}
                          disabled={isPast || !hasTimes}
                          onClick={() => { setNewDate(iso); setNewTime(null); }}>
                          {d}
                        </button>
                      );
                    })}
                  </div>
                </div>
                {newDate && slots.length > 0 && (
                  <div className="bk-times" style={{marginTop:12}}>
                    {slots.map(s => (
                      <button key={s} className={"bk-time" + (newTime===s?" is-selected":"")} onClick={() => setNewTime(s)}>{s}</button>
                    ))}
                  </div>
                )}
                {newDate && slots.length === 0 && (
                  <p style={{color:"var(--text-muted)", textAlign:"center", padding:"12px 0", fontSize:13}}>No available times on this date. Try another day.</p>
                )}
                <div style={{display:"flex", gap:10, marginTop:16}}>
                  <button className="bk-confirm-btn" style={{background:"var(--surface-2)", color:"var(--text)", flex:1}} onClick={() => setAction(null)}>Back</button>
                  <button className="bk-confirm-btn" style={{flex:2}} onClick={handleReschedule} disabled={!newDate || !newTime || saving}>
                    {saving ? "Saving…" : "Confirm reschedule"}
                  </button>
                </div>
              </>
            )}
          </div>
        </div>
        {!profile.whiteLabel && (
          <div className="public-foot">
            <div>Powered by <strong style={{color:"var(--text)"}}>Nexus Booking</strong></div>
          </div>
        )}
      </div>
    </div>
  );
}

window.ManageBookingPage = ManageBookingPage;
window.BookingPage = BookingPage;
window.Confirmation = Confirmation;
