/* ============================================================
   Admin content editor — lightweight CMS overlay for the
   public homepage (port of the old index.html admin system).

   - Ctrl+Shift+A  or  double-click the footer copyright line
     opens an admin sign-in form.
   - Sign-in uses the SAME Members Portal admin account
     (POST /api/auth/login) — no new credentials, no new
     server endpoints. A valid admin JWT is stored the same
     way the Members Portal does (localStorage crm_token/crm_user).
   - Once signed in as an admin, "Edit content" toggles inline
     editing for text wrapped in <EditableText>. Edits are saved
     via POST /api/portal-content with the admin's JWT — this
     endpoint already accepts a valid admin token server-side.
   ============================================================ */

const AdminContentContext = React.createContext({
  content: {}, editing: false, onEdit: () => {}
});

/* Extract a plain-text value from a content key.
   Handles the legacy portal-content.json format where values are stored as
   {type:"inner",value:"...HTML..."} objects (from the old inline editor).
   Strips HTML tags so the new React editor works with plain text. */
function CT(content, key, fallback){
  let v = content && content[key];
  if(v === undefined || v === null || v === '') return fallback;
  // Unwrap legacy {type, value} format
  if(typeof v === 'object' && !Array.isArray(v) && v.value !== undefined) v = v.value;
  if(typeof v !== 'string') return fallback;
  // Strip HTML tags and decode common entities
  v = v
    .replace(/<br\s*\/?>/gi, ' ')
    .replace(/<[^>]+>/g, '')
    .replace(/&amp;/g, '&')
    .replace(/&apos;/g, "'")
    .replace(/&#39;/g, "'")
    .replace(/&lt;/g, '<')
    .replace(/&gt;/g, '>')
    .replace(/&nbsp;/g, ' ')
    .replace(/&quot;/g, '"')
    .trim();
  return v || fallback;
}

function EditableText({k, fallback, tag, className, style}){
  const { content, editing, onEdit } = React.useContext(AdminContentContext);
  const Tag = tag || 'span';
  const val = CT(content, k, fallback);
  if(!editing){
    return <Tag className={className} style={style}>{val}</Tag>;
  }
  return (
    <Tag
      className={(className ? className+' ' : '')+'admin-editable'}
      style={style}
      contentEditable
      suppressContentEditableWarning
      onBlur={e=>onEdit(k, e.target.innerText)}
    >{val}</Tag>
  );
}

function useAdminContent(){
  const [content,setContent]=React.useState({});
  const [loaded,setLoaded]=React.useState(false);
  React.useEffect(()=>{
    fetch('/api/portal-content',{cache:'no-store'})
      .then(r=>r.ok ? r.json() : {})
      .then(d=>{ setContent(d||{}); setLoaded(true); })
      .catch(()=>setLoaded(true));
  },[]);
  return [content, setContent, loaded];
}

function useAdminAuth(){
  const [user,setUser]=React.useState(null);
  const [checked,setChecked]=React.useState(false);

  const refresh = React.useCallback(()=>{
    let token;
    try{ token = localStorage.getItem('crm_token'); }catch(e){ token=null; }
    if(!token){ setUser(null); setChecked(true); return; }
    fetch('/api/auth/me',{headers:{Authorization:'Bearer '+token}})
      .then(r=>r.ok ? r.json() : null)
      .then(d=>{ setUser(d ? (d.user||d) : null); setChecked(true); })
      .catch(()=>{ setUser(null); setChecked(true); });
  },[]);

  React.useEffect(()=>{ refresh(); },[refresh]);
  return [user, refresh, checked];
}

/* Lightweight media library panel — shows all /pictures/ files,
   lets admin upload new ones and copy URLs */
function MediaLibrary({onClose, adminToken}){
  const [pics,setPics]=React.useState([]);
  const [loading,setLoading]=React.useState(true);
  const [uploading,setUploading]=React.useState(false);
  const [copied,setCopied]=React.useState('');

  const loadPics=()=>{
    fetch('/api/pictures').then(r=>r.ok?r.json():[]).then(d=>{
      setPics(Array.isArray(d)?d:[]);
      setLoading(false);
    }).catch(()=>setLoading(false));
  };
  React.useEffect(loadPics,[]);

  const copyUrl=(url)=>{
    navigator.clipboard.writeText('https://asia-ai.org'+url).then(()=>{
      setCopied(url);
      setTimeout(()=>setCopied(''),2000);
    }).catch(()=>{ window.prompt('Copy URL:', 'https://asia-ai.org'+url); });
  };

  const handleUpload=(e)=>{
    const file=e.target.files[0];
    if(!file) return;
    setUploading(true);
    const fd=new FormData();
    fd.append('image', file);
    fetch('/api/pictures/upload',{
      method:'POST',
      headers:{ Authorization: 'Bearer '+adminToken },
      body: fd
    }).then(r=>r.json()).then(d=>{
      if(d.success){ setUploading(false); loadPics(); }
      else{ alert('Upload failed: '+(d.error||'unknown')); setUploading(false); }
    }).catch(e=>{ alert('Upload error: '+e.message); setUploading(false); });
    e.target.value='';
  };

  return (
    <div className="admin-modal-overlay" onClick={onClose}>
      <div className="admin-modal admin-media-modal" onClick={e=>e.stopPropagation()}>
        <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:16}}>
          <h3 style={{margin:0}}>Media Library</h3>
          <label className="btn btn-primary" style={{fontSize:13,padding:'8px 14px',cursor:'pointer'}}>
            {uploading?'Uploading…':'+ Upload'}
            <input type="file" accept="image/*" onChange={handleUpload} style={{display:'none'}} disabled={uploading}/>
          </label>
        </div>
        <p style={{color:'var(--ink-3)',fontSize:13,margin:'0 0 14px'}}>Click any image to copy its full URL to clipboard.</p>
        {loading ? <div style={{padding:20,textAlign:'center',color:'var(--ink-3)'}}>Loading…</div> : (
          <div className="admin-pics-grid">
            {pics.length===0 && <div style={{color:'var(--ink-3)',fontSize:14}}>No pictures yet.</div>}
            {pics.map((p,i)=>(
              <div className={"admin-pic-item"+(copied===p.url?' copied':'')} key={i} onClick={()=>copyUrl(p.url)} title={p.filename}>
                <img src={p.url} alt={p.filename} loading="lazy"/>
                <div className="admin-pic-name">{copied===p.url?'Copied!':p.filename}</div>
              </div>
            ))}
          </div>
        )}
        <div style={{marginTop:16,textAlign:'right'}}>
          <button className="btn btn-ghost" onClick={onClose}>Close</button>
        </div>
      </div>
    </div>
  );
}

