// screens/summer-section.jsx — Dedicated Summer section
// Self-contained area for short-stay rentals (Jun–Aug): calendar, guests,
// contracts, and money. Reached via the sidebar's "Summer" nav item.

function SummerSection({ ctx, initialTab }) {
  const { data, nav } = ctx;
  const tt = ctx.tt;
  const [tab, setTab] = React.useState(initialTab || "calendar");
  // Sync external tab arg (from URL hash) → local state so /summer/money lands
  // on the Money tab even when arriving while the component is already mounted.
  React.useEffect(() => { if (initialTab && initialTab !== tab) setTab(initialTab); }, [initialTab]);

  // Season scope: June through end of August 2026.
  const SEASON_START = "2026-06-01";
  const SEASON_END_EX = "2026-09-01"; // exclusive upper bound
  const SEASON_NIGHTS = nightsBetween(SEASON_START, SEASON_END_EX);

  // All bookings that overlap the season — most things in the section
  // operate on this filtered subset.
  const seasonBookings = data.bookings.filter((b) =>
    b.start < SEASON_END_EX && b.end > SEASON_START);

  const confirmed = seasonBookings.filter((b) => b.status === "confirmed");
  const tentative = seasonBookings.filter((b) => b.status === "tentative");
  const todayISO = ArcoData.ISO(ArcoData.today);

  // Headline numbers shown in the page header.
  const stats = React.useMemo(() => {
    let bookedNights = 0, revenue = 0;
    for (const b of seasonBookings) {
      if (b.status === "blocked" || b.status === "resident") continue;
      const s = b.start < SEASON_START ? SEASON_START : b.start;
      const e = b.end > SEASON_END_EX ? SEASON_END_EX : b.end;
      const nts = nightsBetween(s, e);
      bookedNights += nts;
      revenue += nts * b.nightly;
    }
    const cap = data.apartments.length * SEASON_NIGHTS;
    return { bookedNights, revenue, cap, occPct: Math.round((bookedNights / cap) * 100) };
  }, [seasonBookings]);

  const counts = {
    calendar: undefined,
    guests: seasonBookings.filter((b) => b.status !== "blocked").length,
    contracts: confirmed.length + tentative.length,
    money: undefined,
  };

  return (
    <>
      <div className="main-top">
        <div className="title">
          <h1 className="display flex center gap-2">
            <Icon name="sun" size={20} style={{ color: "var(--ef-accent)" }} />
            {tt("sm.title", { year: 2026 })}
          </h1>
          <div className="sub">{tt("sm.sub", { nights: SEASON_NIGHTS, flats: data.apartments.length, occ: stats.occPct, amt: fmtEUR(stats.revenue) })}</div>
        </div>
        <div className="actions">
          <HeaderTools ctx={ctx} />
          <button className="btn" onClick={() => ctx.showToast && ctx.showToast("Exportación de reservas en marcha — recibirás un email")}>
            <Icon name="file" size={14} /> {tt("btn.exportBookings")}
          </button>
          <button className="btn primary" onClick={() => ctx.openModal && ctx.openModal("newBooking")}>
            <Icon name="plus" size={14} /> {tt("btn.newBooking")}
          </button>
        </div>
      </div>

      <div className="main-scroll">
        <Tabs underline value={tab} onChange={setTab} tabs={[
          { value: "calendar",  label: tt("sm.tab.calendar"),  icon: "calendar" },
          { value: "guests",    label: tt("sm.tab.guests"),    icon: "users",   count: counts.guests },
          { value: "contracts", label: tt("sm.tab.contracts"), icon: "file",    count: counts.contracts },
          { value: "money",     label: tt("sm.tab.money"),     icon: "euro" },
        ]} />

        <div style={{ marginTop: 22 }}>
          {tab === "calendar"  && <SummerCalendarTab ctx={ctx} bookings={data.bookings} todayISO={todayISO} stats={stats} />}
          {tab === "guests"    && <SummerGuestsTab ctx={ctx} bookings={seasonBookings} />}
          {tab === "contracts" && <SummerContractsTab ctx={ctx} bookings={seasonBookings} />}
          {tab === "money"     && <SummerMoneyTab ctx={ctx} bookings={seasonBookings} confirmed={confirmed} stats={stats} />}
        </div>
      </div>

      <style>{summerSectionStyles}</style>
    </>
  );
}

