// crm-helpcenter.jsx — Help Center article management (staff view)
// Public rendering lives in help.html; this is the authoring/curation UI.
const { useState, useEffect, useRef } = React;

// ── Rich text editor (Quill, uncontrolled) ──
// Mounts once per `key`; reports HTML upward on every change. The image
// toolbar button uploads to HelpAssets and embeds the hosted URL — never
// base64 — so images render on help.html and survive deploys.
function ArticleRichEditor({ initialHtml, onChange }) {
  const holderRef = useRef(null);
  const quillRef  = useRef(null);

  useEffect(() => {
    if (!holderRef.current || typeof Quill === 'undefined') return;
    const quill = new Quill(holderRef.current, {
      theme: 'snow',
      placeholder: 'Write the article…',
      modules: {
        toolbar: {
          container: [
            [{ header: [2, 3, 4, false] }],
            ['bold', 'italic', 'underline', 'strike'],
            [{ list: 'ordered' }, { list: 'bullet' }],
            ['blockquote', 'code-block'],
            ['link', 'image'],
            ['clean'],
          ],
          handlers: {
            image() {
              const input = document.createElement('input');
              input.type = 'file';
              input.accept = 'image/*';
              input.onchange = async () => {
                const file = input.files && input.files[0];
                if (!file) return;
                try {
                  const fd = new FormData();
                  fd.append('file', file, file.name);
                  const res = await fetch('/api/articles/assets', { method: 'POST', credentials: 'include', body: fd });
                  if (!res.ok) throw new Error((await res.json().catch(() => ({}))).message || 'Upload failed');
                  const { url } = await res.json();
                  const range = quill.getSelection(true);
                  quill.insertEmbed(range ? range.index : quill.getLength(), 'image', url, 'user');
                } catch (e) { alert('Image upload failed: ' + e.message); }
              };
              input.click();
            },
          },
        },
      },
    });
    if (initialHtml) quill.clipboard.dangerouslyPasteHTML(initialHtml);
    quill.on('text-change', () => onChange(quill.root.innerHTML));
    quillRef.current = quill;
    return () => { quillRef.current = null; };
  }, []);

  return (
    <div style={{background:'#fff',border:'1.5px solid var(--g200)',borderRadius:8,overflow:'hidden',display:'flex',flexDirection:'column',flex:1}}>
      <style>{`
        .ql-toolbar.ql-snow{border:none;border-bottom:1px solid var(--g200);font-family:var(--font);}
        .ql-container.ql-snow{border:none;font-family:var(--font);font-size:14px;flex:1;}
        .ql-editor{min-height:420px;line-height:1.7;}
        .ql-editor img{max-width:100%;height:auto;border-radius:8px;}
        .ql-snow .ql-tooltip{z-index:800;}
      `}</style>
      <div ref={holderRef} style={{display:'flex',flexDirection:'column',flex:1}} />
    </div>
  );
}

const VIS_BADGE = {
  public:    { cls: 'badge-green', label: 'public' },
  customers: { cls: 'badge-blue',  label: 'customers' },
  internal:  { cls: 'badge-gray',  label: 'internal' },
};

