// CoCreate.jsx — 墨吞 · 牵线（共创）
// 找人帮助分两条路，是墨吞常用的问题结构：
//   ① 现成的（过去）：有人已经写过 → 引用并在文末嵌入来源（带 ID / 出处）
//   ② 实时的（现在）：信息还没有、或需要现场（如到某地拍照）→ 约人；
//      墨吞依据你写的内容做 faiss 检索，并判断是否该请专业人士介入。
// 墨吞在这里只做"建立联系"。（演示流程，确定性匹配，未接真实 faiss）
const { useState: useStateCC } = React;

function CoPersonCard({ row, mode, joined, onInvite }) {
  const { p, score, whenPlace, pro } = row;
  const live = (mode === 'live');
  return (
    <div className="co-card">
      <div className="co-card-head">
        <span className="co-ava" style={{ background: p.av }}>{p.name[0]}</span>
        <div className="co-id">
          <div className="co-name">{p.name} <span className="co-prof">{p.prof}</span>
            {live && pro && <span className="co-pro-tag">专业</span>}
          </div>
          <div className="co-handle">{p.id}</div>
        </div>
        <div className="co-score">
          <span className="co-score-n">{score}<i>%</i></span>
          <span className="co-score-l">语境相关</span>
        </div>
      </div>

      <div className="co-meta">
        <span className="co-place"><Icon name="mapPin" size={11} /> 现在 {p.now}</span>
        {p.been.length > 0 && (
          <span className="co-place dim"><Icon name="globe" size={11} /> 去过 {p.been.join(' · ')}</span>
        )}
        {live && whenPlace && <span className="co-when">{whenPlace}</span>}
      </div>

      <div className="co-snip">
        <Icon name="quote" size={13} />
        <p>{p.snippet}</p>
      </div>

      <div className="co-foot">
        {live
          ? <span className="co-src"><Icon name="clock" size={11} /> {p.offer}</span>
          : <span className="co-src">来源《{p.note}》· 已发表</span>}
        <div className="co-acts">
          {joined ? (
            <button className="co-join done" disabled><Icon name="check" size={12} /> {live ? '已发出邀约' : '已引用'}</button>
          ) : live ? (
            <button className="co-join live" onClick={() => onInvite(row)}>
              <Icon name="send" size={12} /> 约 TA{pro ? '（专业）' : ''}
            </button>
          ) : (
            <button className="co-join" onClick={() => onInvite(row)}>
              <Icon name="quote" size={12} /> 引用 · 嵌入出处
            </button>
          )}
        </div>
      </div>
    </div>
  );
}

