/* ============================================================
   ROOM SYSTEM — landing (Create / Join / Display), lobby,
   Room Manager (connection dots + host reassignment), and the
   reconnection overlay. Runs on the MQTT transport behind
   window.Room (see store.jsx). Cinematic dark-fantasy styling.
   ============================================================ */
const { useState: useS_room, useEffect: useE_room, useRef: useR_room } = React;

const ROOM_KEYS = { code:'torchlit-room', role:'torchlit-role', name:'torchlit-name' };
function saveRoom(code, role, name){ try{
  localStorage.setItem(ROOM_KEYS.code, code||''); localStorage.setItem(ROOM_KEYS.role, role||'');
  if(name!=null) localStorage.setItem(ROOM_KEYS.name, name||''); }catch(_){}}
function loadRoom(){ try{ return {
  code: localStorage.getItem(ROOM_KEYS.code)||'', role: localStorage.getItem(ROOM_KEYS.role)||'',
  name: localStorage.getItem(ROOM_KEYS.name)||'' }; }catch(_){ return {code:'',role:'',name:''}; } }
function clearRoom(){ try{ localStorage.removeItem(ROOM_KEYS.code); localStorage.removeItem(ROOM_KEYS.role); }catch(_){}}

/* ---------- segmented room-code input ---------- */
function CodeInput({ value, onChange, len=5 }){
  const refs = useR_room([]);
  const chars = Array.from({length:len}, (_,i)=> (value[i]||''));
  const setAt = (i, ch)=>{
    ch = (ch||'').toUpperCase().replace(/[^A-Z0-9]/g,'').slice(-1);
    const arr = value.split(''); arr[i] = ch; const next = arr.join('').slice(0,len);
    onChange(next);
    if(ch && refs.current[i+1]) refs.current[i+1].focus();
  };
  const onKey = (i, e)=>{
    if(e.key==='Backspace' && !chars[i] && refs.current[i-1]){ refs.current[i-1].focus(); }
  };
  const onPaste = (e)=>{ const t=(e.clipboardData.getData('text')||'').toUpperCase().replace(/[^A-Z0-9]/g,'').slice(0,len); if(t){ e.preventDefault(); onChange(t); const k=Math.min(t.length,len-1); if(refs.current[k]) refs.current[k].focus(); } };
  return (
    <div className="code-input">
      {chars.map((c,i)=>(
        <input key={i} ref={el=>refs.current[i]=el} value={c} inputMode="text" maxLength={1}
          onChange={e=>setAt(i, e.target.value)} onKeyDown={e=>onKey(i,e)} onPaste={onPaste}
          aria-label={`Code letter ${i+1}`}/>
      ))}
    </div>
  );
}

/* ---------- password field with show/hide ---------- */
function PassField({ value, onChange, placeholder='Password', onEnter }){
  const [show, setShow] = useS_room(false);
  return (
    <div className="rm-pass">
      <input className="rm-input" type={show?'text':'password'} placeholder={placeholder} value={value}
        onChange={e=>onChange(e.target.value)} onKeyDown={e=>{ if(e.key==='Enter'&&onEnter) onEnter(); }}/>
      <button className="rm-pass-eye" type="button" onClick={()=>setShow(s=>!s)} title={show?'Hide':'Show'}>
        <Icon name={show?'eye':'eye'} size={16}/>{show?'Hide':'Show'}
      </button>
    </div>
  );
}

/* ============================================================
   LANDING — three glass paths, then their forms / lobby.
   onJoined({role, code, name}) fires once a room is entered.
   ============================================================ */