function HelpCenterView({ user, showToast }) {
  const [articles, setArticles] = useState([]);
  const [loading, setLoading]   = useState(true);
  const [search, setSearch]     = useState('');
  const [editing, setEditing]   = useState(null);   // null | 'new' | article id
  const [importing, setImporting] = useState(false);
  const [selIds, setSelIds]     = useState({});     // admin multi-select: id -> true
  const selCount = Object.values(selIds).filter(Boolean).length;
  const toggleSel = (id) => setSelIds(s => ({ ...s, [id]: !s[id] }));

  const load = () => {
    setLoading(true);
    CRM.ArticlesAPI.list()
      .then(setArticles)
      .catch(err => showToast('Failed to load articles: ' + err.message, 'error'))
      .finally(() => setLoading(false));
  };
  useEffect(load, []);

  const runImport = async () => {
    if (!confirm('Import/refresh all articles from ctrny.zendesk.com?')) return;
    // With Zendesk admin credentials the import also pulls internal
    // (employee-only) articles and tiers them as "internal" here.
    const email = (prompt('Zendesk admin email — leave blank to import public articles only:') || '').trim();
    let apiToken = '';
    if (email) {
      apiToken = (prompt('Zendesk API token (Admin Center → Apps and integrations → Zendesk API):') || '').trim();
      if (!apiToken) { showToast('No API token entered — import cancelled.', 'error'); return; }
    }
    setImporting(true);
    try {
      const r = await CRM.ArticlesAPI.importZendesk('ctrny.zendesk.com', email || null, apiToken || null);
      let msg = `Imported ${r.imported} new, updated ${r.updated}, ${r.assets} images rehosted`;
      if (r.errors && r.errors.length) msg += ` (${r.errors.length} errors)`;
      showToast(msg);
      load();
    } catch (err) {
      showToast('Import failed: ' + err.message, 'error');
    } finally {
      setImporting(false);
    }
  };

  const deleteSelected = async () => {
    const ids = Object.keys(selIds).filter(id => selIds[id]);
    if (ids.length === 0) return;
    if (!confirm(`Permanently delete ${ids.length} article${ids.length === 1 ? '' : 's'}? This cannot be undone.`)) return;
    try {
      const r = await CRM.ArticlesAPI.bulkDelete(ids);
      showToast(`Deleted ${r.deleted} article${r.deleted === 1 ? '' : 's'}.`);
      setSelIds({});
      load();
    } catch (err) {
      showToast('Delete failed: ' + err.message, 'error');
    }
  };

  const runLcImport = async () => {
    if (!confirm('Import the AoD how-to library (194 job-aid articles with screenshots, tiered "Customers")? Re-running refreshes existing ones.')) return;
    setImporting(true);
    try {
      const r = await CRM.ArticlesAPI.importLearningCenter();
      showToast(`Learning Center import: ${r.created} created, ${r.updated} updated.`);
      load();
    } catch (err) {
      showToast('Import failed: ' + err.message, 'error');
    } finally {
      setImporting(false);
    }
  };

  const sections   = [...new Set(articles.map(a => a.section || 'General'))].sort((a, b) => a.localeCompare(b));
  const categories = [...new Set(articles.map(a => a.category).filter(Boolean))].sort((a, b) => a.localeCompare(b));

  if (editing) {
    return (
      <HelpCenterEditor
        user={user}
        showToast={showToast}
        articleId={editing === 'new' ? null : editing}
        sections={sections}
        categories={categories}
        onBack={changed => { setEditing(null); if (changed) load(); }}
      />
    );
  }

  const q = search.trim().toLowerCase();
  const filtered = q
    ? articles.filter(a =>
        (a.title || '').toLowerCase().includes(q) ||
        (a.section || '').toLowerCase().includes(q) ||
        (a.category || '').toLowerCase().includes(q))
    : articles;

  // Two-level grouping: category → section → articles
  const byCategory = {};
  filtered.forEach(a => {
    const c = a.category || 'Uncategorized';
    const s = a.section || 'General';
    const cat = (byCategory[c] = byCategory[c] || {});
    (cat[s] = cat[s] || []).push(a);
  });
  const categoryNames = Object.keys(byCategory).sort((a, b) => {
    if (a === 'Uncategorized') return 1;
    if (b === 'Uncategorized') return -1;
    return a.localeCompare(b);
  });

  const articleRow = (a) => {
    const vis = VIS_BADGE[a.visibility] || VIS_BADGE.internal;
    return (
      <div key={a.id} className="card"
        style={{marginBottom:8,padding:'10px 14px',display:'flex',alignItems:'center',gap:12,cursor:'pointer',transition:'all .15s'}}
        onClick={() => setEditing(a.id)}
        onMouseEnter={e => e.currentTarget.style.borderColor = 'var(--navy)'}
        onMouseLeave={e => e.currentTarget.style.borderColor = 'var(--g200)'}>
        {user.isAdmin && (
          <input type="checkbox" checked={!!selIds[a.id]} style={{width:15,height:15,flexShrink:0,cursor:'pointer'}}
            onClick={e => e.stopPropagation()} onChange={() => toggleSel(a.id)} />
        )}
        <div style={{flex:1,minWidth:0,display:'flex',alignItems:'center',gap:8,flexWrap:'wrap'}}>
          <span style={{fontWeight:600,color:'var(--navy)',fontSize:14}}>{a.title}</span>
          <span className={`badge ${vis.cls}`}>{vis.label}</span>
          {!a.isPublished && <span className="badge badge-amber">DRAFT</span>}
          {a.zendeskId && (
            <span style={{fontSize:10,color:'var(--g600)',background:'var(--off)',border:'1px solid var(--g200)',borderRadius:4,padding:'1px 6px'}}>
              zendesk
            </span>
          )}
        </div>
        <div style={{textAlign:'right',flexShrink:0,fontSize:12,color:'var(--g400)'}}>
          {a.authorName || '—'} · {a.updatedAt ? new Date(a.updatedAt).toLocaleDateString() : ''}
        </div>
      </div>
    );
  };

  return (
    <div>
      <div style={{display:'flex',gap:10,alignItems:'center',marginBottom:18,flexWrap:'wrap'}}>
        <div style={{fontSize:13,color:'var(--g600)',fontWeight:600,flexShrink:0}}>
          {loading ? 'Loading…' : `${filtered.length} article${filtered.length === 1 ? '' : 's'}`}
        </div>
        <input className="search-input" style={{maxWidth:320}} placeholder="Search articles…"
          value={search} onChange={e => setSearch(e.target.value)} />
        <div style={{marginLeft:'auto',display:'flex',gap:8,alignItems:'center',flexWrap:'wrap'}}>
          {user.isAdmin && filtered.length > 0 && (
            <label style={{display:'flex',alignItems:'center',gap:6,fontSize:12,color:'var(--g600)',cursor:'pointer'}}>
              <input type="checkbox" style={{width:14,height:14}}
                checked={filtered.length > 0 && filtered.every(a => selIds[a.id])}
                onChange={e => {
                  const on = e.target.checked;
                  setSelIds(s => { const n = { ...s }; filtered.forEach(a => { n[a.id] = on; }); return n; });
                }} />
              Select all shown
            </label>
          )}
          {user.isAdmin && selCount > 0 && (
            <button className="btn btn-sm" style={{background:'#FEF2F2',color:'var(--red)',border:'1px solid #FECACA'}}
              onClick={deleteSelected}>
              🗑 Delete selected ({selCount})
            </button>
          )}
          {user.isAdmin && (
            <button className="btn btn-ghost btn-sm" onClick={runImport} disabled={importing}>
              {importing ? 'Importing… this can take a minute' : '⬇ Import from Zendesk'}
            </button>
          )}
          {user.isAdmin && (
            <button className="btn btn-ghost btn-sm" onClick={runLcImport} disabled={importing}>
              📖 Import AoD Learning Center
            </button>
          )}
          <button className="btn btn-primary btn-sm" onClick={() => setEditing('new')}>＋ New Article</button>
        </div>
      </div>

      {!loading && filtered.length === 0 && (
        <div className="card" style={{padding:32,textAlign:'center',color:'var(--g400)',fontSize:13}}>
          {q ? 'No articles match your search.' : 'No articles yet — create one or import from Zendesk.'}
        </div>
      )}

      {categoryNames.map(c => {
        const sectionNames = Object.keys(byCategory[c]).sort((a, b) => a.localeCompare(b));
        const count = sectionNames.reduce((n, s) => n + byCategory[c][s].length, 0);
        return (
          <div key={c} style={{marginTop:22}}>
            <div style={{display:'flex',alignItems:'baseline',gap:8,borderBottom:'2px solid var(--g200)',paddingBottom:6,marginBottom:4}}>
              <span style={{fontSize:15,fontWeight:800,color:'var(--navy)',letterSpacing:'-.01em'}}>{c}</span>
              <span style={{fontSize:12,color:'var(--g400)',fontWeight:600}}>{count} article{count === 1 ? '' : 's'}</span>
            </div>
            {sectionNames.map(s => (
              <div key={s}>
                <div style={{fontSize:11,fontWeight:700,letterSpacing:'.06em',textTransform:'uppercase',color:'var(--g400)',margin:'14px 0 8px'}}>
                  {s} ({byCategory[c][s].length})
                </div>
                {byCategory[c][s].map(articleRow)}
              </div>
            ))}
          </div>
        );
      })}
    </div>
  );
}

