/* 所有确认窗口和对话编辑。生成建议与正式保存分开，失败保留输入与原版本。 */
(() => {
  const P = window.Playbook;
  const { Button, Modal, Tag, AgentChoices, Changes } = P;
  function SelectSkills({ kind, onClose }) {
    const { data, commit, error } = P.useApp();
    const [selected, setSelected] = React.useState([]);
    const importing = kind === 'import';
    const list = importing ? P.imports : data.skills.filter(k => k.origin !== 'friend');
    const already = k => importing ? data.skills.some(x => x.id === k.id || x.id === k.existing) : !!k.published;
    const toggle = id => setSelected(v => v.includes(id) ? v.filter(x => x !== id) : [...v, id]);
    const submit = () => commit({ type: importing ? 'import' : 'share', ids: selected }, importing ? 'Skills imported' : selected.length === 1 ? 'Skill added to your card' : 'Skills added to your card', onClose);
    return <Modal title={importing ? 'Import skills' : 'Add skills to your card'} onClose={onClose} footer={<><Button onClick={onClose}>Cancel</Button><Button primary disabled={!selected.length} onClick={submit}>{importing ? 'Import selected' : 'Add to My Card'}</Button></>}>
      <p>{importing ? 'Bring in complete skills from the agents you already use.' : 'Your approved friends can view the selected skills and add them to their playbooks. Skill content and included files will be shared.'}</p>
      {(importing ? ['Codex', 'Claude Code'] : ['']).map(group => <div key={group}>{group && <div className="pb-group-title">{group}</div>}{list.filter(k => !group || k.origin === group).map(k => <label className="pb-select-row" key={k.id}><input type="checkbox" disabled={already(k)} checked={selected.includes(k.id)} onChange={() => toggle(k.id)} /><span><span className="pb-skill-name">{k.name}</span><span className="pb-skill-desc" style={{ display: 'block' }}>{k.desc}</span></span>{already(k) && <Tag>{importing ? 'In Playbook' : 'On your card'}</Tag>}</label>)}</div>)}
      {!list.length && <p>Save a local skill first.</p>}<div className="pb-note">{selected.length} {selected.length === 1 ? 'skill' : 'skills'} selected</div>{error && <div className="pb-error" role="alert">{error}</div>}
    </Modal>;
  }
  function ManageAgents({ k, onClose }) {
    const { commit, error } = P.useApp();
    const [value, setValue] = React.useState(k.agents);
    return <Modal title="Manage agents" onClose={onClose} footer={<><Button onClick={onClose}>Cancel</Button><Button primary onClick={() => commit({ type: 'agents', id: k.id, agents: value }, 'Agents updated', onClose)}>Apply changes</Button></>}><p>{k.name}</p><AgentChoices value={value} onChange={setValue} /><div className="pb-note">Unchecking an agent does not delete this skill from your Playbook.</div>{error && <div className="pb-error" role="alert">{error}</div>}</Modal>;
  }
  function RecordName({ onClose }) {
    const { showPending, setRecording } = P.useApp();
    const [name, setName] = React.useState('');
    const generate = () => {
      const k = P.skill('pending-record', name.trim(), 'Repeat the method demonstrated in your recording.', 'persom', { sources: [{ date: 'Oct 4', title: 'Your recorded demonstration (simulated)' }] });
      setRecording(null); onClose(); showPending(k);
    };
    return <Modal title="Name your skill" onClose={onClose} footer={<><Button onClick={onClose}>Cancel</Button><Button primary disabled={!name.trim()} onClick={generate}>Generate draft</Button></>}><p>The recording has stopped. Give your method a name before reviewing the draft.</p><label className="pb-field">Skill name<input value={name} autoFocus onChange={e => setName(e.target.value)} placeholder="For example, Review a product spec" /></label><div className="pb-note">原型演示：没有实际录制屏幕或生成 AI 内容。录制草稿直接进入审阅，不放进主动发现区，正式入口位置待确认。</div></Modal>;
  }
  function Dialogs() {
    const c = P.useApp();
    const { modal: m, closeModal, data, commit, error, startChat, setNav, openSkill, setRecording, chat } = c;
    if (!m) return null;
    const k = data.skills.find(x => x.id === m.id);
    if (m.type === 'import' || m.type === 'shareSelect') return <SelectSkills key={m.type} kind={m.type} onClose={closeModal} />;
    if (m.type === 'agents' && k) return <ManageAgents key={k.id} k={k} onClose={closeModal} />;
    if (m.type === 'copy' && k) return <Modal title="Edit your own copy?" onClose={closeModal} footer={<><Button onClick={closeModal}>Cancel</Button><Button primary onClick={() => { closeModal(); startChat(k, 'copy'); }}>Continue</Button></>}><p>You can’t edit a friend’s skill directly. Editing will create your own copy. The original skill will stay unchanged.</p><div className="pb-skill-name">{k.name}</div></Modal>;
    if (m.type === 'share' && k) return <Modal title="Add this skill to your card?" onClose={closeModal} footer={<><Button onClick={closeModal}>Cancel</Button><Button primary onClick={() => commit({ type: 'share', ids: [k.id] }, 'Skill added to your card', closeModal)}>Add to My Card</Button></>}><div className="pb-skill-name" style={{ marginBottom: 16 }}>{k.name}</div><p>Your approved friends can view this skill and add it to their playbooks.</p><p>The skill content and included files will be shared.</p>{error && <div className="pb-error" role="alert">{error}</div>}</Modal>;
    if (m.type === 'unshare' && k) return <Modal title="Remove from My Card?" onClose={closeModal} footer={<><Button onClick={closeModal}>Cancel</Button><Button danger onClick={() => commit({ type: 'unshare', id: k.id }, 'Skill removed from your card', closeModal)}>Remove from My Card</Button></>}><p>{k.name} will stay in Your skills. Removing it from your card does not delete your local skill.</p><div className="pb-note">好友已获得版本如何跟随，尚待确认。此处只演示移除自己的分享。</div>{error && <div className="pb-error" role="alert">{error}</div>}</Modal>;
    if (m.type === 'publish' && k) return <Modal title="Update on My Card" wide onClose={closeModal} footer={<><Button onClick={closeModal}>Cancel</Button><Button primary onClick={() => commit({ type: 'share', ids: [k.id] }, 'Skill updated on your card', closeModal)}>Publish update</Button></>}><p>Your approved friends will see the updated skill after you publish. Private memory and discovery sources are not included.</p><Changes before={k.published} after={P.snapshot(k)} />{error && <div className="pb-error" role="alert">{error}</div>}</Modal>;
    if (m.type === 'file') return <Modal title={m.path} wide onClose={closeModal}><div className="pb-note" style={{ marginTop: 0, marginBottom: 12 }}>Read only. Included scripts are never executed by this prototype.</div><pre>{m.skill.files[m.path]}</pre></Modal>;
    if (m.type === 'changes' && chat?.proposed) return <Modal title="View changes" wide onClose={closeModal}><p>{chat.mode === 'copy' ? 'The original skill will stay unchanged.' : chat.mode === 'draft' ? 'Applying these changes updates the draft only.' : `Agents to update: ${chat.original.agents.join(', ') || 'None'}`}</p><Changes before={P.snapshot(chat.original)} after={P.snapshot(chat.proposed)} /></Modal>;
    if (m.type === 'upstream' && k) return <Modal title={`Update from ${k.friend || k.origin}`} wide onClose={closeModal} footer={<Button onClick={closeModal}>Close</Button>}><p>{k.name} · v{k.version} → v{k.upstream.version}</p><p>Agents affected: {k.agents.join(', ') || 'None'}</p><Changes before={P.snapshot(k)} after={P.snapshot(k.upstream)} /><div className="pb-note">来源方更新的具体同步规则待确认。原型只展示完整对比，不擅自应用新版本。</div></Modal>;
    if (m.type === 'recordStart') return <Modal title="Record a skill" onClose={closeModal} footer={<><Button onClick={closeModal}>Cancel</Button><Button primary onClick={() => { setRecording({ seconds: 0 }); closeModal(); }}>Start recording</Button></>}><p>Show Persom how you do something once. It will turn your demonstration into a skill draft for you to review.</p><div className="pb-note">本原型只模拟录制流程，不申请屏幕或麦克风权限。</div></Modal>;
    if (m.type === 'recordName') return <RecordName onClose={closeModal} />;
    return null;
  }
  /* 交互与布局以 Persom 2.1 AskPanel 为准，仅替换成 Skill 的对话内容。 */
  function Chat() {
    const c = P.useApp();
    const { chat, setChat, askOpen, setAskOpen, openModal, submitChat, applyChat, error } = c;
    const ref = React.useRef(null), inputRef = React.useRef(null), bodyRef = React.useRef(null);
    const mode = chat?.mode || 'ask';
    const messages = chat?.messages || [];
    const AskDefaults = window.PersomAskDefaults;
    const showSug = AskDefaults.shouldShow({ messageCount: messages.length, hasResult: !!chat?.proposed, hasContext: !!chat?.original, hasTask: mode !== 'ask' });
    const measure = () => c.setAskHeight(Math.ceil(ref.current?.getBoundingClientRect().height || 48));
    /* ResizeObserver 同时跟踪展开动画，让详情始终避开同一个全局 Ask。 */
    React.useLayoutEffect(() => {
      measure();
      const observer = typeof ResizeObserver === 'function' ? new ResizeObserver(measure) : null;
      if (ref.current) observer?.observe(ref.current);
      window.addEventListener('resize', measure);
      return () => { observer?.disconnect(); window.removeEventListener('resize', measure); };
    }, [c.setAskHeight]);
    React.useLayoutEffect(measure, [askOpen, chat?.original, chat?.proposed, messages.length, showSug]);
    React.useEffect(() => { if (askOpen) inputRef.current?.focus(); }, [askOpen, chat?.original?.id, mode]);
    React.useEffect(() => { if (bodyRef.current) bodyRef.current.scrollTop = bodyRef.current.scrollHeight; }, [messages.length, chat?.proposed, askOpen]);
    React.useEffect(() => {
      if (!askOpen || c.modal) return;
      /* 沿用旧项目的 mousedown，外部按钮的 click 仍能重新打开对话。 */
      const outside = e => { if (!ref.current?.contains(e.target)) setAskOpen(false); };
      const key = e => { if (e.key === 'Escape' && (!c.detail || ref.current?.contains(e.target))) setAskOpen(false); };
      document.addEventListener('mousedown', outside); document.addEventListener('keydown', key);
      return () => { document.removeEventListener('mousedown', outside); document.removeEventListener('keydown', key); };
    }, [askOpen, c.modal, !!c.detail]);
    const labels = { draft: ['Changes to your draft', 'Apply to draft'], local: ['Changes to your skill', 'Apply changes'], copy: ['Changes to your copy', 'Save copy'] };
    const removeContext = () => setChat(prev => ({ mode: 'ask', request: prev.request || '', messages: prev.messages || [] }));
    return <div className="pb-ask-wrap" inert={c.modal ? '' : undefined} aria-hidden={!!c.modal || undefined}><section id="pb-global-ask" className={`pb-ask ${askOpen ? 'pb-ask-open' : ''}`} ref={ref} aria-label="Ask Persom">
      <div className="pb-chat-expand"><div className="pb-chat-clip"><div className="pb-chat-panel" inert={!askOpen ? '' : undefined} aria-hidden={!askOpen || undefined}>
        <div className="pb-chat-head"><span className="pb-chat-title">Ask</span><button type="button" className="pb-chat-clear" aria-label="Clear and close conversation" title="Clear and close" onClick={c.cancelChat}>×</button></div>
        <div ref={bodyRef} className="pb-chat-body p21-scroll" style={{ display: showSug ? 'none' : 'flex' }}>
          {!messages.length && !chat?.proposed && !showSug && <div className="pb-chat-empty">{chat?.original ? 'Tell Persom what you would like to change.' : mode === 'create' ? 'Describe the method you would like to turn into a skill.' : 'Ask about your skills, or open one to edit it with Persom.'}</div>}
          {messages.map((m, i) => <div className={`pb-chat-message ${m.role === 'you' ? 'pb-chat-message-you' : ''}`} key={i}>
            {m.chip && <span className="pb-chat-message-chip">{m.chip}</span>}
            <div className={`pb-chat-bubble ${m.role === 'you' ? 'pb-chat-you' : 'pb-chat-persom'}`}>{m.text}</div>
          </div>)}
          {chat?.proposed && <div className="pb-chat-result"><div className="pb-chat-result-title">{mode === 'create' ? 'Your skill draft is ready to review' : labels[mode][0]}</div>
            {mode === 'create' ? <><div className="pb-skill-name">{chat.proposed.name}</div><div className="pb-skill-desc">{chat.proposed.desc}</div><div className="pb-actions"><Button onClick={() => c.cancelChat()}>Cancel</Button><Button primary onClick={() => c.reviewCreated()}>Review draft</Button></div></> : <>
              <div className="pb-muted" style={{ fontSize: 13 }}>Include your requirement while preserving the existing method.</div>{P.diff(chat.original, chat.proposed).map(r => <div className="pb-row" key={r.path}><code>{r.path}</code><Tag>{r.status}</Tag></div>)}
              <button className="pb-link" style={{ marginTop: 12 }} onClick={() => openModal({ type: 'changes' })}>View changes ›</button>
              {mode === 'copy' ? <div className="pb-note">The original skill will stay unchanged. The copy is not saved yet.</div> : mode === 'local' ? <div className="pb-note">Agents to update: {chat.original.agents.join(', ') || 'None'}. Shared content will not be updated automatically.</div> : <div className="pb-note">This updates the draft only. Save it separately when you are ready.</div>}
              <div className="pb-actions"><Button onClick={() => c.cancelChat()}>Cancel</Button><Button primary onClick={applyChat}>{labels[mode][1]}</Button></div>
            </>}{error && <div className="pb-error" role="alert">{error}</div>}
          </div>}
        </div>
        {showSug && <div className="pb-ask-suggestions">{AskDefaults.suggestions.map(q => <button type="button" key={q} className="pb-ask-suggestion p21-h-soft" onMouseDown={e => e.preventDefault()} onClick={() => submitChat(q)}>↗ {q}</button>)}</div>}
      </div></div></div>
      <form className="pb-ask-input" onSubmit={e => { e.preventDefault(); submitChat(); }}><span className="pb-ask-spark" aria-hidden="true">✦</span>
        {chat?.original && <span className="pb-chat-context"><span title={chat.original.name}>{chat.original.name}{mode === 'copy' ? ' (copy)' : ''}</span><button type="button" aria-label="Remove skill context" onMouseDown={e => e.preventDefault()} onClick={removeContext}>×</button></span>}
        <input type="text" ref={inputRef} aria-label="Message Persom" placeholder={chat?.original ? 'What would you like to change?' : mode === 'create' ? 'What method would you like to turn into a skill?' : 'Ask Persom...'} value={chat?.request || ''} onFocus={() => setAskOpen(true)} onMouseDown={() => setAskOpen(true)} onChange={e => setChat(prev => ({ ...(prev || { mode: 'ask' }), request: e.target.value }))} onKeyDown={e => { if (e.key === 'Enter' && !e.nativeEvent.isComposing) { e.preventDefault(); submitChat(); } }} /><button type="button" className="pb-send p21-h-dark" aria-label="Send message" title="Send" onClick={() => { inputRef.current?.focus(); submitChat(); }}><window.P21.Ico name="send" size={16} sw={2} /></button>
      </form>
    </section></div>;
  }
  const { Logo } = P;
  Object.assign(P, { Dialogs, Chat });
})();