function RoomLanding({ onJoined }){
  const net = useNet();
  const [view, setView] = useS_room('paths');   // paths | create | join | display | lobby
  const [busy, setBusy] = useS_room(false);
  const [err, setErr] = useS_room('');
  // shared form fields
  const [name, setName] = useS_room(()=> loadRoom().name);
  const [pass, setPass] = useS_room('');
  const [code, setCode] = useS_room('');
  const [created, setCreated] = useS_room(null);  // {code} after host creates
  // master passcode that guards the host/display paths (players skip it)
  const MASTER_CODE = 'Abzu1818';
  const [gateTarget, setGateTarget] = useS_room('');  // 'create' | 'display' awaiting the master code
  const [gateVal, setGateVal] = useS_room('');
  const [gateErr, setGateErr] = useS_room(false);

  const go = (v)=>{ setErr(''); setView(v); };
  // Create Room & Display Screen require the master passcode first
  const openGated = (target)=>{ setErr(''); setGateVal(''); setGateErr(false); setGateTarget(target); setView('gate'); };
  const submitGate = ()=>{
    if(gateVal===MASTER_CODE){ const t=gateTarget; setGateVal(''); setGateTarget('');
      // host path lands on a choice (new vs. rejoin); display goes straight in
      go(t==='create' ? 'hostchoice' : t);
    }
    else { setGateErr(true); try{audio.play('wrong');}catch(_){} setTimeout(()=>setGateErr(false),500); }
  };
  // moderator resumes an existing game by code (re-adopts authority; no re-password)
  const doRejoinHost = async ()=>{
    if(code.trim().length<4) return setErr('Enter the game code.');
    setBusy(true); setErr('');
    const r = await Room.rejoinAsHost({ code, name:name.trim()||'Game Master' });
    setBusy(false);
    if(!r.ok){ setErr(r.error||'Could not rejoin.'); return; }
    saveRoom(r.code, 'host', name.trim()||'Game Master');
    onJoined({ role:'host', code:r.code, name:name.trim()||'Game Master' });
  };

  const doCreate = async ()=>{
    if(!name.trim()) return setErr('Enter your name.');
    if(pass.length<3) return setErr('Choose a password (3+ characters).');
    setBusy(true); setErr('');
    const r = await Room.createRoom({ password:pass, name:name.trim(), role:'host' });
    setBusy(false);
    if(!r.ok) return setErr(r.error||'Could not create the room.');
    saveRoom(r.code, 'host', name.trim());
    setCreated({ code:r.code, pass });
    setView('lobby');
  };
  const doJoin = async (role)=>{
    if(role==='player' && !name.trim()) return setErr('Enter your name.');
    if(code.trim().length<4) return setErr('Enter the full room code.');
    if(!pass) return setErr('Enter the room password.');
    setBusy(true); setErr('');
    const r = await Room.joinRoom({ code, password:pass, role, name:name.trim() });
    setBusy(false);
    if(!r.ok){ setErr(r.error||'Could not join.'); return; }
    saveRoom(r.code, role, name.trim());
    onJoined({ role, code:r.code, name:name.trim() });
  };

  /* ---- paths ---- */
  if(view==='paths') return (
    <div className="room-scene">
      <div className="room-veil-bg"></div>
      {window.Embers && <Embers count={20}/>}
      <div className="room-head">
        <h1 className="display flicker">Torchlit</h1>
        <p className="room-sub">Gather your party across any distance</p>
      </div>
      <div className="room-paths">
        <button className="room-path liquid-glass" onClick={()=>openGated('create')}>
          <span className="rp-ico"><Icon name="book" size={30}/></span>
          <span className="rp-t display">Create Room</span>
          <span className="rp-s">Host a new game &amp; invite your party</span>
        </button>
        <button className="room-path liquid-glass" onClick={()=>go('join')}>
          <span className="rp-ico"><Icon name="sword" size={30}/></span>
          <span className="rp-t display">Join Game</span>
          <span className="rp-s">Enter a code to take your seat</span>
        </button>
        <button className="room-path liquid-glass" onClick={()=>openGated('display')}>
          <span className="rp-ico"><Icon name="eye" size={30}/></span>
          <span className="rp-t display">Display Screen</span>
          <span className="rp-s">The shared board for the table</span>
        </button>
      </div>
    </div>
  );

  /* ---- master passcode gate (Create / Display) ---- */
  if(view==='gate') return (
    <RoomForm title="Keeper's Word" sub={`Required to ${gateTarget==='create'?'create a room':'open the display'}.`} onBack={()=>{ setGateTarget(''); go('paths'); }}>
      <label className="rm-label">Passcode
        <PassField value={gateVal} onChange={setGateVal} placeholder="Enter the keeper's word" onEnter={submitGate}/>
      </label>
      {gateErr && <div className="rm-err">That word holds no power here.</div>}
      <button className="rm-go" onClick={submitGate}>Continue →</button>
    </RoomForm>
  );

  /* ---- host choice: create new game OR rejoin an existing one (reconnect path) ---- */
  if(view==='hostchoice') return (
    <RoomForm title="Game Master" sub="Start fresh, or step back into a game in progress." onBack={()=>go('paths')}>
      <button className="rm-go" onClick={()=>go('create')}>✦ Create New Game</button>
      <div className="rm-or"><span>or rejoin a game you’re already running</span></div>
      <div className="rm-label">Game code<CodeInput value={code} onChange={setCode}/></div>
      <label className="rm-label">Your name
        <input className="rm-input" value={name} maxLength={24} placeholder="Game Master" onChange={e=>setName(e.target.value)}/>
      </label>
      {err && <div className="rm-err">{err}</div>}
      <button className="rm-go ghost" disabled={busy} onClick={doRejoinHost}>{busy?'Rejoining…':'↩ Rejoin as Moderator'}</button>
    </RoomForm>
  );

  /* ---- create ---- */
  if(view==='create') return (
    <RoomForm title="Create a Room" sub="You are the Game Master." onBack={()=>go('paths')}>
      <label className="rm-label">Your name
        <input className="rm-input" value={name} maxLength={24} placeholder="Game Master" onChange={e=>setName(e.target.value)}/>
      </label>
      <label className="rm-label">Room password
        <PassField value={pass} onChange={setPass} placeholder="Set a password" onEnter={doCreate}/>
      </label>
      {err && <div className="rm-err">{err}</div>}
      <button className="rm-go" disabled={busy} onClick={doCreate}>{busy?'Kindling…':'Create Room →'}</button>
    </RoomForm>
  );

  /* ---- join (player) ---- */
  if(view==='join') return (
    <RoomForm title="Join the Game" sub="Take your seat at the table." onBack={()=>go('paths')}>
      <label className="rm-label">Your name
        <input className="rm-input" value={name} maxLength={24} placeholder="Your hero's name" onChange={e=>setName(e.target.value)}/>
      </label>
      <div className="rm-label">Room code<CodeInput value={code} onChange={setCode}/></div>
      <label className="rm-label">Password
        <PassField value={pass} onChange={setPass} onEnter={()=>doJoin('player')}/>
      </label>
      {err && <div className="rm-err">{err}</div>}
      <button className="rm-go" disabled={busy} onClick={()=>doJoin('player')}>{busy?'Entering…':'Join →'}</button>
    </RoomForm>
  );

  /* ---- display (main) ---- */
  if(view==='display') return (
    <RoomForm title="Display Screen" sub="The shared board — view only." onBack={()=>go('paths')}>
      <div className="rm-label">Room code<CodeInput value={code} onChange={setCode}/></div>
      <label className="rm-label">Password
        <PassField value={pass} onChange={setPass} onEnter={()=>doJoin('main')}/>
      </label>
      {err && <div className="rm-err">{err}</div>}
      <button className="rm-go" disabled={busy} onClick={()=>doJoin('main')}>{busy?'Connecting…':'Connect →'}</button>
    </RoomForm>
  );

  /* ---- lobby (host, after create) ---- */
  if(view==='lobby' && created) return (
    <HostLobby created={created} onStart={()=> onJoined({ role:'host', code:created.code, name })}/>
  );
  return null;
}
window.RoomLanding = RoomLanding;

