/* ============================================================
   CAMPAIGNS — "My Campaigns" manager + campaign detail (Phases 5 & 4).
   List/create/rename/delete games (window.Games); open a campaign to
   upload & manage its art by category (window.Assets / uploadAsset /
   watchGameAssets). No-build: loaded after auth.jsx + backend.jsx;
   reuses Icon + glass / rm-* / tiny-btn styling. Aliased hooks.
   ============================================================ */
const { useState: useS_camp, useEffect: useE_camp, useRef: useR_camp } = React;

const ASSET_CATS = [
  { id:'item',  label:'Items'   },
  { id:'npc',   label:'NPCs'    },
  { id:'enemy', label:'Enemies' },
  { id:'boss',  label:'Bosses'  },
  { id:'map',   label:'Maps'    },
];
const MAX_IMG = 20 * 1024 * 1024;    // 20 MB
const MAX_VID = 200 * 1024 * 1024;   // 200 MB

// friendlier copy when the upload brokers aren't deployed yet
function uploadErrMsg(e){
  const m = (e && e.message) || 'Upload failed.';
  if(/not found|404|Failed to fetch|NetworkError|Load failed/i.test(m))
    return 'Upload service isn’t live yet — finish the Cloudflare setup, then deploy the functions.';
  return m;
}

/* ============================================================
   MANAGER — the campaign list (create / rename / delete / open).
   ============================================================ */
