/* EntryRow + Entry expansion.
 *
 * Single source of truth for "render an entry in a list and let the user
 * tap to reveal transcript / audio / actions". Members, Recent, Attention,
 * Search, and member-detail all use this primitive.
 *
 * Layouts vary by `density`:
 *   - "row":   horizontal one-line (Recent timeline)
 *   - "card":  full card with chip row (Attention, Pinned)
 *   - "stack": tight stacked block (Member detail feed)
 */
(function () {
  const { useState, useEffect } = React;
  const {
    Avatar,
    Pill,
    Icons,
    showToast,
    coach,
    entries,
    members,
    time,
    tokens,
  } = window.CC;

  function typeLabel(type) {
    if (type === "member") return "Member";
    if (type === "class") return "Class";
    return "Note";
  }
  function typeTone(type) {
    if (type === "member") return "member";
    if (type === "class") return "onTrack";
    return "other";
  }

  function EntryRow({
    entry,
    density = "row",
    onEdit,
    onOpenMember,
    showCoach = true,
    forceExpanded = false,
  }) {
    const [open, setOpen] = useState(forceExpanded);
    useEffect(() => {
      if (forceExpanded) setOpen(true);
    }, [forceExpanded]);

    const memberRefs = (entry.members || [])
      .map((id) => members.byId(id))
      .filter(Boolean);

    return (
      <div className={`cc-entry cc-entry--${density} ${open ? "is-open" : ""}`}>
        <button
          type="button"
          className="cc-entry__head"
          onClick={() => setOpen((v) => !v)}
          aria-expanded={open}
        >
          {showCoach && (
            <Avatar
              coach={entry.coach}
              size={density === "card" ? 32 : 24}
              label={coach.label(entry.coach)}
            />
          )}
          <Pill size="sm" tone={typeTone(entry.type)}>
            {typeLabel(entry.type)}
          </Pill>
          {entry.pinned && (
            <span className="cc-entry__icon-meta" title="Pinned">
              {Icons.pin(14)}
            </span>
          )}
          {entry.needs_followup && (
            <span
              className="cc-entry__icon-meta"
              title="Needs follow-up"
              style={{ color: tokens.colors.status.overdue }}
            >
              {Icons.flag(14)}
            </span>
          )}
          {memberRefs.length > 0 && density !== "row" && (
            <span className="cc-entry__members">
              {memberRefs.slice(0, 3).map((m) => m.name).join(", ")}
              {memberRefs.length > 3 ? ` +${memberRefs.length - 3}` : ""}
            </span>
          )}
          <span className="cc-entry__body">{entry.body}</span>
          <span className="cc-entry__time">
            {density === "row"
              ? time.timeOfDay(entry.created_at)
              : time.relative(entry.created_at)}
          </span>
        </button>

        {open && (
          <ExpandedDetail
            entry={entry}
            memberRefs={memberRefs}
            onEdit={onEdit}
            onOpenMember={onOpenMember}
          />
        )}
      </div>
    );
  }

  function ExpandedDetail({ entry, memberRefs, onEdit, onOpenMember }) {
    const [showTranscript, setShowTranscript] = useState(false);
    const me = coach.get() || "simon";

    function pinToggle() {
      if (entry.pinned) {
        entries.unpin(entry.id);
        showToast("Unpinned.");
      } else {
        entries.pin(entry.id, me);
        showToast("Pinned to Attention.");
      }
    }
    function flagToggle() {
      const next = !entry.needs_followup;
      entries.flag(entry.id, next);
      showToast(next ? "Flagged for follow-up." : "Cleared.");
    }
    async function del() {
      await entries.softDelete(entry.id);
      showToast("Deleted.", {
        action: { label: "Undo", onClick: () => entries.restore(entry.id) },
      });
    }

    return (
      <div className="cc-entry__detail">
        {memberRefs.length > 0 && (
          <div className="cc-entry__detail-row">
            <span className="cc-entry__detail-label">Members</span>
            <div className="cc-entry__detail-chips">
              {memberRefs.map((m) => (
                <button
                  type="button"
                  key={m.row_id}
                  className="cc-entry__chip"
                  onClick={() => onOpenMember?.(m)}
                >
                  {m.name}
                </button>
              ))}
            </div>
          </div>
        )}

        {entry.transcript && entry.transcript !== entry.body && (
          <div className="cc-entry__detail-row">
            <button
              type="button"
              className="cc-entry__transcript-toggle"
              onClick={() => setShowTranscript((v) => !v)}
            >
              {showTranscript ? "Hide" : "Show"} full transcript
            </button>
            {showTranscript && (
              <div className="cc-entry__transcript">{entry.transcript}</div>
            )}
          </div>
        )}

        {entry.audio_path && (
          <AudioPlayback path={entry.audio_path} duration={entry.audio_duration_sec} />
        )}

        <div className="cc-entry__actions">
          <button type="button" className="cc-entry__action" onClick={() => onEdit?.(entry)}>
            {Icons.edit(14)} Edit
          </button>
          <button
            type="button"
            className={`cc-entry__action ${entry.pinned ? "is-on" : ""}`}
            onClick={pinToggle}
          >
            {Icons.pin(14)} {entry.pinned ? "Unpin" : "Pin"}
          </button>
          <button
            type="button"
            className={`cc-entry__action ${entry.needs_followup ? "is-on" : ""}`}
            onClick={flagToggle}
          >
            {Icons.flag(14)} {entry.needs_followup ? "Clear flag" : "Flag follow-up"}
          </button>
          <button
            type="button"
            className="cc-entry__action cc-entry__action--danger"
            onClick={del}
          >
            {Icons.trash(14)} Delete
          </button>
        </div>
      </div>
    );
  }

  function AudioPlayback({ path, duration }) {
    const [url, setUrl] = useState(null);
    const [error, setError] = useState(false);
    useEffect(() => {
      let cancelled = false;
      window.CC.fb.storage
        .ref(path)
        .getDownloadURL()
        .then((u) => {
          if (!cancelled) setUrl(u);
        })
        .catch(() => {
          if (!cancelled) setError(true);
        });
      return () => {
        cancelled = true;
      };
    }, [path]);
    if (error)
      return (
        <div className="cc-entry__audio-missing">
          {Icons.x(14)} Audio missing
        </div>
      );
    return (
      <div className="cc-entry__audio">
        {url ? (
          <audio src={url} controls preload="none" />
        ) : (
          <span className="cc-entry__audio-loading">Loading audio…</span>
        )}
        {duration ? (
          <span className="cc-entry__audio-duration">
            {time.audioDuration(duration)}
          </span>
        ) : null}
      </div>
    );
  }

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