function AdminContentProvider({children}){
  const [content,setContent,loaded]=useAdminContent();
  const [user,refreshAuth,authChecked]=useAdminAuth();
  const [editing,setEditing]=React.useState(false);
  const [toolbarOpen,setToolbarOpen]=React.useState(false);
  const [showMedia,setShowMedia]=React.useState(false);
  const [showLogin,setShowLogin]=React.useState(false);
  const [email,setEmail]=React.useState('');
  const [pw,setPw]=React.useState('');
  const [err,setErr]=React.useState('');
  const [busy,setBusy]=React.useState(false);
  const [dirty,setDirty]=React.useState(false);
  const [saving,setSaving]=React.useState(false);
  const [savedMsg,setSavedMsg]=React.useState('');

  const isAdmin = !!(user && user.role==='admin');

  let adminToken='';
  try{ adminToken = localStorage.getItem('crm_token')||''; }catch(e){}

  React.useEffect(()=>{
    const onKey=(e)=>{
      if(e.ctrlKey && e.shiftKey && (e.key==='A' || e.key==='a')){
        e.preventDefault();
        if(isAdmin) setToolbarOpen(o=>!o);
        else setShowLogin(true);
      }
    };
    const onDbl=(e)=>{
      if(e.target && e.target.closest && e.target.closest('#footer-copy')){
        if(isAdmin) setToolbarOpen(true);
        else setShowLogin(true);
      }
    };
    window.addEventListener('keydown', onKey);
    window.addEventListener('dblclick', onDbl);
    return ()=>{
      window.removeEventListener('keydown', onKey);
      window.removeEventListener('dblclick', onDbl);
    };
  },[isAdmin]);

  const login = async ()=>{
    setErr(''); setBusy(true);
    try{
      const r = await fetch('/api/auth/login',{
        method:'POST',
        headers:{'Content-Type':'application/json'},
        body: JSON.stringify({email, password: pw})
      });
      const d = await r.json();
      if(!r.ok || !d.token){
        setErr(d.error || 'Sign-in failed.');
        setBusy(false);
        return;
      }
      const u = d.user || {};
      if(u.role !== 'admin'){
        setErr('This account does not have admin access.');
        setBusy(false);
        return;
      }
      try{
        localStorage.setItem('crm_token', d.token);
        localStorage.setItem('crm_user', JSON.stringify(u));
      }catch(e){}
      refreshAuth();
      setShowLogin(false);
      setToolbarOpen(true);
      setPw('');
    }catch(e){
      setErr('Could not sign in — please try again.');
    }
    setBusy(false);
  };

  const logout = ()=>{
    setEditing(false);
    setToolbarOpen(false);
  };

  const onEdit = (k,v)=>{
    setContent(prev=>({...prev,[k]:v}));
    setDirty(true);
  };

  const save = async ()=>{
    setSaving(true); setSavedMsg('');
    let token='';
    try{ token = localStorage.getItem('crm_token')||''; }catch(e){}
    try{
      /* Build a clean snapshot: for legacy {type,value} entries keep them,
         for plain-string entries (edited by this system) keep as-is.
         The server stores whatever we send. On next load, CT() handles both. */
      const r = await fetch('/api/portal-content',{
        method:'POST',
        headers:{
          'Content-Type':'application/json',
          ...(token ? {Authorization:'Bearer '+token} : {})
        },
        body: JSON.stringify({...content})
      });
      const d = await r.json();
      if(d && d.success){ setDirty(false); setSavedMsg('Saved ✓'); }
      else setSavedMsg('Save failed: '+((d && d.error)||'unknown error'));
    }catch(e){
      setSavedMsg('Save failed — network error');
    }
    setSaving(false);
    setTimeout(()=>setSavedMsg(''), 3000);
  };

  const ctx = React.useMemo(()=>({content, editing: isAdmin && editing, onEdit}), [content, editing, isAdmin]);

  if(!loaded || !authChecked) return <React.Fragment>{children}</React.Fragment>;

  return (
    <AdminContentContext.Provider value={ctx}>
      {children}

      {isAdmin && toolbarOpen && (
        <div className="admin-toolbar">
          <span className="admin-pill">Admin · {(user.name||user.email||'').split(' ')[0]}</span>
          <button className={"admin-btn"+(editing?" on":"")} onClick={()=>setEditing(e=>!e)}>
            {editing ? '✏ Editing ON' : 'Edit content'}
          </button>
          {editing && (
            <button className="admin-btn primary" onClick={save} disabled={!dirty || saving}>
              {saving ? 'Saving…' : dirty ? 'Save' : '✓ Saved'}
            </button>
          )}
          <button className="admin-btn" onClick={()=>setShowMedia(true)}>📷 Photos</button>
          {savedMsg && <span className="admin-msg">{savedMsg}</span>}
          <button className="admin-btn ghost" onClick={logout}>Hide</button>
        </div>
      )}

      {showMedia && (
        <MediaLibrary onClose={()=>setShowMedia(false)} adminToken={adminToken}/>
      )}

      {showLogin && (
        <div className="admin-modal-overlay" onClick={()=>setShowLogin(false)}>
          <div className="admin-modal" onClick={e=>e.stopPropagation()}>
            <h3>Admin sign-in</h3>
            <p>Sign in with your Members Portal admin account to edit this page's content.</p>
            <input
              type="email"
              placeholder="Email"
              value={email}
              onChange={e=>setEmail(e.target.value)}
              style={{marginBottom:10}}
              autoFocus
            />
            <input
              type="password"
              placeholder="Password"
              value={pw}
              onChange={e=>setPw(e.target.value)}
              onKeyDown={e=>{ if(e.key==='Enter') login(); }}
            />
            {err && <div className="admin-err">{err}</div>}
            <div className="admin-modal-actions">
              <button className="btn btn-ghost" onClick={()=>setShowLogin(false)}>Cancel</button>
              <button className="btn btn-primary" onClick={login} disabled={busy}>{busy?'Signing in…':'Sign in'}</button>
            </div>
          </div>
        </div>
      )}
    </AdminContentContext.Provider>
  );
}

Object.assign(window, { AdminContentProvider, AdminContentContext, EditableText, CT });
