/* Content tab — Phase 10 (v5: split rail + viewer).
 *
 * Two surfaces:
 *   List      desktop split — rail of compact thumbnail-led rows on the
 *             left, inline viewer pane on the right. Mobile: rail-only,
 *             tapping a row opens a modal viewer.
 *   Calendar  drag-drop month grid for scheduling. Clicking an event
 *             opens the modal viewer.
 *
 * Card visual language is unified across video and original ideas. Each
 * rail row = small accent square (thumbnail or tinted chit) + a line of
 * text beside. Two lines max. No platform badges, no status pills, no
 * date chips on the rail itself. Detail lives in the viewer.
 */
(function () {
  const { useState, useEffect, useMemo, useRef } = React;
  const {
    SegmentedControl,
    Drawer,
    Button,
    Input,
    TextArea,
    Icons,
    EmptyState,
    showToast,
    content,
    coach,
    tokens,
    time,
  } = window.CC;

  function ideaTitle(c) {
    return c.title || c.note || c.url || "idea";
  }
  function shortenUrl(u) {
    try {
      const url = new URL(u);
      return url.host.replace(/^www\./, "") + url.pathname;
    } catch {
      return u;
    }
  }
  function shortDateChip(iso) {
    const d = new Date(iso);
    return d.toLocaleDateString(undefined, { day: "numeric", month: "short" });
  }
  function platformLabel(p) {
    if (p === "youtube") return "YouTube";
    if (p === "tiktok") return "TikTok";
    if (p === "instagram") return "Instagram";
    return null;
  }

  function rowSubline(c) {
    if (c.type === "original") return "Idea";
    if (c.creator) return "@" + c.creator;
    if (c.platform) return platformLabel(c.platform);
    if (c.url) return shortenUrl(c.url).split("/")[0];
    return "Link";
  }
  function rowTitle(c) {
    if (c.title) return c.title;
    if (c.type === "original") return c.note || "Empty idea";
    return c.url ? shortenUrl(c.url) : "Untitled";
  }

  // ────────────────────────────────────────────────────────────
  // Hooks
  // ────────────────────────────────────────────────────────────
  function useContent() {
    const [list, setList] = useState(content.all());
    useEffect(() => content.subscribe(setList), []);
    return list;
  }
  function useViewport() {
    const [wide, setWide] = useState(
      typeof window !== "undefined" ? window.innerWidth >= 1024 : true
    );
    useEffect(() => {
      const onResize = () => setWide(window.innerWidth >= 1024);
      window.addEventListener("resize", onResize);
      return () => window.removeEventListener("resize", onResize);
    }, []);
    return { wide };
  }

  // ────────────────────────────────────────────────────────────
  // Tab root
  // ────────────────────────────────────────────────────────────
  function Content() {
    const { wide } = useViewport();
    const all = useContent();
    const [view, setView] = useState("list");
    const [selectedId, setSelectedId] = useState(null);
    const [modalId, setModalId] = useState(null); // mobile + calendar entry
    const [adding, setAdding] = useState(false);
    const [scheduleFor, setScheduleFor] = useState(null);
    const [cursorMonth, setCursorMonth] = useState(() => {
      const d = new Date();
      d.setDate(1);
      return d;
    });

    useEffect(() => {
      if (window.CC._sharedUrl) {
        setAdding({
          prefill: window.CC._sharedUrl,
          prefillTitle: window.CC._sharedTitle || "",
        });
        delete window.CC._sharedUrl;
        delete window.CC._sharedTitle;
      }
    }, []);

    // If selected/modal item disappears (deleted), drop it.
    useEffect(() => {
      if (selectedId && !content.byId(selectedId)) setSelectedId(null);
      if (modalId && !content.byId(modalId)) setModalId(null);
    }, [all, selectedId, modalId]);

    function openItem(c) {
      if (wide && view === "list") {
        setSelectedId(c.id);
      } else {
        setModalId(c.id);
      }
    }

    const selected = selectedId ? content.byId(selectedId) : null;
    const modalItem = modalId ? content.byId(modalId) : null;

    return (
      <div className="cc-content">
        <header className="cc-content__head">
          <h1 className="cc-hub__title">Content</h1>
          <div className="cc-content__head-controls">
            <Button
              size="sm"
              icon={Icons.plus(14)}
              onClick={() => setAdding({ prefill: "" })}
            >
              Add
            </Button>
            <SegmentedControl
              size="sm"
              value={view}
              onChange={setView}
              options={[
                { label: "List", value: "list" },
                { label: "Calendar", value: "calendar" },
              ]}
            />
          </div>
        </header>

        {view === "list" ? (
          <ListView
            wide={wide}
            items={all}
            selected={selected}
            onOpen={openItem}
            onSchedule={(c) => setScheduleFor(c)}
          />
        ) : (
          <CalendarView
            cursorMonth={cursorMonth}
            onCursorChange={setCursorMonth}
            items={all}
            unscheduled={all.filter((c) => !c.scheduledFor)}
            onDropIdea={(idea, dateIso) => {
              content.schedule(idea.id, dateIso);
              showToast(`Scheduled "${ideaTitle(idea)}".`);
            }}
            onOpen={(c) => setModalId(c.id)}
          />
        )}

        <ViewerModal
          item={modalItem}
          onClose={() => setModalId(null)}
          onSchedule={() => setScheduleFor(modalItem)}
        />
        <AddDrawer
          spec={adding}
          onClose={() => setAdding(null)}
          onSaved={(id) => {
            setAdding(null);
            if (wide && view === "list") setSelectedId(id);
            else setModalId(id);
          }}
          onOpenExisting={(id) => {
            setAdding(null);
            if (wide && view === "list") setSelectedId(id);
            else setModalId(id);
          }}
        />
        <SchedulePickerDrawer
          item={scheduleFor}
          onClose={() => setScheduleFor(null)}
          onPick={(dateIso) => {
            content.schedule(scheduleFor.id, dateIso);
            setScheduleFor(null);
            showToast(`Scheduled for ${time.shortDate(new Date(dateIso))}.`);
          }}
          onClear={() => {
            content.unschedule(scheduleFor.id);
            setScheduleFor(null);
            showToast("Date cleared.");
          }}
        />
      </div>
    );
  }

  // ────────────────────────────────────────────────────────────
  // List view (split on desktop, rail-only on mobile)
  // ────────────────────────────────────────────────────────────
  const SORT_OPTIONS = [
    { value: "newest", label: "Newest" },
    { value: "oldest", label: "Oldest" },
    { value: "alpha", label: "A → Z" },
    { value: "scheduled", label: "Scheduled date" },
    { value: "manual", label: "Manual" },
  ];

  function useManualOrder() {
    const [map, setMap] = useState(null);
    useEffect(() => content.listenManualOrder(setMap), []);
    return map;
  }

  function applySort(items, sortKey, manualMap) {
    const arr = items.slice();
    if (sortKey === "manual" && manualMap) {
      arr.sort((a, b) => {
        const ai = manualMap[a.id] ?? Infinity;
        const bi = manualMap[b.id] ?? Infinity;
        if (ai !== bi) return ai - bi;
        return (b.createdAt || 0) - (a.createdAt || 0);
      });
    } else if (sortKey === "oldest") {
      arr.sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0));
    } else if (sortKey === "alpha") {
      arr.sort((a, b) => rowTitle(a).localeCompare(rowTitle(b)));
    } else if (sortKey === "scheduled") {
      arr.sort((a, b) => {
        const ad = a.scheduledFor || "9999-12-31";
        const bd = b.scheduledFor || "9999-12-31";
        if (ad !== bd) return ad.localeCompare(bd);
        return (b.createdAt || 0) - (a.createdAt || 0);
      });
    } else {
      // newest
      arr.sort((a, b) => (b.createdAt || 0) - (a.createdAt || 0));
    }
    // Pinned cards always float to top, preserving their relative sort order.
    arr.sort((a, b) => Number(Boolean(b.pinned)) - Number(Boolean(a.pinned)));
    return arr;
  }

  function ListView({ wide, items, selected, onOpen, onSchedule }) {
    const [sortKey, setSortKey] = useState("newest");
    const manualMap = useManualOrder();
    const sorted = useMemo(
      () => applySort(items, sortKey, manualMap),
      [items, sortKey, manualMap]
    );

    function commitDrag(draggedId, targetId, before) {
      // Snapshot the current visible order, move dragged → target.
      const order = sorted.map((c) => c.id);
      const fromIdx = order.indexOf(draggedId);
      if (fromIdx < 0) return;
      order.splice(fromIdx, 1);
      let toIdx = order.indexOf(targetId);
      if (toIdx < 0) toIdx = before ? 0 : order.length;
      else if (!before) toIdx += 1;
      order.splice(toIdx, 0, draggedId);
      content.setManualOrder(order);
      if (sortKey !== "manual") setSortKey("manual");
    }

    if (!items.length) {
      return (
        <div className="cc-content__empty">
          <EmptyState
            icon={Icons.sparkle(40)}
            title="Nothing in your swipe file yet"
            subtitle="Tap Add and paste a Reel, TikTok, or YouTube URL. Or just type an idea."
          />
        </div>
      );
    }

    return (
      <div className={`cc-content__split ${wide ? "is-wide" : ""}`}>
        <aside className="cc-content__rail">
          <div className="cc-content__rail-head">
            <select
              className="cc-content__sort"
              value={sortKey}
              onChange={(e) => setSortKey(e.target.value)}
              aria-label="Sort cards"
            >
              {SORT_OPTIONS.map((o) => (
                <option key={o.value} value={o.value}>
                  {o.label}
                </option>
              ))}
            </select>
          </div>
          <ul className="cc-content__rows">
            {sorted.map((c) => (
              <RailRow
                key={c.id}
                item={c}
                selected={wide && selected && selected.id === c.id}
                onOpen={() => onOpen(c)}
                onPinToggle={() => content.setPinned(c.id, !c.pinned)}
                onDropOnRow={commitDrag}
              />
            ))}
          </ul>
        </aside>

        {wide && (
          <section className="cc-content__pane">
            {selected ? (
              <Viewer
                item={selected}
                onSchedule={() => onSchedule(selected)}
              />
            ) : (
              <div className="cc-content__pane-hint">
                <p>Pick a card on the left.</p>
              </div>
            )}
          </section>
        )}
      </div>
    );
  }

  function RailRow({ item, selected, onOpen, onPinToggle, onDropOnRow }) {
    const [hot, setHot] = useState(null); // 'top' | 'bottom' | null

    function onDragStart(e) {
      e.dataTransfer.setData("text/plain", item.id);
      e.dataTransfer.effectAllowed = "move";
    }
    function onDragOver(e) {
      const id = e.dataTransfer.types.includes("text/plain") ? "x" : null;
      if (!id) return;
      e.preventDefault();
      e.dataTransfer.dropEffect = "move";
      const r = e.currentTarget.getBoundingClientRect();
      setHot(e.clientY < r.top + r.height / 2 ? "top" : "bottom");
    }
    function onDragLeave() { setHot(null); }
    function onDrop(e) {
      e.preventDefault();
      const draggedId = e.dataTransfer.getData("text/plain");
      const before = hot === "top";
      setHot(null);
      if (draggedId && draggedId !== item.id) {
        onDropOnRow?.(draggedId, item.id, before);
      }
    }

    return (
      <li
        className={`cc-row ${selected ? "is-selected" : ""} ${
          hot ? `is-drop-${hot}` : ""
        }`}
        draggable
        onDragStart={onDragStart}
        onDragOver={onDragOver}
        onDragLeave={onDragLeave}
        onDrop={onDrop}
      >
        <button type="button" className="cc-row__btn" onClick={onOpen}>
          <RowAccent item={item} />
          <div className="cc-row__text">
            <span className="cc-row__title">{rowTitle(item)}</span>
            <span className="cc-row__sub">{rowSubline(item)}</span>
          </div>
        </button>
        <button
          type="button"
          className={`cc-row__pin ${item.pinned ? "is-pinned" : ""}`}
          onClick={(e) => {
            e.stopPropagation();
            onPinToggle?.();
          }}
          aria-label={item.pinned ? "Unpin" : "Pin to top"}
          title={item.pinned ? "Unpin" : "Pin to top"}
        >
          {Icons.pin(14)}
        </button>
      </li>
    );
  }

  function RowAccent({ item }) {
    if (item.type === "original") {
      return (
        <span className="cc-row__accent cc-row__accent--idea">
          <span className="cc-row__accent-icon">{Icons.edit(20)}</span>
        </span>
      );
    }
    if (item.thumbnail) {
      return (
        <span className="cc-row__accent cc-row__accent--thumb">
          <img src={item.thumbnail} alt="" loading="lazy" />
        </span>
      );
    }
    const platform = item.platform || "link";
    return (
      <span
        className={`cc-row__accent cc-row__accent--platform cc-platform-bg--${platform}`}
      >
        {Icons.play(14)}
      </span>
    );
  }

  // ────────────────────────────────────────────────────────────
  // Viewer (right pane on desktop)
  // ────────────────────────────────────────────────────────────
  function Viewer({ item, onSchedule }) {
    const [editing, setEditing] = useState(false);
    const [draft, setDraft] = useState(item.note || "");
    const [editingTitle, setEditingTitle] = useState(false);
    const [titleDraft, setTitleDraft] = useState(item.title || "");

    useEffect(() => {
      setDraft(item.note || "");
      setEditing(false);
      setTitleDraft(item.title || "");
      setEditingTitle(false);
    }, [item.id]);

    function commitNote() {
      const next = draft.trim();
      if (next !== (item.note || "")) {
        content.update(item.id, { note: next });
      }
      setEditing(false);
    }

    function commitTitle() {
      const next = titleDraft.trim();
      if (next !== (item.title || "")) {
        content.update(item.id, { title: next || null });
      }
      setEditingTitle(false);
    }

    async function del() {
      await content.softDelete(item.id);
      showToast("Deleted.", {
        action: { label: "Undo", onClick: () => content.restore(item.id) },
      });
    }

    return (
      <div className="cc-viewer">
        <div className="cc-viewer__media">
          <MediaEmbed item={item} />
        </div>
        <div className="cc-viewer__body">
          {editingTitle ? (
            <form
              onSubmit={(e) => {
                e.preventDefault();
                commitTitle();
              }}
            >
              <Input
                value={titleDraft}
                onChange={setTitleDraft}
                placeholder="Title"
                autoFocus
              />
              <div className="cc-modal__note-actions" style={{ marginTop: 8 }}>
                <Button
                  size="sm"
                  variant="ghost"
                  onClick={() => {
                    setTitleDraft(item.title || "");
                    setEditingTitle(false);
                  }}
                >
                  Cancel
                </Button>
                <Button size="sm" type="submit" onClick={commitTitle}>
                  Save title
                </Button>
              </div>
            </form>
          ) : (
            <button
              type="button"
              className={`cc-viewer__title-btn ${
                item.title ? "" : "is-empty"
              }`}
              onClick={() => setEditingTitle(true)}
              title="Click to rename"
            >
              {item.title || "Add title"}
            </button>
          )}

          {item.type === "inspiration" ? (
            <>
              {item.creator && (
                <p className="cc-viewer__creator">@{item.creator}</p>
              )}
              {item.url && (
                <a
                  className="cc-modal__url"
                  href={item.url}
                  target="_blank"
                  rel="noopener noreferrer"
                >
                  {Icons.external(14)}
                  <span>{shortenUrl(item.url)}</span>
                </a>
              )}
            </>
          ) : null}

          {editing ? (
            <>
              <TextArea
                value={draft}
                onChange={setDraft}
                rows={item.type === "original" ? 5 : 3}
                autoFocus
              />
              <div className="cc-modal__note-actions">
                <Button
                  size="sm"
                  variant="ghost"
                  onClick={() => {
                    setDraft(item.note || "");
                    setEditing(false);
                  }}
                >
                  Cancel
                </Button>
                <Button size="sm" onClick={commitNote}>
                  Save note
                </Button>
              </div>
            </>
          ) : (
            <button
              type="button"
              className="cc-modal__note"
              onClick={() => setEditing(true)}
            >
              {item.note ? (
                item.note
              ) : (
                <span className="cc-modal__note-empty">
                  Add a note. What's the idea here?
                </span>
              )}
            </button>
          )}

          <div className="cc-modal__actions">
            <Button variant="secondary" onClick={onSchedule}>
              {Icons.calendar(14)}{" "}
              {item.scheduledFor
                ? `Scheduled ${shortDateChip(item.scheduledFor)}`
                : "Schedule"}
            </Button>
            <span style={{ flex: 1 }} />
            <Button variant="ghost" onClick={del}>
              {Icons.trash(14)} Delete
            </Button>
          </div>
        </div>
      </div>
    );
  }

  // ────────────────────────────────────────────────────────────
  // Modal (mobile entry point + calendar entry point)
  // ────────────────────────────────────────────────────────────
  function ViewerModal({ item, onClose, onSchedule }) {
    useEffect(() => {
      if (!item) return;
      const onKey = (e) => {
        if (e.key === "Escape") onClose();
      };
      document.addEventListener("keydown", onKey);
      const prev = document.body.style.overflow;
      document.body.style.overflow = "hidden";
      return () => {
        document.removeEventListener("keydown", onKey);
        document.body.style.overflow = prev;
      };
    }, [item, onClose]);

    if (!item) return null;

    return (
      <div className="cc-modal-root" role="dialog" aria-modal="true">
        <div className="cc-modal__backdrop" onClick={onClose} />
        <div className="cc-modal__sheet">
          <button
            type="button"
            className="cc-modal__close"
            onClick={onClose}
            aria-label="Close"
          >
            {Icons.x(18)}
          </button>
          <Viewer item={item} onSchedule={onSchedule} />
        </div>
      </div>
    );
  }

  // Click-to-play facade. Renders a poster + play button until clicked,
  // then swaps to the actual iframe. Stops the iframe from hijacking the
  // page scroll wheel until the user is actively engaging with it.
  function Facade({ itemId, aspectClass, thumbnail, platform, src, title, allow }) {
    const [active, setActive] = useState(false);
    useEffect(() => setActive(false), [itemId]);
    if (active) {
      return (
        <div className={`cc-modal__iframe-wrap ${aspectClass}`}>
          <iframe
            src={src}
            title={title}
            frameBorder="0"
            allow={allow}
            allowFullScreen
          />
        </div>
      );
    }
    return (
      <button
        type="button"
        className={`cc-modal__iframe-wrap cc-facade ${aspectClass} cc-platform-bg--${platform}`}
        onClick={() => setActive(true)}
        aria-label="Play video"
      >
        {thumbnail && <img src={thumbnail} alt="" className="cc-facade__img" />}
        <span className="cc-facade__shade" aria-hidden="true" />
        <span className="cc-facade__play" aria-hidden="true">
          {Icons.play(28)}
        </span>
      </button>
    );
  }

  function MediaEmbed({ item }) {
    if (item.type === "original") {
      return (
        <div className="cc-modal__original">
          <p className="cc-modal__original-text">
            {item.note || item.title || "Original idea"}
          </p>
        </div>
      );
    }
    const detected = content.detectUrl(item.url) || {};
    const platform = item.platform || detected.platform;

    if (platform === "youtube" && (item.videoId || detected.videoId)) {
      const id = item.videoId || detected.videoId;
      return (
        <div className="cc-modal__iframe-wrap cc-modal__iframe-wrap--youtube">
          <iframe
            src={`https://www.youtube.com/embed/${id}?rel=0`}
            title={ideaTitle(item)}
            frameBorder="0"
            allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
            allowFullScreen
          />
        </div>
      );
    }
    if (platform === "tiktok" && (item.videoId || detected.videoId)) {
      const id = item.videoId || detected.videoId;
      return (
        <div className="cc-modal__iframe-wrap cc-modal__iframe-wrap--tiktok">
          <iframe
            src={`https://www.tiktok.com/embed/v2/${id}`}
            title={ideaTitle(item)}
            frameBorder="0"
            allow="encrypted-media; picture-in-picture"
            allowFullScreen
          />
        </div>
      );
    }
    if (platform === "instagram") {
      return (
        <div className="cc-modal__instagram">
          {item.thumbnail ? (
            <img src={item.thumbnail} alt="" />
          ) : (
            <div className="cc-modal__instagram-placeholder">
              {Icons.sparkle(36)}
            </div>
          )}
          <div className="cc-modal__instagram-overlay">
            <p>Instagram needs login to play in-app.</p>
            <a
              className="cc-btn cc-btn--primary cc-btn--md"
              href={item.url}
              target="_blank"
              rel="noopener noreferrer"
            >
              {Icons.external(16)}
              <span>Open in Instagram</span>
            </a>
          </div>
        </div>
      );
    }
    return (
      <a
        className="cc-modal__generic"
        href={item.url}
        target="_blank"
        rel="noopener noreferrer"
      >
        {item.thumbnail ? (
          <img src={item.thumbnail} alt="" />
        ) : (
          <div className="cc-modal__instagram-placeholder">
            {Icons.external(36)}
          </div>
        )}
        <span className="cc-modal__generic-cta">
          {Icons.external(16)} Open link
        </span>
      </a>
    );
  }

  // ────────────────────────────────────────────────────────────
  // Calendar view
  // ────────────────────────────────────────────────────────────
  function CalendarView({
    cursorMonth,
    onCursorChange,
    items,
    unscheduled,
    onDropIdea,
    onOpen,
  }) {
    const grid = useMemo(() => buildGrid(cursorMonth), [cursorMonth]);
    const todayIso = content.todayIso();

    const byDate = useMemo(() => {
      const m = new Map();
      for (const c of items) {
        if (!c.scheduledFor) continue;
        const list = m.get(c.scheduledFor) || [];
        list.push(c);
        m.set(c.scheduledFor, list);
      }
      return m;
    }, [items]);

    function shiftMonth(delta) {
      const d = new Date(cursorMonth);
      d.setMonth(d.getMonth() + delta);
      onCursorChange(d);
    }

    return (
      <div className="cc-content__cal-layout">
        <UnscheduledRail items={unscheduled} onOpen={onOpen} />
        <section className="cc-cal">
          <header className="cc-cal__head">
            <button type="button" onClick={() => shiftMonth(-1)} aria-label="Previous month">←</button>
            <h2 className="cc-cal__title">
              {cursorMonth.toLocaleDateString(undefined, { month: "long", year: "numeric" })}
            </h2>
            <button type="button" onClick={() => shiftMonth(1)} aria-label="Next month">→</button>
          </header>
          <div className="cc-cal__weekdays">
            {["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"].map((d) => (
              <span key={d}>{d}</span>
            ))}
          </div>
          <div className="cc-cal__grid">
            {grid.map((cell) => (
              <CalendarCell
                key={cell.iso}
                cell={cell}
                today={cell.iso === todayIso}
                items={byDate.get(cell.iso) || []}
                onDropIdea={onDropIdea}
                onOpen={onOpen}
              />
            ))}
          </div>
        </section>
      </div>
    );
  }

  function UnscheduledRail({ items, onOpen }) {
    const [hot, setHot] = useState(false);
    function onDragOver(e) { e.preventDefault(); e.dataTransfer.dropEffect = "move"; setHot(true); }
    function onDragLeave() { setHot(false); }
    function onDrop(e) {
      e.preventDefault();
      setHot(false);
      const id = e.dataTransfer.getData("text/plain");
      const found = content.byId(id);
      if (found && found.scheduledFor) {
        content.unschedule(found.id);
        showToast(`"${ideaTitle(found)}" moved back.`);
      }
    }
    return (
      <aside
        className={`cc-events__rail ${hot ? "is-hot" : ""}`}
        onDragOver={onDragOver}
        onDragLeave={onDragLeave}
        onDrop={onDrop}
      >
        <div className="cc-events__rail-head">
          <strong style={{ fontSize: 13 }}>Unscheduled</strong>
        </div>
        {items.length === 0 ? (
          <EmptyState
            icon={Icons.sparkle(36)}
            title="Nothing waiting"
            subtitle="Drop scheduled cards here to clear their date."
          />
        ) : (
          <ul className="cc-events__rail-list">
            {items.map((c) => (
              <li
                key={c.id}
                className="cc-idea-card"
                draggable
                onDragStart={(e) => {
                  e.dataTransfer.setData("text/plain", c.id);
                  e.dataTransfer.effectAllowed = "move";
                }}
              >
                <button
                  type="button"
                  className="cc-idea-card__main"
                  onClick={() => onOpen(c)}
                >
                  <div className="cc-idea-card__title">{rowTitle(c)}</div>
                  {c.creator && <div className="cc-idea-card__desc">@{c.creator}</div>}
                </button>
              </li>
            ))}
          </ul>
        )}
      </aside>
    );
  }

  function buildGrid(cursorMonth) {
    const out = [];
    const first = new Date(cursorMonth);
    first.setDate(1);
    const dayOfWeek = (first.getDay() + 6) % 7;
    const start = new Date(first);
    start.setDate(1 - dayOfWeek);
    for (let i = 0; i < 42; i++) {
      const d = new Date(start);
      d.setDate(start.getDate() + i);
      const iso = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
      out.push({ iso, day: d.getDate(), otherMonth: d.getMonth() !== cursorMonth.getMonth() });
    }
    return out;
  }

  function CalendarCell({ cell, today, items, onDropIdea, onOpen }) {
    const [hot, setHot] = useState(false);
    function onDragOver(e) { e.preventDefault(); e.dataTransfer.dropEffect = "move"; setHot(true); }
    function onDragLeave() { setHot(false); }
    function onDrop(e) {
      e.preventDefault();
      setHot(false);
      const id = e.dataTransfer.getData("text/plain");
      const found = content.byId(id);
      if (found) onDropIdea(found, cell.iso);
    }
    return (
      <div
        className={`cc-cal__cell ${cell.otherMonth ? "is-other" : ""} ${today ? "is-today" : ""} ${hot ? "is-hot" : ""}`}
        onDragOver={onDragOver}
        onDragLeave={onDragLeave}
        onDrop={onDrop}
      >
        <div className="cc-cal__day">{cell.day}</div>
        <div className="cc-cal__events">
          {items.slice(0, 3).map((c) => (
            <button
              type="button"
              key={c.id}
              onClick={() => onOpen(c)}
              draggable
              onDragStart={(e) => {
                e.stopPropagation();
                e.dataTransfer.setData("text/plain", c.id);
                e.dataTransfer.effectAllowed = "move";
              }}
              className="cc-cal__event cc-cal__event--saved"
              title={ideaTitle(c)}
            >
              {rowTitle(c)}
            </button>
          ))}
          {items.length > 3 && <span className="cc-cal__more">+{items.length - 3}</span>}
        </div>
      </div>
    );
  }

  // ────────────────────────────────────────────────────────────
  // Add drawer — single field, auto-detects URL vs text
  // ────────────────────────────────────────────────────────────
  function AddDrawer({ spec, onClose, onSaved, onOpenExisting }) {
    const [title, setTitle] = useState("");
    const [description, setDescription] = useState("");
    const [url, setUrl] = useState("");
    const [saving, setSaving] = useState(false);
    const [recording, setRecording] = useState(false);
    const [transcribing, setTranscribing] = useState(false);
    const [elapsed, setElapsed] = useState(0);
    const recRef = useRef(null);

    useEffect(() => {
      if (!spec) return;
      setTitle("");
      setDescription("");
      setUrl("");
      setSaving(false);
      setRecording(false);
      setTranscribing(false);
      setElapsed(0);
      if (spec.prefill) {
        if (/^https?:\/\//i.test(spec.prefill.trim())) {
          setUrl(spec.prefill.trim());
        } else {
          setDescription(spec.prefill);
        }
      }
      if (spec.prefillTitle) setTitle(spec.prefillTitle);
    }, [spec]);

    // Duplicate detection on URL change.
    const duplicate = useMemo(() => {
      const u = url.trim();
      if (!u || !/^https?:\/\//i.test(u)) return null;
      const detected = content.detectUrl(u);
      if (!detected || !detected.videoId) return null;
      return content
        .all()
        .find(
          (c) =>
            c.type === "inspiration" &&
            c.platform === detected.platform &&
            c.videoId === detected.videoId
        );
    }, [url]);

    if (!spec) return null;

    async function startRecord() {
      try {
        const r = new window.CC.recorder.Recorder({
          onElapsed: (s) => setElapsed(s),
        });
        await r.start();
        recRef.current = r;
        setRecording(true);
      } catch (e) {
        showToast(e.message || "Mic unavailable.");
      }
    }
    async function stopRecord() {
      const r = recRef.current;
      if (!r) return;
      setRecording(false);
      setTranscribing(true);
      try {
        const { blob, durationSec, mime } = await r.stop();
        recRef.current = null;
        const ext = mime.includes("mp4") ? "m4a" : "webm";
        const path = `audio/content-${Date.now()}.${ext}`;
        const { path: stored } = await window.CC.fb.uploadAudio(path, blob);
        const { text } = await window.CC.api.transcribeAudio({
          audioPath: stored,
          durationSec,
        });
        setDescription((d) => (d ? `${d}\n${text}` : text));
      } catch (e) {
        showToast("Couldn't transcribe.");
      } finally {
        setTranscribing(false);
      }
    }

    async function save() {
      const t = title.trim();
      const d = description.trim();
      const u = url.trim();
      if (!t && !d && !u) {
        showToast("Add a title, description, or URL.");
        return;
      }
      if (u && !/^https?:\/\//i.test(u)) {
        showToast("URL needs to start with https://");
        return;
      }
      setSaving(true);
      try {
        let id;
        if (u) {
          const created = await content.addInspiration({
            url: u,
            title: t,
            note: d,
          });
          id = created.id;
          showToast("Saved.");
        } else {
          const created = await content.addOriginal({ title: t, note: d });
          id = created.id;
          showToast("Idea added.");
        }
        onSaved?.(id);
      } catch (e) {
        showToast("Couldn't save.");
        setSaving(false);
      }
    }

    return (
      <Drawer
        open={Boolean(spec)}
        onClose={onClose}
        title="Add to swipe file"
        footer={
          <Button fullWidth size="lg" onClick={save} loading={saving}>
            Save
          </Button>
        }
      >
        <div style={{ display: "grid", gap: 14 }}>
          <Input
            label="Title"
            value={title}
            onChange={setTitle}
            placeholder="A few words to label this"
            autoFocus
          />
          <div className="cc-add__voice-row">
            <div style={{ flex: 1, minWidth: 0 }}>
              <TextArea
                label="Description"
                value={description}
                onChange={setDescription}
                placeholder="What's the idea? Or tap the mic and dictate."
                rows={3}
              />
              {recording && (
                <div className="cc-add__voice-meta">
                  Recording · {Math.round(elapsed)}s
                </div>
              )}
              {transcribing && (
                <div className="cc-add__voice-meta">Transcribing…</div>
              )}
            </div>
            <button
              type="button"
              className={`cc-record cc-record--${
                recording ? "recording" : transcribing ? "processing" : "idle"
              } ${transcribing ? "is-disabled" : ""}`}
              onClick={recording ? stopRecord : startRecord}
              disabled={transcribing}
              aria-label={recording ? "Stop recording" : "Record voice note"}
            >
              {transcribing
                ? Icons.sparkle(20)
                : recording
                ? Icons.stop(20)
                : Icons.mic(22)}
            </button>
          </div>
          <Input
            label="URL"
            value={url}
            onChange={setUrl}
            placeholder="https://..."
            inputMode="url"
          />
          {duplicate && (
            <div className="cc-add__dup">
              <span>You've saved this before.</span>
              <button
                type="button"
                className="cc-add__dup-link"
                onClick={() => {
                  onOpenExisting?.(duplicate.id);
                }}
              >
                Open it →
              </button>
            </div>
          )}
        </div>
      </Drawer>
    );
  }

  function SchedulePickerDrawer({ item, onClose, onPick, onClear }) {
    const [date, setDate] = useState(content.todayIso());
    useEffect(() => {
      if (item) setDate(item.scheduledFor || content.todayIso());
    }, [item]);
    if (!item) return null;
    return (
      <Drawer
        open={Boolean(item)}
        onClose={onClose}
        title={item.scheduledFor ? "Reschedule" : "Schedule"}
        footer={
          <div style={{ display: "flex", gap: 8 }}>
            {item.scheduledFor && (
              <Button variant="ghost" onClick={onClear}>Clear date</Button>
            )}
            <span style={{ flex: 1 }} />
            <Button size="lg" onClick={() => onPick(date)}>
              {item.scheduledFor ? "Reschedule" : "Schedule"}
            </Button>
          </div>
        }
      >
        <Input label="Date" type="date" value={date} onChange={setDate} autoFocus />
      </Drawer>
    );
  }

  window.CC = window.CC || {};
  window.CC.Content = Content;
})();