function RoomForm({ title, sub, onBack, children }){
  return (
    <div className="room-scene">
      <div className="room-veil-bg"></div>
      {window.Embers && <Embers count={16}/>}
      <div className="room-form liquid-glass animate-fade-rise">
        <button className="rm-back glass-btn" onClick={onBack}>← Back</button>
        <h2 className="display">{title}</h2>
        <p className="rm-formsub">{sub}</p>
        {children}
      </div>
    </div>
  );
}

/* ---------- host lobby: share code + live party + Start ---------- */
function HostLobby({ created, onStart }){
  const game = useGame();
  const presence = usePresence();
  const [copied, setCopied] = useS_room(false);
  const now = Date.now();
  const isConn = (devId)=> devId && (devId===Room.myDeviceId() || (presence[devId] && now-presence[devId].t<6000));
  const copy = ()=>{ try{ navigator.clipboard.writeText(created.code); setCopied(true); setTimeout(()=>setCopied(false),1500); }catch(_){}}

  return (
    <div className="room-scene">
      <div className="room-veil-bg"></div>
      {window.Embers && <Embers count={20}/>}
      <div className="room-form lobby liquid-glass animate-fade-rise">
        <h2 className="display">Your Room is Lit</h2>
        <p className="rm-formsub">Share this code &amp; password with your party.</p>
        <div className="lobby-code-plate">
          <span className="room-code">{created.code}</span>
          <div className="lobby-code-row">
            <span className="lobby-pw">🔑 {created.pass}</span>
            <button className="rm-mini glass-btn" onClick={copy}>{copied?'Copied!':'Copy code'}</button>
          </div>
        </div>
        <div className="lobby-party">
          <div className="lobby-party-h">Party <span className="lobby-count">{game.players.length}</span></div>
          {game.players.length===0 && <div className="lobby-empty">Waiting for heroes to join…</div>}
          {game.players.map(p=>(
            <div key={p.id} className="lobby-slot">
              <span className={`status-dot ${isConn(p.deviceId)?'connected':'disconnected'}`}></span>
              <span className="lobby-slot-name">{p.name}</span>
              <span className="lobby-slot-cls">{p.cls}</span>
            </div>
          ))}
        </div>
        <button className="rm-go" onClick={onStart}>Enter the Realm →</button>
      </div>
    </div>
  );
}