// ───────────────────────── CALENDAR TAB ─────────────────────────
function SummerCalendarTab({ ctx, bookings, todayISO, stats }) {
  const { data, nav } = ctx;
  const tt = ctx.tt || ((k) => k);
  // Default to a 2-month window; user can slide it.
  const [range, setRange] = React.useState(["2026-07", "2026-08"]);
  const RANGE_OPTIONS = [
    { value: "jun-jul", label: "Jun – Jul", months: ["2026-06", "2026-07"] },
    { value: "jul-aug", label: "Jul – Aug", months: ["2026-07", "2026-08"] },
    { value: "jun-aug", label: "All summer", months: ["2026-06", "2026-07", "2026-08"] },
  ];
  const activeRangeValue =
    range.length === 3 ? "jun-aug" :
    range[0] === "2026-06" ? "jun-jul" : "jul-aug";

  // Top arrivals + key callouts.
  const today = new Date(todayISO);
  const arrivals = bookings
    .filter((b) => b.status !== "blocked" && b.status !== "resident" && b.start >= todayISO && b.start <= "2026-09-01")
    .sort((a, b) => a.start.localeCompare(b.start))
    .slice(0, 4);
  const nextA = arrivals[0];
  const daysToNext = nextA ? Math.round((new Date(nextA.start) - today) / 86400000) : null;
  const turnovers = computeTurnovers(bookings.filter((b) => b.status === "confirmed"));

  return (
    <>
      {/* Top KPIs — concise, calendar-focused */}
      <div className="grid-stat-4" style={{ marginBottom: 18 }}>
        <Stat icon="calendar" label="Season occupancy" value={`${stats.occPct}%`}
              sub={<span>{stats.bookedNights} of {stats.cap} nights</span>} />
        <Stat icon="euro" label="Revenue booked" value={fmtEUR(stats.revenue)}
              sub={<span>across {bookings.filter((b)=>b.status==="confirmed").length} confirmed stays</span>} />
        <Stat icon="clock" label="Next arrival"
              value={nextA ? fmtDate(nextA.start, { short: true }) : "—"}
              sub={nextA ? <span>{nextA.guestName.split(/—|\(/)[0].trim()} · in {daysToNext}d</span> : <span className="muted">No upcoming</span>} />
        <Stat icon="wrench" label="Turnovers next 14d" value={turnovers.filter((t) => t.daysAway <= 14).length}
              sub={<span>{turnovers.filter((t) => t.kind === "same-day").length} same-day</span>} />
      </div>

      <div className="flex center between" style={{ marginBottom: 14, flexWrap: "wrap", gap: 8 }}>
        <div className="flex center gap-2">
          <Tabs value={activeRangeValue} onChange={(v) => setRange(RANGE_OPTIONS.find((r) => r.value === v).months)}
                tabs={RANGE_OPTIONS.map(({value, label}) => ({ value, label }))} />
        </div>
        <div className="flex center gap-3 txt-xs muted" style={{ flexWrap: "wrap" }}>
          <span className="flex center gap-1"><i style={{ width: 12, height: 8, background: "var(--ef-accent)", borderRadius: 3 }} /> Confirmed</span>
          <span className="flex center gap-1"><i style={{ width: 12, height: 8, background: "var(--ef-warn-soft)", border: "1px dashed var(--ef-warn)", borderRadius: 3 }} /> Tentative</span>
          <span className="flex center gap-1"><i style={{ width: 12, height: 8, background: "var(--ef-info)", borderRadius: 3 }} /> Long-term resident</span>
          <span className="flex center gap-1"><i style={{ width: 12, height: 8, background: "var(--ef-muted)", borderRadius: 3 }} /> Blocked</span>
        </div>
      </div>

      <Card className="flush" style={{ overflowX: "auto", marginBottom: 24 }}>
        <SummerGantt ctx={ctx} months={range} apartments={data.apartments} bookings={bookings} todayISO={todayISO} />
      </Card>

      {/* Arrivals + turnovers strip below the calendar */}
      <div className="grid-2" style={{ gap: 16 }}>
        <Card>
          <div className="card-head">
            <h3>Arriving soon</h3>
            <Pill className="accent">{arrivals.length}</Pill>
          </div>
          <div className="flex col" style={{ display: "flex", flexDirection: "column" }}>
            {arrivals.length === 0 && <Empty icon="calendar" title={tt("empty.nothingUrgent")} />}
            {arrivals.map((b) => {
              const apt = data.byId.apt(b.aptId);
              const days = Math.round((new Date(b.start) - today) / 86400000);
              return (
                <div key={b.id} className="arr-row" onClick={() => ctx.openModal ? ctx.openModal("bookingDetail", { bookingId: b.id }) : nav("apartment", b.aptId)}>
                  <DateBlock iso={b.start} />
                  <div className="grow" style={{ minWidth: 0 }}>
                    <div className="b500 flex center gap-1" style={{ whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>
                      {b.guestName} <Flag code={b.guestCountry} />
                    </div>
                    <div className="muted txt-xs">{apt.name} · {nightsBetween(b.start, b.end)} nights · {b.source}</div>
                  </div>
                  <div className="ta-r flex col" style={{ display: "flex", flexDirection: "column", alignItems: "flex-end" }}>
                    <span className="num b500">{fmtEUR(nightsBetween(b.start, b.end) * b.nightly)}</span>
                    <span className="muted txt-xs">in {days === 0 ? "today" : `${days}d`}</span>
                  </div>
                </div>
              );
            })}
          </div>
        </Card>

        <Card>
          <div className="card-head">
            <h3>Turnovers next 14 days</h3>
            <Pill>{turnovers.filter((t) => t.daysAway <= 14).length}</Pill>
            <div className="head-right"><button className="btn ghost sm" onClick={() => ctx.showToast && ctx.showToast("Limpieza solicitada al equipo")}><Icon name="plus" size={12} /> Book cleaner</button></div>
          </div>
          {turnovers.length === 0
            ? <Empty icon="check" title={tt("empty.nothingUrgent")} />
            : (
            <div className="flex col" style={{ display: "flex", flexDirection: "column" }}>
              {turnovers.slice(0, 5).map((tr, i) => {
                const apt = data.byId.apt(tr.aptId);
                return (
                  <div key={i} className="arr-row">
                    <div style={{ width: 34, height: 34, borderRadius: 8, overflow: "hidden", flexShrink: 0 }}>
                      <AptArchHero aptId={tr.aptId} />
                    </div>
                    <div className="grow" style={{ minWidth: 0 }}>
                      <div className="b500" style={{ whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{apt.name}</div>
                      <div className="muted txt-xs" style={{ whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>
                        {tr.kind === "same-day" ? `${tr.outGuest} → ${tr.inGuest}` : `${tr.outGuest} checks out`}
                      </div>
                    </div>
                    <Pill tone={tr.kind === "same-day" ? "danger" : "warn"}>
                      <span className="dot" />{tr.kind === "same-day" ? "Same-day" : "Clean"}
                    </Pill>
                    <span className="muted txt-xs num">{fmtDate(tr.date, { short: true })}</span>
                  </div>
                );
              })}
            </div>
          )}
        </Card>
      </div>
    </>
  );
}

// ───────────────────────── GUESTS TAB ─────────────────────────
function SummerGuestsTab({ ctx, bookings }) {
  const { data, nav } = ctx;
  const tt = ctx.tt || ((k) => k);
  const [query, setQuery] = React.useState("");
  const [statusFilter, setStatusFilter] = React.useState("all");

  const filtered = bookings
    .filter((b) => b.status !== "blocked")
    .filter((b) => statusFilter === "all" ? true : b.status === statusFilter)
    .filter((b) => !query || (b.guestName + " " + b.guestCountry).toLowerCase().includes(query.toLowerCase()))
    .sort((a, b) => a.start.localeCompare(b.start));

  const totalRevenue = filtered.filter((b) => b.status === "confirmed").reduce((s, b) => s + nightsBetween(b.start, b.end) * b.nightly, 0);

  return (
    <>
      <div className="flex center between gap-2" style={{ marginBottom: 14, flexWrap: "wrap" }}>
        <Tabs value={statusFilter} onChange={setStatusFilter} tabs={[
          { value: "all",       label: tt("sm.guests.tab.all") },
          { value: "confirmed", label: tt("sm.guests.tab.confirmed") },
          { value: "tentative", label: tt("sm.guests.tab.tentative") },
          { value: "resident",  label: tt("sm.guests.tab.resident") },
        ]} />
        <div className="flex center gap-2">
          <div className="searchbar" style={{ width: 240 }}>
            <Icon name="search" size={13} />
            <input placeholder={tt("sm.guests.searchPh")} value={query} onChange={(e) => setQuery(e.target.value)} />
          </div>
          <button className="btn primary" onClick={() => ctx.openModal && ctx.openModal("newBooking")}><Icon name="plus" size={13} /> {tt("sm.guests.add")}</button>
        </div>
      </div>

      <div className="grid-stat-4" style={{ marginBottom: 18 }}>
        <Stat icon="users" label={tt("sm.guests.stat.guests")} value={filtered.length}
              sub={<span>{tt("sm.guests.stat.guestsSub", { n: filtered.filter((b) => b.status === "confirmed").length })}</span>} />
        <Stat icon="calendar" label={tt("sm.guests.stat.nights")}
              value={filtered.filter((b) => b.status === "confirmed").reduce((s, b) => s + nightsBetween(b.start, b.end), 0)} />
        <Stat icon="euro" label={tt("sm.guests.stat.rev")} value={fmtEUR(totalRevenue)} />
        <Stat icon="upTrend" label={tt("sm.guests.stat.avg")} value={(() => {
          const conf = filtered.filter((b) => b.status === "confirmed" && b.nightly > 0);
          if (!conf.length) return "—";
          const total = conf.reduce((s, b) => s + nightsBetween(b.start, b.end) * b.nightly, 0);
          const nts = conf.reduce((s, b) => s + nightsBetween(b.start, b.end), 0);
          return fmtEUR(Math.round(total / nts));
        })()} />
      </div>

      <Card className="flush">
        <table className="table">
          <thead>
            <tr>
              <th>{tt("sm.guests.col.guest")}</th>
              <th>{tt("sm.guests.col.apt")}</th>
              <th>{tt("sm.guests.col.dates")}</th>
              <th className="num">{tt("sm.guests.col.nights")}</th>
              <th className="num">{tt("sm.guests.col.total")}</th>
              <th>{tt("sm.guests.col.source")}</th>
              <th>{tt("sm.guests.col.status")}</th>
            </tr>
          </thead>
          <tbody>
            {filtered.map((b) => {
              const apt = data.byId.apt(b.aptId);
              const nts = nightsBetween(b.start, b.end);
              const initials2 = b.guestName.split(/\s+|—|\(/).filter(Boolean).slice(0, 2).map((s) => s[0]).join("").toUpperCase();
              return (
                <tr key={b.id} onClick={() => ctx.openModal ? ctx.openModal("bookingDetail", { bookingId: b.id }) : nav("apartment", b.aptId)}>
                  <td>
                    <div className="flex center gap-3">
                      <div className="avatar">{initials2}</div>
                      <div>
                        <div className="b500 flex center gap-1">{b.guestName} <Flag code={b.guestCountry} /></div>
                        {b.note && <div className="muted txt-xs" style={{ maxWidth: 280, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{b.note}</div>}
                      </div>
                    </div>
                  </td>
                  <td>
                    <div className="b500">{apt.name}</div>
                    <div className="muted txt-xs">{apt.neighborhood}</div>
                  </td>
                  <td className="num">{fmtDate(b.start, { short: true })} → {fmtDate(b.end, { short: true })}</td>
                  <td className="num">{nts}</td>
                  <td className="num b500">{b.nightly ? fmtEUR(nts * b.nightly) : "—"}</td>
                  <td><Pill>{b.source}</Pill></td>
                  <td><StatusBadge status={b.status} /></td>
                </tr>
              );
            })}
            {filtered.length === 0 && <tr><td colSpan="7"><Empty icon="users" title={tt("empty.nothingHere")} /></td></tr>}
          </tbody>
        </table>
      </Card>
    </>
  );
}

// ───────────────────────── CONTRACTS TAB ─────────────────────────
function SummerContractsTab({ ctx, bookings }) {
  const { data, nav } = ctx;
  const tt = ctx.tt || ((k) => k);
  const list = bookings
    .filter((b) => b.status === "confirmed" || b.status === "tentative")
    .sort((a, b) => a.start.localeCompare(b.start));

  return (
    <>
      <div className="grid-2" style={{ marginBottom: 16, gap: 16 }}>
        <Card tinted>
          <div className="flex center gap-3">
            <div style={{ width: 40, height: 40, borderRadius: 10, background: "var(--ef-accent-soft)",
                          color: "var(--ef-accent-deep)", display: "flex", alignItems: "center", justifyContent: "center" }}>
              <Icon name="file" size={18} />
            </div>
            <div className="grow">
              <div className="b500">{list.length} short-stay contracts</div>
              <div className="muted txt-xs">{list.filter((b)=>b.status==="confirmed").length} confirmed, {list.filter((b)=>b.status==="tentative").length} tentative</div>
            </div>
            <button className="btn sm" onClick={() => ctx.openModal && ctx.openModal("newBooking")}><Icon name="plus" size={12} /> New contract</button>
          </div>
        </Card>
        <Card tinted>
          <div className="flex center gap-3">
            <div style={{ width: 40, height: 40, borderRadius: 10, background: "var(--ef-info-soft)",
                          color: "var(--ef-info)", display: "flex", alignItems: "center", justifyContent: "center" }}>
              <Icon name="check" size={18} />
            </div>
            <div className="grow">
              <div className="b500">Deposits & house rules</div>
              <div className="muted txt-xs">All contracts use the standard short-stay template (v3, May 2026)</div>
            </div>
            <button className="btn sm ghost">Open template</button>
          </div>
        </Card>
      </div>

      <div className="grid-2" style={{ gap: 16 }}>
        {list.map((b) => <ContractCard key={b.id} booking={b} apt={data.byId.apt(b.aptId)} onOpen={() => nav("apartment", b.aptId)} />)}
        {list.length === 0 && <div style={{ gridColumn: "1 / -1" }}><Empty icon="file" title={tt("empty.nothingHere")} /></div>}
      </div>
    </>
  );
}

function ContractCard({ booking, apt, onOpen }) {
  const nts = nightsBetween(booking.start, booking.end);
  const total = nts * booking.nightly;
  const initials2 = booking.guestName.split(/\s+|—|\(/).filter(Boolean).slice(0, 2).map((s) => s[0]).join("").toUpperCase();
  return (
    <Card className="contract-card" onClick={onOpen} style={{ cursor: "pointer" }}>
      <div className="flex center between" style={{ marginBottom: 14 }}>
        <div className="flex center gap-2">
          <Icon name="file" size={14} className="muted" />
          <span className="muted txt-xs" style={{ letterSpacing: "0.06em", textTransform: "uppercase", fontWeight: 600 }}>
            Contract · {booking.id.toUpperCase()}
          </span>
        </div>
        <StatusBadge status={booking.status} />
      </div>
      <div className="flex center gap-3" style={{ marginBottom: 16 }}>
        <div className="avatar lg">{initials2}</div>
        <div className="grow" style={{ minWidth: 0 }}>
          <div className="b500 flex center gap-2" style={{ fontSize: 15 }}>{booking.guestName} <Flag code={booking.guestCountry} /></div>
          <div className="muted txt-sm">{apt.name} · {apt.neighborhood}</div>
        </div>
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10, marginBottom: 14 }}>
        <ContractRow label="Check-in" value={fmtDate(booking.start)} icon="calendar" />
        <ContractRow label="Check-out" value={fmtDate(booking.end)} icon="calendar" />
        <ContractRow label="Nights" value={`${nts}`} />
        <ContractRow label="Nightly" value={fmtEUR(booking.nightly)} />
      </div>
      <div className="contract-total">
        <span className="muted txt-sm">Total · {booking.source}</span>
        <span className="num b500" style={{ fontSize: 20 }}>{fmtEUR(total)}</span>
      </div>
      {booking.note && (
        <div style={{ marginTop: 12, padding: 10, background: "var(--ef-bg-soft)", borderRadius: 8, fontSize: 12.5, color: "var(--ef-ink-2)" }}>
          <Icon name="flag" size={11} className="muted" style={{ marginRight: 6, verticalAlign: -1 }} />
          {booking.note}
        </div>
      )}
    </Card>
  );
}

function ContractRow({ label, value, icon }) {
  return (
    <div>
      <div className="muted txt-xs" style={{ letterSpacing: "0.04em", textTransform: "uppercase", fontWeight: 500, fontSize: 10.5 }}>
        {icon && <Icon name={icon} size={10} style={{ marginRight: 4, verticalAlign: -1 }} />}{label}
      </div>
      <div className="b500" style={{ marginTop: 2 }}>{value}</div>
    </div>
  );
}

// ───────────────────────── MONEY TAB ─────────────────────────
function SummerMoneyTab({ ctx, bookings, confirmed, stats }) {
  const { data, nav } = ctx;
  const tt = ctx.tt || ((k) => k);

  // Per-apartment summer revenue + expenses.
  const perApt = data.apartments.map((a) => {
    const aptBks = bookings.filter((b) => b.aptId === a.id && (b.status === "confirmed" || b.status === "tentative") && b.nightly > 0);
    const nts = aptBks.reduce((s, b) => s + nightsBetween(b.start, b.end), 0);
    const rev = aptBks.reduce((s, b) => s + nightsBetween(b.start, b.end) * b.nightly, 0);
    // Summer expenses: cleaning + supplies tied to this flat in May-Aug.
    const ex = data.expenses.filter((e) => e.aptId === a.id &&
      (e.category === "cleaning" || e.category === "supplies") &&
      e.date >= "2026-05-01" && e.date < "2026-09-01")
      .reduce((s, e) => s + e.amount, 0);
    return { apt: a, bookings: aptBks.length, nights: nts, revenue: rev, expenses: ex, net: rev - ex };
  });
  const totalRev = perApt.reduce((s, p) => s + p.revenue, 0);
  const totalEx = perApt.reduce((s, p) => s + p.expenses, 0);
  const totalNet = totalRev - totalEx;
  const maxRev = Math.max(...perApt.map((p) => p.revenue), 1);

  // Source breakdown
  const sources = confirmed.reduce((acc, b) => { acc[b.source] = (acc[b.source] || 0) + nightsBetween(b.start, b.end) * b.nightly; return acc; }, {});
  const sumSources = Object.values(sources).reduce((s, n) => s + n, 0) || 1;

  // Expense list for this period
  const summerExpenses = data.expenses
    .filter((e) => (e.category === "cleaning" || e.category === "supplies") && e.date >= "2026-05-01" && e.date < "2026-09-01")
    .sort((a, b) => b.date.localeCompare(a.date));

  return (
    <>
      <div className="grid-stat-4" style={{ marginBottom: 18 }}>
        <Stat icon="upTrend" label="Summer revenue" value={fmtEUR(totalRev)}
              sub={<span>{confirmed.length} stays</span>} />
        <Stat icon="downTrend" label="Summer expenses" value={fmtEUR(totalEx)}
              sub={<span>Cleaning + supplies</span>} />
        <Stat icon="euro" label="Summer net" value={fmtEUR(totalNet, { sign: totalNet > 0 })}
              sub={<span style={{ color: totalNet >= 0 ? "var(--ef-accent-deep)" : "var(--ef-danger)" }}>
                {Math.round((totalNet / Math.max(totalRev, 1)) * 100)}% margin
              </span>} />
        <Stat icon="calendar" label="Avg per stay" value={fmtEUR(confirmed.length ? totalRev / confirmed.length : 0)} />
      </div>

      <div className="split-23" style={{ gap: 16, marginBottom: 24 }}>
        <Card>
          <div className="card-head">
            <h3>Revenue by apartment</h3>
            <div className="muted txt-sm head-right">Confirmed + tentative</div>
          </div>
          <div className="flex col" style={{ display: "flex", flexDirection: "column", gap: 16 }}>
            {perApt.map((p) => (
              <div key={p.apt.id} onClick={() => nav("apartment", p.apt.id)} style={{ cursor: "pointer" }}>
                <div className="flex between" style={{ marginBottom: 6 }}>
                  <div className="flex center gap-2">
                    <div style={{ width: 22, height: 22, borderRadius: 5, overflow: "hidden" }}><AptArchHero aptId={p.apt.id} /></div>
                    <span className="b500">{p.apt.name}</span>
                    <span className="muted txt-xs">· {p.nights}n · {p.bookings} stays</span>
                  </div>
                  <div className="flex center gap-3">
                    <span className="num b500">{fmtEUR(p.revenue)}</span>
                    <Pill tone={p.net >= 0 ? "positive" : "danger"}>
                      {fmtEUR(p.net, { sign: p.net > 0 })} net
                    </Pill>
                  </div>
                </div>
                <div style={{ position: "relative", height: 10, borderRadius: 999, background: "var(--ef-bg-soft)", overflow: "hidden" }}>
                  <div style={{ position: "absolute", top: 0, left: 0, bottom: 0, width: `${(p.revenue / maxRev) * 100}%`, background: "var(--ef-accent)" }} />
                </div>
              </div>
            ))}
          </div>
        </Card>

        <Card>
          <div className="card-head"><h3>Source mix</h3></div>
          <div className="flex col" style={{ display: "flex", flexDirection: "column", gap: 14 }}>
            <SourceStack sources={Object.fromEntries(Object.entries(sources).map(([k, v]) => [k, v]))} total={sumSources} />
            {Object.entries(sources).sort((a, b) => b[1] - a[1]).map(([src, v]) => (
              <div key={src} className="flex center gap-3">
                <span style={{ width: 10, height: 10, borderRadius: 3, background: sourceColor(src), flexShrink: 0 }} />
                <span className="grow">{src}</span>
                <span className="num b500">{fmtEUR(v)}</span>
                <span className="muted txt-xs num" style={{ width: 44, textAlign: "right" }}>{Math.round((v / sumSources) * 100)}%</span>
              </div>
            ))}
          </div>
        </Card>
      </div>

      <div className="grid-2" style={{ gap: 16 }}>
        <Card className="flush">
          <div style={{ padding: "16px 20px", borderBottom: "1px solid var(--ef-line)", display: "flex", alignItems: "center" }}>
            <h3>Summer-specific expenses</h3>
            <span className="muted txt-sm" style={{ marginLeft: 12 }}>Cleaning, linens, turnover supplies</span>
            <button className="btn sm" style={{ marginLeft: "auto" }} onClick={() => ctx.openModal && ctx.openModal("addExpense")}><Icon name="plus" size={12} /> Add expense</button>
          </div>
          <table className="table">
            <thead>
              <tr><th>Date</th><th>Label</th><th>Apartment</th><th className="num">Amount</th></tr>
            </thead>
            <tbody>
              {summerExpenses.map((e) => (
                <tr key={e.id} onClick={() => nav("apartment", e.aptId)}>
                  <td className="num">{fmtDate(e.date, { short: true })}</td>
                  <td>
                    <div className="b500">{e.label}</div>
                    <div className="muted txt-xs">{e.vendor}</div>
                  </td>
                  <td className="muted">{data.byId.apt(e.aptId).name}</td>
                  <td className="num b500">−{fmtEUR(e.amount)}</td>
                </tr>
              ))}
              {summerExpenses.length === 0 && <tr><td colSpan="4"><Empty icon="receipt" title={tt("ad.exp.empty")} /></td></tr>}
            </tbody>
          </table>
        </Card>

        <Card>
          <div className="card-head"><h3>Bookings ledger</h3><div className="muted txt-sm head-right">Revenue per confirmed stay</div></div>
          <table className="table" style={{ marginTop: -10 }}>
            <thead>
              <tr><th>Stay</th><th className="num">Nights</th><th className="num">Total</th></tr>
            </thead>
            <tbody>
              {confirmed.sort((a, b) => a.start.localeCompare(b.start)).map((b) => {
                const apt = data.byId.apt(b.aptId);
                const nts = nightsBetween(b.start, b.end);
                return (
                  <tr key={b.id}>
                    <td>
                      <div className="b500 flex center gap-1" style={{ whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", maxWidth: 200 }}>
                        {b.guestName} <Flag code={b.guestCountry} />
                      </div>
                      <div className="muted txt-xs">{apt.name} · {fmtDate(b.start, { short: true })}</div>
                    </td>
                    <td className="num">{nts}</td>
                    <td className="num b500">{fmtEUR(nts * b.nightly)}</td>
                  </tr>
                );
              })}
              <tr style={{ background: "var(--ef-bg-soft)" }}>
                <td className="b500">Total</td>
                <td className="num b500">{confirmed.reduce((s, b) => s + nightsBetween(b.start, b.end), 0)}</td>
                <td className="num b500">{fmtEUR(confirmed.reduce((s, b) => s + nightsBetween(b.start, b.end) * b.nightly, 0))}</td>
              </tr>
            </tbody>
          </table>
        </Card>
      </div>
    </>
  );
}

// ───────────────────────── GANTT ─────────────────────────
// Renders a multi-month Gantt with apartments as rows and bookings as pills.
// Accepts an array of "YYYY-MM" strings for the months to display.
function SummerGantt({ ctx, months, apartments, bookings, todayISO }) {
  const dayWidth = 28;
  const labelCol = 180;
  const rowHeight = 64;

  const segments = months.map((m) => {
    const [y, mn] = m.split("-").map(Number);
    return { y, m: mn, days: new Date(y, mn, 0).getDate(), start: new Date(y, mn - 1, 1) };
  });
  const totalDays = segments.reduce((s, seg) => s + seg.days, 0);
  const rangeStart = segments[0].start;
  const rangeEnd = new Date(segments.at(-1).y, segments.at(-1).m, 1);
  const monthNames = ["January","February","March","April","May","June","July","August","September","October","November","December"];

  return (
    <div style={{ minWidth: labelCol + totalDays * dayWidth + 24 }}>
      <div style={{ display: "flex", position: "sticky", top: 0, background: "var(--ef-bg-soft)", borderBottom: "1px solid var(--ef-line)", zIndex: 2 }}>
        <div style={{ width: labelCol, padding: "10px 16px", borderRight: "1px solid var(--ef-line)" }}>
          <div className="muted txt-xs" style={{ textTransform: "uppercase", letterSpacing: "0.06em", fontWeight: 600, fontSize: 10.5 }}>Apartment</div>
          <div className="b500 txt-sm" style={{ marginTop: 2 }}>{apartments.length} flats</div>
        </div>
        <div>
          <div style={{ display: "flex", borderBottom: "1px solid var(--ef-line)" }}>
            {segments.map((seg, i) => (
              <div key={i} style={{ width: seg.days * dayWidth, padding: "10px 14px", borderRight: i < segments.length - 1 ? "1px solid var(--ef-line-strong)" : "0" }}>
                <div className="display" style={{ fontWeight: 600, fontSize: 14 }}>{monthNames[seg.m - 1]} <span className="muted" style={{ fontWeight: 400 }}>{seg.y}</span></div>
              </div>
            ))}
          </div>
          <div style={{ display: "flex" }}>
            {segments.flatMap((seg) =>
              Array.from({ length: seg.days }, (_, i) => {
                const d = new Date(seg.y, seg.m - 1, i + 1);
                const isWeekend = d.getDay() === 0 || d.getDay() === 6;
                const isToday = ArcoData.ISO(d) === todayISO;
                return (
                  <div key={`${seg.y}-${seg.m}-${i}`} style={{
                    width: dayWidth, padding: "6px 0 4px", textAlign: "center",
                    background: isWeekend ? "var(--ef-bg-soft)" : "transparent",
                    borderRight: "1px solid var(--ef-line)",
                  }}>
                    <div className="num" style={{ fontSize: 11, fontWeight: isToday ? 600 : 500, color: isToday ? "var(--ef-accent-deep)" : "var(--ef-ink-2)" }}>{i + 1}</div>
                    <div className="muted" style={{ fontSize: 9, letterSpacing: "0.04em" }}>{"SMTWTFS"[d.getDay()]}</div>
                  </div>
                );
              })
            )}
          </div>
        </div>
      </div>

      {apartments.map((a) => {
        const aptBookings = bookings.filter((b) => b.aptId === a.id);
        const seasonNts = aptBookings.filter((b) => b.status === "confirmed" && b.nightly > 0 && b.start >= "2026-06-01" && b.start < "2026-09-01").reduce((s, b) => s + nightsBetween(b.start, b.end), 0);
        const seasonRev = aptBookings.filter((b) => b.status === "confirmed" && b.nightly > 0 && b.start >= "2026-06-01" && b.start < "2026-09-01").reduce((s, b) => s + nightsBetween(b.start, b.end) * b.nightly, 0);
        return (
          <div key={a.id} style={{ display: "flex", borderBottom: "1px solid var(--ef-line)", position: "relative", minHeight: rowHeight }}>
            <div onClick={() => ctx?.nav && ctx.nav("apartment", a.id)}
                 style={{ width: labelCol, padding: "10px 16px", borderRight: "1px solid var(--ef-line)", display: "flex", gap: 10, alignItems: "center", background: "var(--ef-bg)", cursor: "pointer" }}>
              <div style={{ width: 32, height: 32, borderRadius: 7, overflow: "hidden", flexShrink: 0 }}>
                <AptArchHero aptId={a.id} />
              </div>
              <div className="grow" style={{ minWidth: 0 }}>
                <div className="b500" style={{ fontSize: 12.5, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{a.name}</div>
                <div className="muted txt-xs" style={{ whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>
                  {seasonNts}n · {fmtEUR(seasonRev)}
                </div>
              </div>
            </div>
            <div style={{ display: "flex", position: "relative", minHeight: rowHeight }}>
              {segments.flatMap((seg, segIdx) =>
                Array.from({ length: seg.days }, (_, i) => {
                  const d = new Date(seg.y, seg.m - 1, i + 1);
                  const isWeekend = d.getDay() === 0 || d.getDay() === 6;
                  const isToday = ArcoData.ISO(d) === todayISO;
                  return (
                    <div key={`${seg.y}-${seg.m}-${i}`} style={{
                      width: dayWidth,
                      borderRight: i === seg.days - 1 && segIdx < segments.length - 1 ? "1px solid var(--ef-line-strong)" : "1px solid var(--ef-line)",
                      background: isWeekend ? "var(--ef-bg-soft)" : "transparent",
                      position: "relative",
                    }}>
                      {isToday && <div style={{ position: "absolute", top: 0, bottom: 0, left: "50%", width: 1, background: "var(--ef-accent)", opacity: 0.6 }} />}
                    </div>
                  );
                })
              )}
              {aptBookings.map((b) => {
                const bStart = new Date(b.start);
                const bEnd = new Date(b.end);
                if (bEnd <= rangeStart || bStart >= rangeEnd) return null;
                const start = bStart < rangeStart ? rangeStart : bStart;
                const end = bEnd > rangeEnd ? rangeEnd : bEnd;
                const offsetDays = (start - rangeStart) / 86400000;
                const lenDays = (end - start) / 86400000;
                if (lenDays <= 0) return null;
                const left = offsetDays * dayWidth + 3;
                const width = lenDays * dayWidth - 6;
                const palette = bookingPalette(b);
                return (
                  <div key={b.id} className="booking-pill"
                       onClick={() => ctx?.openModal && ctx.openModal("bookingDetail", { bookingId: b.id })}
                       style={{
                    position: "absolute", top: 10, left, width,
                    height: rowHeight - 20,
                    background: palette.bg, color: palette.fg,
                    borderRadius: rowHeight - 20,
                    padding: "0 12px",
                    display: "flex", alignItems: "center", gap: 8,
                    fontSize: 11.5, fontWeight: 500, overflow: "hidden",
                    boxShadow: "var(--ef-shadow-card-sm)", cursor: "pointer",
                    border: palette.border,
                  }} title={`${b.guestName} · ${fmtDate(b.start, { short: true })} → ${fmtDate(b.end, { short: true })} · ${b.source}`}>
                    {width > 60 && <span style={{ fontSize: 12 }}>{FLAGS[b.guestCountry] || "🌍"}</span>}
                    <span style={{ flex: 1, minWidth: 0, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>
                      {b.guestName}
                    </span>
                    {width > 100 && b.nightly > 0 && (
                      <span className="num" style={{ fontSize: 10.5, opacity: 0.8 }}>{nightsBetween(b.start, b.end)}n</span>
                    )}
                  </div>
                );
              })}
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ───────────────────────── HELPERS ─────────────────────────
function bookingPalette(b) {
  if (b.status === "tentative") return { bg: "var(--ef-warn-soft)", fg: "var(--ef-warn)", border: "1px dashed var(--ef-warn)" };
  if (b.status === "blocked")   return { bg: "var(--ef-bg-soft)", fg: "var(--ef-muted)", border: "1px solid var(--ef-line-strong)" };
  if (b.status === "resident")  return { bg: "var(--ef-info)", fg: "var(--ef-bg)", border: "1px solid var(--ef-info)" };
  return { bg: "var(--ef-accent)", fg: "#fff", border: "1px solid var(--ef-accent)" };
}

function computeTurnovers(bookings) {
  const today = ArcoData.today;
  const byApt = {};
  for (const b of bookings) {
    if (b.nightly === 0) continue;
    byApt[b.aptId] = byApt[b.aptId] || [];
    byApt[b.aptId].push(b);
  }
  const out = [];
  for (const aptId in byApt) {
    const arr = byApt[aptId].sort((a, b) => a.end.localeCompare(b.end));
    for (const dep of arr) {
      const depDate = new Date(dep.end);
      if (depDate < today) continue;
      const daysAway = Math.round((depDate - today) / 86400000);
      if (daysAway > 21) continue;
      const next = arr.find((b) => b.start >= dep.end && b !== dep);
      const sameDay = next && next.start === dep.end;
      out.push({
        aptId,
        date: dep.end,
        outGuest: dep.guestName.split(/—|\(/)[0].trim(),
        inGuest: next ? next.guestName.split(/—|\(/)[0].trim() : null,
        kind: sameDay ? "same-day" : "cleaning",
        daysAway,
      });
    }
  }
  return out.sort((a, b) => a.date.localeCompare(b.date));
}

function DateBlock({ iso }) {
  const d = new Date(iso);
  const month = ["JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"][d.getMonth()];
  return (
    <div style={{
      width: 42, flexShrink: 0,
      background: "var(--ef-accent-soft)", color: "var(--ef-accent-deep)",
      borderRadius: 8, padding: "6px 0", textAlign: "center",
      border: "1px solid var(--ef-accent-soft)",
    }}>
      <div className="num b500" style={{ fontSize: 18, lineHeight: 1 }}>{d.getDate()}</div>
      <div style={{ fontSize: 9, fontWeight: 600, letterSpacing: "0.08em", marginTop: 2 }}>{month}</div>
    </div>
  );
}

function sourceColor(src) {
  const map = {
    Direct: "var(--ef-accent)",
    Airbnb: "var(--ef-danger)",
    Booking: "var(--ef-info)",
    Resident: "var(--ef-info)",
    Block: "var(--ef-muted)",
  };
  return map[src] || "var(--ef-muted)";
}

function SourceStack({ sources, total }) {
  const ordered = Object.entries(sources).sort((a, b) => b[1] - a[1]);
  return (
    <div style={{ display: "flex", height: 12, borderRadius: 999, overflow: "hidden", background: "var(--ef-bg-soft)" }}>
      {ordered.map(([src, n]) => (
        <div key={src} title={`${src}: ${n}`} style={{ flex: n, background: sourceColor(src) }} />
      ))}
    </div>
  );
}

// ───────────────────────── STYLES ─────────────────────────
const summerSectionStyles = `
  .arr-row {
    display: flex; align-items: center; gap: 12px;
    padding: 12px 0;
    border-bottom: 1px solid var(--ef-line);
    cursor: pointer;
  }
  .arr-row:last-child { border-bottom: 0; }
  .arr-row:hover { background: var(--ef-bg-soft); margin: 0 -8px; padding: 12px 8px; border-radius: 8px; }

  .contract-card { transition: transform .12s, box-shadow .12s, border-color .12s; }
  .contract-card:hover { border-color: var(--ef-line-strong); box-shadow: var(--ef-shadow-card); transform: translateY(-1px); }

  .contract-total {
    display: flex; align-items: baseline; justify-content: space-between;
    padding: 10px 12px;
    background: var(--ef-accent-soft);
    color: var(--ef-accent-deep);
    border-radius: 10px;
  }
  [

  .booking-pill:hover { transform: translateY(-1px); box-shadow: var(--ef-shadow-card); transition: transform .15s, box-shadow .15s; }
`;

window.SummerSection = SummerSection;