function HelpCenterEditor({ user, showToast, articleId, sections, categories, onBack }) {
  const [loading, setLoading] = useState(!!articleId);
  const [saving, setSaving]   = useState(false);
  const [wide, setWide]       = useState(window.innerWidth >= 900);
  const [mode, setMode]       = useState('visual');   // visual | html
  const [form, setForm] = useState({
    title: '', section: '', category: '', body: '',
    visibility: 'internal', isPublished: false,
  });

  useEffect(() => {
    if (!articleId) return;
    CRM.ArticlesAPI.get(articleId)
      .then(a => setForm({
        title:       a.title       || '',
        section:     a.section     || '',
        category:    a.category    || '',
        body:        a.body        || '',
        visibility:  a.visibility  || 'internal',
        isPublished: !!a.isPublished,
      }))
      .catch(err => { showToast('Failed to load article: ' + err.message, 'error'); onBack(false); })
      .finally(() => setLoading(false));
  }, [articleId]);

  useEffect(() => {
    const onResize = () => setWide(window.innerWidth >= 900);
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, []);

  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const save = async () => {
    if (!form.title.trim()) { showToast('Title is required', 'error'); return; }
    setSaving(true);
    try {
      const data = {
        title:    form.title.trim(),
        section:  form.section.trim() || 'General',
        category: form.category.trim() || null,
        body:     form.body,
      };
      if (user.isAdmin) {
        data.visibility  = form.visibility;
        data.isPublished = form.isPublished;
      }
      if (articleId) {
        await CRM.ArticlesAPI.update(articleId, data);
        showToast('Article saved');
      } else {
        await CRM.ArticlesAPI.create(data);
        showToast('Article created');
      }
      onBack(true);
    } catch (err) {
      showToast('Save failed: ' + err.message, 'error');
    } finally {
      setSaving(false);
    }
  };

  const remove = async () => {
    if (!confirm('Delete this article permanently?')) return;
    try {
      await CRM.ArticlesAPI.delete(articleId);
      showToast('Article deleted');
      onBack(true);
    } catch (err) {
      showToast('Delete failed: ' + err.message, 'error');
    }
  };

  if (loading) return <div style={{padding:32,color:'var(--g400)',fontSize:13}}>Loading article…</div>;

  return (
    <div>
      <div style={{display:'flex',alignItems:'center',gap:10,marginBottom:16,flexWrap:'wrap'}}>
        <button className="btn btn-ghost btn-sm" onClick={() => onBack(false)}>← Back</button>
        <div style={{fontSize:16,fontWeight:700,color:'var(--navy)'}}>
          {articleId ? 'Edit Article' : 'New Article'}
        </div>
        <div style={{marginLeft:'auto',display:'flex',gap:8}}>
          {articleId && user.isAdmin && (
            <button className="btn btn-ghost btn-sm" style={{color:'#BC141E'}} onClick={remove}>🗑 Delete</button>
          )}
          <button className="btn btn-primary btn-sm" onClick={save} disabled={saving}>
            {saving ? 'Saving…' : 'Save'}
          </button>
        </div>
      </div>

      <div className="card" style={{padding:16,marginBottom:14}}>
        <div style={{display:'flex',gap:14,flexWrap:'wrap'}}>
          <div style={{flex:2,minWidth:240}}>
            <label style={{display:'block',fontSize:11,fontWeight:700,textTransform:'uppercase',letterSpacing:'.06em',color:'var(--g400)',marginBottom:4}}>Title</label>
            <input className="search-input" style={{width:'100%',minWidth:0}} value={form.title}
              onChange={e => set('title', e.target.value)} placeholder="Article title" />
          </div>
          <div style={{flex:1,minWidth:170}}>
            <label style={{display:'block',fontSize:11,fontWeight:700,textTransform:'uppercase',letterSpacing:'.06em',color:'var(--g400)',marginBottom:4}}>Category</label>
            <input className="search-input" style={{width:'100%',minWidth:0}} list="hc-categories" value={form.category}
              onChange={e => set('category', e.target.value)} placeholder="e.g. Hardware" />
            <datalist id="hc-categories">
              {categories.map(c => <option key={c} value={c} />)}
            </datalist>
          </div>
          <div style={{flex:1,minWidth:170}}>
            <label style={{display:'block',fontSize:11,fontWeight:700,textTransform:'uppercase',letterSpacing:'.06em',color:'var(--g400)',marginBottom:4}}>Section</label>
            <input className="search-input" style={{width:'100%',minWidth:0}} list="hc-sections" value={form.section}
              onChange={e => set('section', e.target.value)} placeholder="e.g. Getting Started" />
            <datalist id="hc-sections">
              {sections.map(s => <option key={s} value={s} />)}
            </datalist>
          </div>
          {user.isAdmin ? (
            <React.Fragment>
              <div style={{minWidth:150}}>
                <label style={{display:'block',fontSize:11,fontWeight:700,textTransform:'uppercase',letterSpacing:'.06em',color:'var(--g400)',marginBottom:4}}>Visibility</label>
                <select className="search-input" style={{width:'100%',minWidth:0}} value={form.visibility}
                  onChange={e => set('visibility', e.target.value)}>
                  <option value="internal">Internal (staff only)</option>
                  <option value="customers">Customers</option>
                  <option value="public">Public</option>
                </select>
              </div>
              <div style={{minWidth:110,display:'flex',alignItems:'flex-end',paddingBottom:8}}>
                <label style={{display:'flex',alignItems:'center',gap:6,fontSize:13,color:'var(--navy)',cursor:'pointer',fontWeight:600}}>
                  <input type="checkbox" checked={form.isPublished}
                    onChange={e => set('isPublished', e.target.checked)} />
                  Published
                </label>
              </div>
            </React.Fragment>
          ) : (
            <div style={{display:'flex',alignItems:'flex-end',paddingBottom:8}}>
              <span style={{fontSize:12,color:'var(--g400)'}}>
                🔒 An admin reviews and publishes drafts. Current: {form.visibility} / {form.isPublished ? 'published' : 'draft'}
              </span>
            </div>
          )}
        </div>
      </div>

      <div style={{display:'flex',alignItems:'center',gap:8,marginBottom:6}}>
        <label style={{fontSize:11,fontWeight:700,textTransform:'uppercase',letterSpacing:'.06em',color:'var(--g400)'}}>Body</label>
        <div style={{marginLeft:'auto',display:'flex',gap:0,border:'1px solid var(--g200)',borderRadius:6,overflow:'hidden'}}>
          {['visual','html'].map(m => (
            <button key={m} onClick={() => setMode(m)}
              style={{padding:'4px 12px',fontSize:11,fontWeight:600,border:'none',cursor:'pointer',fontFamily:'var(--font)',
                background: mode === m ? 'var(--navy)' : '#fff', color: mode === m ? '#fff' : 'var(--g600)'}}>
              {m === 'visual' ? '✏️ Editor' : '</> HTML'}
            </button>
          ))}
        </div>
      </div>

      {mode === 'visual' ? (
        // Keyed so switching back from HTML view re-mounts with the latest body
        <ArticleRichEditor key={(articleId || 'new') + '-' + mode}
          initialHtml={form.body}
          onChange={html => set('body', html)} />
      ) : (
        <div style={{display:'flex',flexDirection:wide ? 'row' : 'column',gap:14,alignItems:'stretch'}}>
          <div style={{flex:1,minWidth:0,display:'flex',flexDirection:'column'}}>
            <textarea value={form.body} onChange={e => set('body', e.target.value)}
              placeholder="<p>Write article HTML here…</p>"
              style={{flex:1,minHeight:420,width:'100%',fontFamily:'monospace',fontSize:12,lineHeight:1.5,
                border:'1.5px solid var(--g200)',borderRadius:8,padding:12,color:'var(--navy)',
                outline:'none',resize:'vertical',background:'white'}} />
          </div>
          <div style={{flex:1,minWidth:0,display:'flex',flexDirection:'column'}}>
            <div className="card" style={{flex:1,padding:16,minHeight:420,overflow:'auto',fontSize:14,lineHeight:1.6}}>
              <style>{'.hc-preview img{max-width:100%;height:auto;}'}</style>
              <div className="hc-preview" dangerouslySetInnerHTML={{__html: form.body || '<p style="color:#94A0AB">Nothing to preview yet.</p>'}} />
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

window.HelpCenterView = HelpCenterView;