function CampaignManager({ onClose }){
  const [items, setItems]   = useS_camp(null);   // null = loading
  const [err, setErr]       = useS_camp('');
  const [busy, setBusy]     = useS_camp(false);
  const [title, setTitle]   = useS_camp('');
  const [editId, setEditId] = useS_camp('');
  const [editTitle, setEditTitle] = useS_camp('');
  const [confirmDel, setConfirmDel] = useS_camp('');
  const [openGame, setOpenGame]     = useS_camp(null);

  const load = async ()=>{
    setErr('');
    try{ setItems(await Games.list()); }
    catch(e){ setErr(e.message || 'Could not load campaigns.'); setItems([]); }
  };
  useE_camp(()=>{ load(); }, []);

  const create = async ()=>{
    if(busy || !title.trim()) return;
    setBusy(true); setErr('');
    try{ const g = await Games.create({ title }); setItems(list=> [g, ...(list||[])]); setTitle(''); }
    catch(e){ setErr(e.message || 'Could not create.'); }
    finally{ setBusy(false); }
  };
  const saveRename = async (id)=>{
    const t = editTitle.trim(); const prev = editId; setEditId('');
    if(!t || prev!==id) return;
    try{ const g = await Games.update(id, { title:t }); setItems(list=> list.map(x=> x.id===id ? g : x)); }
    catch(e){ setErr(e.message || 'Could not rename.'); }
  };
  const del = async (id)=>{
    setConfirmDel('');
    try{ await Games.remove(id); setItems(list=> list.filter(x=> x.id!==id)); }
    catch(e){ setErr(e.message || 'Could not delete.'); }
  };

  const fmt = (s)=>{ try{ return new Date(s).toLocaleDateString(undefined,{month:'short',day:'numeric',year:'numeric'}); }catch(_){ return ''; } };

  if(openGame) return <CampaignDetail game={openGame} onBack={()=>setOpenGame(null)} onClose={onClose}/>;

  return (
    <div className="camp-overlay" onClick={e=>{ if(e.target===e.currentTarget) onClose(); }}>
      <div className="camp-panel liquid-glass animate-fade-rise">
        <div className="camp-head">
          <h2 className="display">My Campaigns</h2>
          <button className="camp-x glass-btn" onClick={onClose} title="Close">✕</button>
        </div>
        <p className="camp-sub">Open a campaign to add art — items, NPCs, enemies, bosses &amp; maps.</p>

        <div className="camp-new">
          <input className="rm-input" placeholder="New campaign title" value={title} maxLength={80}
            onChange={e=>setTitle(e.target.value)} onKeyDown={e=>{ if(e.key==='Enter') create(); }}/>
          <button className="rm-go" disabled={busy || !title.trim()} onClick={create}>{busy ? 'Creating…' : '+ Create'}</button>
        </div>

        {err && <div className="rm-err">{err}</div>}

        <div className="camp-list">
          {items===null && <div className="camp-empty">Loading…</div>}
          {items && items.length===0 && <div className="camp-empty">No campaigns yet — name your first above.</div>}
          {items && items.map(g=>(
            <div key={g.id} className="camp-row">
              <button className="camp-row-main" onClick={()=>{ if(editId!==g.id) setOpenGame(g); }} title="Open campaign">
                <span className="camp-row-ico"><Icon name="book" size={20}/></span>
                <span className="camp-row-text">
                  {editId===g.id ? (
                    <input className="rm-input camp-edit" autoFocus value={editTitle} maxLength={80}
                      onClick={e=>e.stopPropagation()}
                      onChange={e=>setEditTitle(e.target.value)}
                      onKeyDown={e=>{ if(e.key==='Enter') saveRename(g.id); if(e.key==='Escape') setEditId(''); }}
                      onBlur={()=>saveRename(g.id)}/>
                  ) : (
                    <span className="camp-title">{g.title}</span>
                  )}
                  <span className="camp-meta">{g.is_published ? 'Published · ' : ''}{fmt(g.created_at)}</span>
                </span>
              </button>
              {confirmDel===g.id ? (
                <span className="camp-confirm">
                  <button className="tiny-btn danger" onClick={()=>del(g.id)}>Delete</button>
                  <button className="tiny-btn" onClick={()=>setConfirmDel('')}>Cancel</button>
                </span>
              ) : (
                <span className="camp-actions">
                  <button className="tiny-btn" onClick={()=>{ setEditId(g.id); setEditTitle(g.title); }}>Rename</button>
                  <button className="tiny-btn" onClick={()=>setConfirmDel(g.id)}>Delete</button>
                </span>
              )}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}
window.CampaignManager = CampaignManager;

/* ============================================================
   DETAIL — one campaign: category tabs + uploader + asset grid.
   ============================================================ */
function CampaignDetail({ game, onBack, onClose }){
  const [cat, setCat]       = useS_camp('item');
  const [assets, setAssets] = useS_camp(null);
  const [err, setErr]       = useS_camp('');
  const [uploading, setUploading] = useS_camp(false);
  const [confirmDel, setConfirmDel] = useS_camp('');
  const fileRef = useR_camp(null);

  const load = async ()=>{
    try{ setAssets(await Assets.listForGame(game.id)); }
    catch(e){ setErr(e.message || 'Could not load art.'); setAssets([]); }
  };
  useE_camp(()=>{
    load();
    let ch = null;
    try{ if(window.watchGameAssets) ch = watchGameAssets(game.id, ()=> load()); }catch(_){}
    return ()=>{ try{ if(ch && window.sb) sb.removeChannel(ch); }catch(_){} };
  }, [game.id]);

  const onFile = async (e)=>{
    const file = e.target.files && e.target.files[0];
    if(e.target) e.target.value = '';
    if(!file) return;
    const isVid = file.type && file.type.indexOf('video/')===0;
    const isImg = file.type && file.type.indexOf('image/')===0;
    setErr('');
    if(!isVid && !isImg) return setErr('Pick an image or a video file.');
    if(isImg && file.size > MAX_IMG) return setErr('Image too large — 20 MB cap.');
    if(isVid && file.size > MAX_VID) return setErr('Video too large — 200 MB cap.');
    setUploading(true);
    try{ await uploadAsset(file, { gameId:game.id, category:cat }); await load(); }
    catch(ex){ setErr(uploadErrMsg(ex)); }
    finally{ setUploading(false); }
  };
  const removeAsset = async (id)=>{
    setConfirmDel('');
    try{ await Assets.remove(id); setAssets(list=> (list||[]).filter(a=> a.id!==id)); }
    catch(e){ setErr(e.message || 'Could not delete.'); }
  };

  const shown = (assets || []).filter(a=> a.category===cat);
  const countFor = (c)=> (assets || []).filter(a=> a.category===c).length;
  const activeLabel = (ASSET_CATS.find(c=>c.id===cat) || {}).label || '';

  return (
    <div className="camp-overlay" onClick={e=>{ if(e.target===e.currentTarget) onClose(); }}>
      <div className="camp-panel detail liquid-glass animate-fade-rise">
        <div className="camp-head">
          <button className="camp-back glass-btn" onClick={onBack} title="All campaigns">←</button>
          <h2 className="display">{game.title}</h2>
          <button className="camp-x glass-btn" onClick={onClose} title="Close">✕</button>
        </div>

        <div className="camp-tabs">
          {ASSET_CATS.map(c=>(
            <button key={c.id} className={`camp-tab ${cat===c.id ? 'on' : ''}`} onClick={()=>{ setCat(c.id); setErr(''); }}>
              {c.label}{countFor(c.id) ? <span className="camp-tab-n">{countFor(c.id)}</span> : null}
            </button>
          ))}
        </div>

        <div className="camp-uploader">
          <button className="rm-go" disabled={uploading} onClick={()=>{ setErr(''); if(fileRef.current) fileRef.current.click(); }}>
            {uploading ? 'Uploading…' : `+ Add ${activeLabel.replace(/s$/,'')} art`}
          </button>
          <span className="camp-uphint">Image (≤20 MB) or video (≤200 MB)</span>
          <input ref={fileRef} type="file" accept="image/*,video/*" style={{display:'none'}} onChange={onFile}/>
        </div>

        {err && <div className="rm-err">{err}</div>}

        <div className="camp-grid">
          {assets===null && <div className="camp-empty">Loading…</div>}
          {assets && shown.length===0 && <div className="camp-empty">No {activeLabel.toLowerCase()} art yet — add your first above.</div>}
          {shown.map(a=>(
            <div key={a.id} className={`asset-card status-${a.status}`}>
              <div className="asset-thumb">
                {a.thumbnail_url
                  ? <img src={a.thumbnail_url} alt="" draggable="false"/>
                  : <span className="asset-ph"><Icon name={a.kind==='video' ? 'eye' : 'item'} size={22}/></span>}
                {a.kind==='video' && <span className="asset-kind">▶</span>}
              </div>
              <div className="asset-foot">
                <span className={`asset-badge b-${a.status}`}>{a.status}</span>
                {confirmDel===a.id ? (
                  <span className="asset-confirm">
                    <button className="tiny-btn danger" onClick={()=>removeAsset(a.id)}>Del</button>
                    <button className="tiny-btn" onClick={()=>setConfirmDel('')}>×</button>
                  </span>
                ) : (
                  <button className="tiny-btn" onClick={()=>setConfirmDel(a.id)}>Delete</button>
                )}
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}
window.CampaignDetail = CampaignDetail;
