/* ============================================================
   PURE SPA — AGENDA · Calendario  /admin/calendar
   Vistas Día / Semana / Mes · disponibilidad por camilla.
   ============================================================ */
const OPEN_H = 10, CLOSE_H = 19;
const OPEN_MIN = OPEN_H * 60, CLOSE_MIN = CLOSE_H * 60;
const PXMIN = 1.25; // px por minuto en vista día
const minOf = (t) => { const [h, m] = t.split(":").map(Number); return h * 60 + m; };
const isoOf = (d) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
const parseIso = (s) => { const [y, m, d] = s.split("-").map(Number); return new Date(y, m - 1, d); };
const MESES = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"];
const DIASC = ["Lun", "Mar", "Mié", "Jue", "Vie", "Sáb", "Dom"];

function CalendarView() {
  const { version, openModal, can } = useApp();
  const [view, setView] = useState("day");
  const [date, setDate] = useState(TODAY);
  const [bedFilter, setBedFilter] = useState("all");
  const [statusFilter, setStatusFilter] = useState("");

  const beds = PureApi.getBeds().filter((b) => b.active);
  const shiftDay = (n) => { const d = parseIso(date); d.setDate(d.getDate() + n); setDate(isoOf(d)); };
  const shiftWeek = (n) => { const d = parseIso(date); d.setDate(d.getDate() + n * 7); setDate(isoOf(d)); };
  const shiftMonth = (n) => { const d = parseIso(date); d.setMonth(d.getMonth() + n); setDate(isoOf(d)); };

  const titleFor = () => {
    const d = parseIso(date);
    if (view === "month") return `${MESES[d.getMonth()]} ${d.getFullYear()}`;
    if (view === "week") { const wk = weekDays(date); return `${wk[0].getDate()} – ${wk[5].getDate()} ${MESES[wk[5].getMonth()]}`; }
    return fullDate(date);
  };
  const shift = (n) => view === "month" ? shiftMonth(n) : view === "week" ? shiftWeek(n) : shiftDay(n);

  return (
    <div>
      <PageHead eyebrow="Agenda" title="Agenda interna" sub="Disponibilidad por camilla, en tiempo real.">
        {can("booking:create") && <Button variant="primary" size="sm" onClick={() => openModal("newBooking", { date })}><Icon name="Plus" size={14} color={C.espresso} style={{ marginRight: 4 }} />Nueva reserva</Button>}
        {can("booking:move") && <Button variant="secondary" size="sm" onClick={() => openModal("block", { date })}><Icon name="Ban" size={14} color={C.espresso} style={{ marginRight: 4 }} />Bloquear horario</Button>}
      </PageHead>

      {/* barra de control */}
      <div style={{ display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap", marginBottom: 18 }}>
        <div style={{ display: "flex", background: C.white, border: `1px solid ${C.line}`, borderRadius: 999, padding: 3 }}>
          {[["day", "Día"], ["week", "Semana"], ["month", "Mes"]].map(([k, l]) => (
            <button key={k} onClick={() => setView(k)} style={{ border: "none", cursor: "pointer", borderRadius: 999,
              padding: "8px 18px", fontFamily: "var(--font-body)", fontSize: 11, fontWeight: 600, letterSpacing: "0.08em",
              textTransform: "uppercase", background: view === k ? C.espresso : "transparent", color: view === k ? C.ivory : C.taupe }}>{l}</button>
          ))}
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
          <button onClick={() => shift(-1)} style={navBtn}><Icon name="ChevronLeft" size={16} color={C.taupe} /></button>
          <div style={{ fontFamily: "var(--font-display)", fontSize: 19, color: C.espresso, minWidth: 150, textAlign: "center" }}>{titleFor()}</div>
          <button onClick={() => shift(1)} style={navBtn}><Icon name="ChevronRight" size={16} color={C.taupe} /></button>
          <button onClick={() => setDate(TODAY)} style={{ ...navBtn, width: "auto", padding: "0 14px", fontFamily: "var(--font-body)", fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: C.taupe }}>Hoy</button>
        </div>
        <div style={{ flex: 1 }} />
        <div style={{ minWidth: 140 }}>
          <Select value={bedFilter} onChange={setBedFilter} options={[{ value: "all", label: "Todas las camillas" }, ...beds.map((b) => ({ value: b.id, label: b.name }))]} />
        </div>
        <div style={{ minWidth: 150 }}>
          <Select value={statusFilter} onChange={setStatusFilter} placeholder="Todos los estados"
            options={Object.keys(STATUS).filter((s) => s !== "blocked").map((s) => ({ value: s, label: STATUS[s].label }))} />
        </div>
      </div>

      {view === "day" && <DayGrid date={date} beds={beds} bedFilter={bedFilter} statusFilter={statusFilter} version={version} openModal={openModal} />}
      {view === "week" && <WeekGrid date={date} bedFilter={bedFilter} statusFilter={statusFilter} version={version} openModal={openModal} onPickDay={(d) => { setDate(d); setView("day"); }} />}
      {view === "month" && <MonthGrid date={date} version={version} onPickDay={(d) => { setDate(d); setView("day"); }} />}
    </div>
  );
}

function weekDays(iso) {
  const d = parseIso(iso);
  const dow = (d.getDay() + 6) % 7; // 0 = lunes
  const mon = new Date(d); mon.setDate(d.getDate() - dow);
  return Array.from({ length: 6 }, (_, i) => { const x = new Date(mon); x.setDate(mon.getDate() + i); return x; }); // Lun-Sáb
}

/* ---------- VISTA DÍA ---------- */
function DayGrid({ date, beds, bedFilter, statusFilter, version, openModal }) {
  const cols = beds.filter((b) => bedFilter === "all" || b.id === bedFilter);
  const height = (CLOSE_MIN - OPEN_MIN) * PXMIN;
  const hours = [];
  for (let h = OPEN_H; h <= CLOSE_H; h++) hours.push(h);
  const allBk = PureApi.getBookings({ date }).filter((b) => b.status !== "cancelled" && (!statusFilter || b.status === statusFilter));
  const blocks = PureApi.getBlocks({ date });

  return (
    <Card pad={0} style={{ overflow: "hidden" }}>
      <div style={{ display: "flex", borderBottom: `1px solid ${C.line}` }}>
        <div style={{ width: 58, flexShrink: 0 }} />
        {cols.map((bed) => (
          <div key={bed.id} style={{ flex: 1, padding: "13px 16px", borderLeft: `1px solid ${C.line}`, display: "flex", alignItems: "center", gap: 9 }}>
            <span style={{ width: 9, height: 9, borderRadius: 999, background: C.gold }} />
            <span style={{ fontFamily: "var(--font-display)", fontSize: 17, color: C.espresso }}>{bed.name}</span>
            <span style={{ fontFamily: "var(--font-body)", fontSize: 10, color: C.taupe, marginLeft: "auto" }}>{bed.code}</span>
          </div>
        ))}
      </div>
      <div style={{ display: "flex", position: "relative" }}>
        {/* horas */}
        <div style={{ width: 58, flexShrink: 0, position: "relative", height }}>
          {hours.map((h) => (
            <div key={h} style={{ position: "absolute", top: (h * 60 - OPEN_MIN) * PXMIN - 7, right: 8,
              fontFamily: "var(--font-body)", fontSize: 11, color: C.taupe }}>{String(h).padStart(2, "0")}:00</div>
          ))}
        </div>
        {cols.map((bed) => {
          const bk = allBk.filter((b) => b.bedId === bed.id);
          const bedBlocks = blocks.filter((b) => b.bedId === "all" || b.bedId === bed.id);
          return (
            <div key={bed.id} style={{ flex: 1, position: "relative", height, borderLeft: `1px solid ${C.line}` }}>
              {hours.map((h) => (
                <div key={h} style={{ position: "absolute", top: (h * 60 - OPEN_MIN) * PXMIN, left: 0, right: 0, borderTop: `1px solid ${C.ivoryDeep}` }} />
              ))}
              {bedBlocks.map((bl) => {
                const top = (minOf(bl.start) - OPEN_MIN) * PXMIN;
                const hgt = (minOf(bl.end) - minOf(bl.start)) * PXMIN;
                return (
                  <div key={bl.id} style={{ position: "absolute", top, left: 6, right: 6, height: hgt - 3,
                    background: "repeating-linear-gradient(45deg, #EAE6DF, #EAE6DF 8px, #E3DED4 8px, #E3DED4 16px)",
                    border: `1px solid #D8D0C2`, borderRadius: 8, padding: "6px 10px", overflow: "hidden" }}>
                    <div style={{ fontFamily: "var(--font-body)", fontSize: 10.5, fontWeight: 600, color: "#6E6557", display: "flex", alignItems: "center", gap: 5 }}>
                      <Icon name="Ban" size={12} color="#6E6557" />{bl.reason}
                    </div>
                    <div style={{ fontFamily: "var(--font-body)", fontSize: 10, color: "#8C8273" }}>{bl.start}–{bl.end}</div>
                  </div>
                );
              })}
              {bk.map((b) => {
                const svc = svcOf(b);
                const span = svc ? svc.duration + svc.cleanup : 60;
                const top = (minOf(b.start) - OPEN_MIN) * PXMIN;
                const hgt = span * PXMIN;
                const st = STATUS[b.status];
                return (
                  <button key={b.id} onClick={() => openModal("detail", { id: b.id })} style={{ position: "absolute", top: top + 1, left: 6, right: 6, height: hgt - 3,
                    background: st.bg, borderLeft: `3px solid ${st.dot}`, borderRadius: 8, padding: "7px 11px", cursor: "pointer",
                    textAlign: "left", border: "none", borderLeftWidth: 3, borderLeftStyle: "solid", borderLeftColor: st.dot, overflow: "hidden",
                    boxShadow: "0 1px 4px rgba(43,37,32,0.06)", display: "flex", flexDirection: "column", gap: 2 }}>
                    <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 6 }}>
                      <span style={{ fontFamily: "var(--font-body)", fontSize: 11.5, fontWeight: 600, color: st.fg, whiteSpace: "nowrap" }}>{b.start}–{addMin(b.start, span)}</span>
                      <span style={{ width: 7, height: 7, borderRadius: 999, background: st.dot, flexShrink: 0 }} />
                    </div>
                    <div style={{ fontFamily: "var(--font-body)", fontSize: 12.5, fontWeight: 500, color: C.espresso, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{custName(b)}</div>
                    {hgt > 58 && <div style={{ fontFamily: "var(--font-body)", fontSize: 10.5, fontWeight: 300, color: C.taupe, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{b._svcName}</div>}
                    {hgt > 84 && <div style={{ fontFamily: "var(--font-body)", fontSize: 10, fontWeight: 300, color: C.taupe }}>{custPhone(b)}</div>}
                  </button>
                );
              })}
            </div>
          );
        })}
      </div>
    </Card>
  );
}

/* ---------- VISTA SEMANA ---------- */
function WeekGrid({ date, bedFilter, statusFilter, version, openModal, onPickDay }) {
  const days = weekDays(date);
  const beds = PureApi.getBeds().filter((b) => b.active);
  return (
    <div style={{ display: "grid", gridTemplateColumns: "repeat(6, 1fr)", gap: 10 }} className="pu-week">
      {days.map((d) => {
        const iso = isoOf(d);
        const bk = PureApi.getBookings({ date: iso }).filter((b) => b.status !== "cancelled" && (!statusFilter || b.status === statusFilter) && (bedFilter === "all" || b.bedId === bedFilter)).sort((a, b) => a.start.localeCompare(b.start));
        const isToday = iso === TODAY;
        // ocupación
        const total = (CLOSE_MIN - OPEN_MIN) * beds.length;
        const used = bk.filter((b) => ["confirmed", "paid", "completed", "pending_payment", "pending_confirmation"].includes(b.status)).reduce((s, b) => { const sv = svcOf(b); return s + (sv ? sv.duration + sv.cleanup : 0); }, 0);
        const pct = Math.min(100, Math.round((used / total) * 100));
        return (
          <Card key={iso} pad={0} style={{ minHeight: 320, display: "flex", flexDirection: "column", border: isToday ? `1.5px solid ${C.gold}` : `1px solid ${C.line}` }}>
            <button onClick={() => onPickDay(iso)} style={{ padding: "12px 12px 10px", borderBottom: `1px solid ${C.line}`, cursor: "pointer", background: isToday ? C.gold15 : "transparent", border: "none", textAlign: "left" }}>
              <div style={{ fontFamily: "var(--font-body)", fontSize: 9.5, fontWeight: 600, letterSpacing: "0.1em", textTransform: "uppercase", color: isToday ? C.goldDeep : C.taupe }}>{DIASC[(d.getDay() + 6) % 7]}</div>
              <div style={{ fontFamily: "var(--font-display)", fontSize: 24, color: C.espresso, lineHeight: 1 }}>{d.getDate()}</div>
              <div style={{ marginTop: 8, height: 5, borderRadius: 999, background: C.ivoryDeep, overflow: "hidden" }}>
                <div style={{ width: pct + "%", height: "100%", background: `linear-gradient(90deg,${C.champagne},${C.gold})` }} />
              </div>
              <div style={{ fontFamily: "var(--font-body)", fontSize: 9.5, color: C.taupe, marginTop: 4 }}>{bk.length} reserva{bk.length !== 1 ? "s" : ""} · {pct}%</div>
            </button>
            <div style={{ padding: 8, display: "flex", flexDirection: "column", gap: 6, overflowY: "auto", flex: 1 }}>
              {bk.map((b) => {
                const st = STATUS[b.status];
                return (
                  <button key={b.id} onClick={() => openModal("detail", { id: b.id })} style={{ textAlign: "left", cursor: "pointer", background: st.bg, borderLeft: `3px solid ${st.dot}`, borderRadius: 6, padding: "6px 8px", border: "none" }}>
                    <div style={{ fontFamily: "var(--font-body)", fontSize: 11, fontWeight: 600, color: st.fg }}>{b.start}</div>
                    <div style={{ fontFamily: "var(--font-body)", fontSize: 11, fontWeight: 500, color: C.espresso, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{custName(b)}</div>
                    <div style={{ fontFamily: "var(--font-body)", fontSize: 9.5, color: C.taupe }}>{bedShort(b.bedId)}</div>
                  </button>
                );
              })}
              {bk.length === 0 && <div style={{ fontFamily: "var(--font-body)", fontWeight: 300, fontSize: 11, color: C.taupe, textAlign: "center", padding: "12px 0" }}>Libre</div>}
            </div>
          </Card>
        );
      })}
    </div>
  );
}

/* ---------- VISTA MES ---------- */
function MonthGrid({ date, version, onPickDay }) {
  const d = parseIso(date);
  const y = d.getFullYear(), m = d.getMonth();
  const first = new Date(y, m, 1);
  const startDow = (first.getDay() + 6) % 7;
  const days = new Date(y, m + 1, 0).getDate();
  const beds = PureApi.getBeds().filter((b) => b.active).length;
  const cells = [];
  for (let i = 0; i < startDow; i++) cells.push(null);
  for (let dd = 1; dd <= days; dd++) cells.push(dd);
  return (
    <Card pad={16}>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(7,1fr)", gap: 6, marginBottom: 8 }}>
        {["Lun", "Mar", "Mié", "Jue", "Vie", "Sáb", "Dom"].map((x) => (
          <div key={x} style={{ textAlign: "center", fontFamily: "var(--font-body)", fontSize: 10, fontWeight: 600, letterSpacing: "0.1em", textTransform: "uppercase", color: C.taupe, padding: "4px 0" }}>{x}</div>
        ))}
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(7,1fr)", gap: 6 }}>
        {cells.map((dd, i) => {
          if (!dd) return <div key={i} />;
          const iso = `${y}-${String(m + 1).padStart(2, "0")}-${String(dd).padStart(2, "0")}`;
          const dow = new Date(y, m, dd).getDay();
          const bk = PureApi.getBookings({ date: iso }).filter((b) => b.status !== "cancelled");
          const total = (CLOSE_MIN - OPEN_MIN) * beds;
          const used = bk.filter((b) => ["confirmed", "paid", "completed", "pending_payment", "pending_confirmation"].includes(b.status)).reduce((s, b) => { const sv = svcOf(b); return s + (sv ? sv.duration + sv.cleanup : 0); }, 0);
          const pct = total ? Math.min(100, Math.round((used / total) * 100)) : 0;
          const isToday = iso === TODAY;
          const hasPending = bk.some((b) => b.status === "pending_payment" || b.status === "pending_confirmation");
          return (
            <button key={i} onClick={() => onPickDay(iso)} disabled={dow === 0} style={{ aspectRatio: "1 / 0.92", borderRadius: 10, cursor: dow === 0 ? "default" : "pointer",
              background: isToday ? C.gold15 : (dow === 0 ? "transparent" : C.white), border: `1px solid ${isToday ? C.champagne : C.line}`,
              padding: "8px 9px", display: "flex", flexDirection: "column", alignItems: "flex-start", textAlign: "left", opacity: dow === 0 ? 0.45 : 1 }}>
              <div style={{ display: "flex", justifyContent: "space-between", width: "100%", alignItems: "center" }}>
                <span style={{ fontFamily: "var(--font-display)", fontSize: 17, color: C.espresso }}>{dd}</span>
                {hasPending && <span style={{ width: 6, height: 6, borderRadius: 999, background: "#C9A53D" }} />}
              </div>
              {bk.length > 0 && <div style={{ fontFamily: "var(--font-body)", fontSize: 10, color: C.taupe, marginTop: 2 }}>{bk.length} reserva{bk.length !== 1 ? "s" : ""}</div>}
              <div style={{ marginTop: "auto", width: "100%", height: 5, borderRadius: 999, background: C.ivoryDeep, overflow: "hidden" }}>
                <div style={{ width: pct + "%", height: "100%", background: pct > 70 ? C.goldDeep : `linear-gradient(90deg,${C.champagne},${C.gold})` }} />
              </div>
            </button>
          );
        })}
      </div>
    </Card>
  );
}

Object.assign(window, { CalendarView });