/* ============================================================
   ROOM MANAGER — host panel: slots, connection dots, reassign.
   Mounted inside the host screen.
   ============================================================ */
function RoomManager(){
  const game = useGame();
  const net = useNet();
  const presence = usePresence();
  const [reassignFor, setReassignFor] = useS_room('');
  const now = Date.now();
  const connectedIds = Object.keys(presence).filter(id=> now-presence[id].t<6000).concat([Room.myDeviceId()]);
  const isConn = (devId)=> devId && connectedIds.includes(devId);

  return (
    <div className="host-card liquid-glass">
      <h2 className="section-label"><Icon name="key" size={16}/> Room Manager</h2>
      <div className="rmgr-meta">
        <span className="rmgr-code">Code <b>{net.room || (net.meta&&net.meta.code) || '—'}</b></span>
        <span className={`rmgr-net net-${net.status}`}><span className="status-dot connected"></span>{net.status==='online'?'Live':net.status}</span>
      </div>
      <div className="rmgr-slots">
        {game.players.length===0 && <div className="muted" style={{fontSize:'.8rem'}}>No heroes have joined yet.</div>}
        {game.players.map(p=>{
          const conn = isConn(p.deviceId);
          return (
            <div key={p.id} className="rmgr-slot">
              <span className={`status-dot ${conn?'connected':'disconnected'}`}></span>
              <span className="rmgr-name">{p.name}</span>
              <span className="rmgr-cls">{p.cls}</span>
              <span className={`rmgr-state ${conn?'on':'off'}`}>{conn?'connected':'disconnected'}</span>
              <button className="tiny-btn" onClick={()=>setReassignFor(reassignFor===p.id?'':p.id)}>Reassign</button>
              {reassignFor===p.id && (
                <div className="rmgr-reassign">
                  <span className="rmgr-reassign-h">Bind to a connected device:</span>
                  {connectedIds.filter(id=>id!==p.deviceId).length===0 && <span className="muted" style={{fontSize:'.72rem'}}>No other devices online.</span>}
                  {connectedIds.filter(id=>id!==p.deviceId).map(id=>{
                    const pr = presence[id];
                    const label = id===Room.myDeviceId()?'This device (GM)':(pr&&pr.name)?pr.name:(id.slice(0,6)+'…');
                    return <button key={id} className="rmgr-dev" onClick={()=>{ Game.reassignCharacter(p.id, id); setReassignFor(''); }}>
                      <span className="status-dot connected"></span>{label} <em>{pr&&pr.role}</em></button>;
                  })}
                </div>
              )}
            </div>
          );
        })}
      </div>
      <p className="rmgr-hint">If a player loses their device or character, reassign their hero to a device that's connected now.</p>
    </div>
  );
}
window.RoomManager = RoomManager;

/* ---------- reconnection overlay ---------- */
function ReconnectVeil(){
  const net = useNet();
  const [slow, setSlow] = useS_room(false);
  useE_room(()=>{
    if(net.status==='online' || net.status==='idle'){ setSlow(false); return; }
    const t=setTimeout(()=>setSlow(true), 9000); return ()=>clearTimeout(t);
  }, [net.status]);
  if(net.status==='online' || net.status==='idle' || net.status==='off') return null;
  return (
    <div className="reconnect-veil">
      <div className="reconnect-box">
        <div className="reconnect-rune"></div>
        <div className="reconnect-t display">Reattuning to the realm…</div>
        {slow && <div className="reconnect-s">Still trying. If this persists, ask your host to reassign your character — room <b>{net.room}</b>.</div>}
      </div>
    </div>
  );
}
window.ReconnectVeil = ReconnectVeil;