function CoCreate({ note, embedded, lockMode, onCite }) {
  const [mode, setMode] = useStateCC(lockMode || 'past');     // past 现成 / live 实时
  const [query, setQuery] = useStateCC('');
  const [activeDim, setActiveDim] = useStateCC(null);
  const [busy, setBusy] = useStateCC(false);
  const [results, setResults] = useStateCC(null);
  const [cited, setCited] = useStateCC([]);        // ① 已引用（带出处）
  const [invited, setInvited] = useStateCC([]);    // ② 已约人（实时）
  const [compose, setCompose] = useStateCC(null);  // 正在写的邀约卡（live）
  const [inviteText, setInviteText] = useStateCC('');
  const [available, setAvailable] = useStateCC(true); // 可被邀约（用户可关闭）
  const judge = motunCoJudge(note);
  const dims = coDimensions(note, mode);

  const pageTitle = (note && note.title) || '这一页';
  const place0 = (note && note.locs && note.locs[0]) || '';

  function switchMode(m) {
    if (m === mode) return;
    setMode(m); setResults(null); setActiveDim(null); setQuery('');
  }

  function search(q, dimId) {
    if (busy) return;
    setActiveDim(dimId || null);
    setBusy(true);
    setResults(null);
    setTimeout(() => {
      setResults(faissMatch(note, q, mode === 'live'));
      setBusy(false);
    }, 950);
  }
  function runDim(d) {
    setQuery(d.id === 'prof' || d.id === 'pro' ? '' : d.label.replace(/[「」]/g, ''));
    search(d.q || d.label, d.id);
  }

  // —— ① 引用现成（past）——
  function cite(row) {
    if (cited.some(j => j.p.id === row.p.id)) return;
    const n = onCite ? onCite(row.p, 0) : (cited.length + 1);
    setCited(j => [...j, { ...row, n }]);
  }
  // —— ② 约人（live）：先写邀约卡，再发出 ——
  function openCompose(row) {
    if (invited.some(j => j.p.id === row.p.id)) return;
    const pl = place0 || row.p.now;
    const canShoot = /拍|现拍/.test(row.p.offer || '');
    setInviteText(canShoot
      ? `想请你在${pl}，为《${pageTitle}》拍一张照片 —— 如果你愿意。`
      : `想请你聊聊「${(note && note.notes && note.notes[0]) || row.p.prof}」，为《${pageTitle}》补一块。`);
    setCompose(row);
  }
  function sendInvite() {
    if (!compose) return;
    const row = compose;
    const canShoot = /拍|现拍/.test(inviteText) || /现拍/.test(row.p.offer || '');
    setInvited(j => [...j, { p: row.p, pro: row.pro, msg: inviteText, status: 'waiting', material: null, n: 0 }]);
    setCompose(null);
    setTimeout(() => {
      setInvited(list => list.map(it => {
        if (it.p.id !== row.p.id || it.status !== 'waiting') return it;
        const material = canShoot
          ? { kind: 'photo', label: '应约现拍 · ' + (place0 || row.p.now) }
          : { kind: 'note', label: row.p.snippet };
        let n = 0;
        if (onCite) {
          const src = canShoot
            ? '应约现拍《' + pageTitle + '》· ' + row.p.id + ' · ' + (typeof NOW !== 'undefined' ? NOW.date : '')
            : '应约共创 · ' + row.p.id + ' · “' + row.p.snippet + '”';
          n = onCite(row.p, 0, { source: src });
        }
        return Object.assign({}, it, { status: 'accepted', material, n });
      }));
    }, 2200);
  }
  function invite(row) { mode === 'live' ? openCompose(row) : cite(row); }
  function removeCite(id) { setCited(j => j.filter(x => x.p.id !== id).map((x, i) => ({ ...x, n: i + 1 }))); }
  function removeInvite(id) { setInvited(j => j.filter(x => x.p.id !== id)); }

  const isJoined = id => (mode === 'live' ? invited : cited).some(j => j.p.id === id);
  const corpus = (1240 + (note ? note.id.charCodeAt(note.id.length - 1) * 7 : 0));

  return (
    <div className={'cocreate' + (embedded ? ' embedded' : '')}>
      {/* 墨吞 · 判断这一页缺什么，并结构成两条路 */}
      {!embedded && (
      <div className="co-top">
        <span className="motun-ava">墨</span>
        <div style={{ flex: 1 }}>
          <div className="nm">墨吞 · 牵线 — 这一页，要不要请人补一块？</div>
          <div className="co-judge">
            我读了这一页，判断你可能缺：<b>{judge.missing}</b>。这通常有两条路 —
          </div>
        </div>
        <span className="co-engine"><Icon name="spark" size={11} /> 向量检索</span>
      </div>
      )}

      {/* 两条路 · 模式切换（嵌入书写视图时由页签锁定，隐藏切换）*/}
      {!lockMode && (
      <div className="co-modes">
        <button className={'co-mode' + (mode === 'past' ? ' on' : '')} onClick={() => switchMode('past')}>
          <span className="co-mode-n"><Icon name="quote" size={13} /> ① 引用现成的</span>
          <span className="co-mode-d">有人写过 · 过去 · 带出处</span>
        </button>
        <button className={'co-mode' + (mode === 'live' ? ' on' : '')} onClick={() => switchMode('live')}>
          <span className="co-mode-n"><Icon name="send" size={13} /> ② 约人帮忙</span>
          <span className="co-mode-d">还没有 · 实时 · 现场或专业</span>
        </button>
      </div>
      )}

      {/* 当前路的墨吞提示 */}
      <div className={'co-hint ' + mode}>
        {mode === 'past'
          ? <span><Icon name="spark" size={12} /> {judge.pastLine}</span>
          : <span><Icon name="spark" size={12} /> {judge.liveLine}
              {judge.proRole && <b className="co-pro-note"> 建议请「{judge.proRole}」介入。</b>}
            </span>}
      </div>

      {/* 可被邀约 · 用户可随时关闭 */}
      {mode === 'live' && (
        <button className={'co-avail' + (available ? ' on' : '')} onClick={() => setAvailable(a => !a)}>
          <span className="co-avail-dot" />
          <span className="co-avail-t">{available ? '可被邀约 · 别人也能请你共创' : '已关闭邀约 · 别人无法约你'}</span>
          <span className="co-avail-sw"><i /></span>
        </button>
      )}

      {/* 邀约卡 · 真正发出的一张卡片 */}
      {compose && (
        <div className="co-invitecard">
          <div className="ic-head">
            <span className="co-ava" style={{ background: compose.p.av }}>{compose.p.name[0]}</span>
            <div className="ic-to">
              <div className="ic-to-n">致 {compose.p.name} <span className="co-prof">{compose.p.prof}</span></div>
              <div className="ic-to-from">一张来自《{pageTitle}》的邀约</div>
            </div>
            <button className="co-x" onClick={() => setCompose(null)}><Icon name="x" size={13} /></button>
          </div>
          <textarea className="ic-text" value={inviteText} onChange={e => setInviteText(e.target.value)}
            placeholder="想请 TA 做什么？" />
          <div className="ic-note"><Icon name="link" size={11} /> 若用了 TA 的照片或资料，会自动署上 {compose.p.id}，写进文末出处。</div>
          <div className="ic-acts">
            <button className="ic-cancel" onClick={() => setCompose(null)}>再想想</button>
            <button className="ic-send" onClick={sendInvite} disabled={!inviteText.trim()}>
              <Icon name="send" size={13} /> 发出邀约
            </button>
          </div>
        </div>
      )}

      {/* 选择要找什么 */}
      <div className="co-dims">
        {dims.map(d => (
          <button key={d.id} className={'co-dim' + (activeDim === d.id ? ' on' : '')} onClick={() => runDim(d)} disabled={busy}>
            <Icon name={d.icon} size={14} />
            <span className="co-dim-l">{d.label}</span>
            <span className="co-dim-h">{d.hint}</span>
          </button>
        ))}
      </div>

      {/* 自由检索 */}
      <div className="co-search">
        <Icon name="search" size={14} />
        <input value={query} onChange={e => setQuery(e.target.value)}
          onKeyDown={e => { if (e.key === 'Enter') search(query); }}
          placeholder={mode === 'live' ? '想请谁来现场？例如：现在在杭州、能拍西湖的人' : '想引用谁写过的？例如：写过侘寂 / 爵士的人'} />
        <button className="co-go" disabled={busy || !query.trim()} onClick={() => search(query)}>检索</button>
      </div>

      {busy && (
        <div className="co-loading">
          <Icon name="refresh" size={13} className="spin" />
          向量检索中 · 在 {corpus.toLocaleString()} 页他人的笔记里匹配语境…
        </div>
      )}

      {!busy && results && (
        results.length ? (
          <div className="co-results">
            <div className="co-results-hd">
              {mode === 'live'
                ? `墨吞找到 ${results.length} 位现在能帮上忙的人 · 按相关度排序`
                : `墨吞找到 ${results.length} 则可引用的现成内容 · 按相关度排序`}
            </div>
            {results.map(row => (
              <CoPersonCard key={row.p.id} row={row} mode={mode}
                joined={isJoined(row.p.id)} onInvite={invite} />
            ))}
          </div>
        ) : (
          <div className="co-empty">这一向度暂时没匹配到。换个职业、地点或主题试试？</div>
        )
      )}

      {/* ① 已引用：文末出处 */}
      {cited.length > 0 && (
        <div className="co-tray">
          <div className="co-tray-hd">
            <Icon name="quote" size={13} /> 已引用进这一页 · {cited.length}
            <span className="co-tray-note">自动写入文末出处，署对方 ID 与来源</span>
          </div>
          {cited.map(({ p, n }) => (
            <div key={p.id} className="co-contrib">
              <span className="co-cite-n">[{n}]</span>
              <div className="co-contrib-body">
                <div className="co-contrib-top">
                  <span className="co-contrib-name">{p.name}</span>
                  <span className="co-contrib-prof">{p.prof}</span>
                  <button className="co-x" onClick={() => removeCite(p.id)} title="移除"><Icon name="x" size={11} /></button>
                </div>
                <p className="co-contrib-text">“{p.snippet}”</p>
                <div className="co-cite">
                  <Icon name="link" size={10} /> 文末出处 [{n}] · <b>{p.id}</b> · 来源《{p.note}》
                </div>
              </div>
            </div>
          ))}
          <div className="co-tray-foot">引用的文字会带着 [序号] 落进正文，文末自动生成出处清单。</div>
        </div>
      )}

      {/* ② 已约人：实时邀约 · 等待 → 接受（素材回到这一页 + 文末出处）*/}
      {invited.length > 0 && (
        <div className="co-tray live">
          <div className="co-tray-hd">
            <Icon name="send" size={13} /> 邀约 · {invited.length}
            <span className="co-tray-note">对方接受后，素材带 ID 回到这一页</span>
          </div>
          {invited.map(({ p, pro, msg, status, material, n }) => (
            <div key={p.id} className={'co-contrib' + (status === 'accepted' ? ' accepted' : '')}>
              <span className="co-ava sm" style={{ background: p.av }}>{p.name[0]}</span>
              <div className="co-contrib-body">
                <div className="co-contrib-top">
                  <span className="co-contrib-name">{p.name}</span>
                  <span className="co-contrib-prof">{p.prof}</span>
                  {pro && <span className="co-pro-tag">专业</span>}
                  <button className="co-x" onClick={() => removeInvite(p.id)} title={status === 'waiting' ? '撤回' : '移除'}><Icon name="x" size={11} /></button>
                </div>
                <p className="co-invite-msg">“{msg}”</p>
                {status === 'waiting' && (
                  <div className="co-invite-status"><span className="co-dot-wait" /> 已送达 · 等待回应…</div>
                )}
                {status === 'accepted' && (
                  <div className="co-deliver">
                    <div className="co-deliver-hd"><Icon name="check" size={12} /> {p.name} 接受了邀约</div>
                    {material && material.kind === 'photo'
                      ? <div className="co-deliver-photo"><Icon name="camera" size={16} /> {material.label}</div>
                      : <p className="co-deliver-note">“{material && material.label}”</p>}
                    <div className="co-cite"><Icon name="link" size={10} /> 文末出处 [{n}] · <b>{p.id}</b> · 已署名</div>
                  </div>
                )}
              </div>
            </div>
          ))}
          <div className="co-tray-foot">回来的照片 / 资料带上 TA 的 ID 与时间戳，作为这一页的共创素材，并写入文末出处。</div>
        </div>
      )}
    </div>
  );
}

Object.assign(window, { CoCreate, CoPersonCard });
