// ═══ GENESIS BUILD rbac-fase-a · 2026-07-10 ═══
// Tidal — Cabines: modais do fluxo de planejamento (aplicar plano, carregar plano, escolher modo de aplicação).

const PlanModeModal = ({ onAgora, onReativo, temLazy, onClose, lang }) => {
  const pt = lang === 'pt';
  const card = (icone, titulo, desc, cor, onClick, aviso) => (
    <div onClick={onClick} style={{cursor:'pointer',background:'var(--surface)',border:'1px solid var(--line-soft)',borderTop:`3px solid ${cor}`,borderRadius:16,padding:'18px 18px',transition:'box-shadow .15s, transform .1s'}}
      onMouseEnter={e=>{e.currentTarget.style.boxShadow='var(--shadow-md)';e.currentTarget.style.transform='translateY(-2px)';}}
      onMouseLeave={e=>{e.currentTarget.style.boxShadow='none';e.currentTarget.style.transform='none';}}>
      <div style={{display:'flex',alignItems:'center',gap:10,marginBottom:8}}>
        <span style={{fontSize:22}}>{icone}</span>
        <span style={{fontFamily:'var(--fs)',fontSize:19,color:'var(--ink)'}}>{titulo}</span>
      </div>
      <div style={{fontFamily:'var(--f)',fontSize:13,color:'var(--muted)',lineHeight:1.5}}>{desc}</div>
      {aviso && <div style={{marginTop:10,fontFamily:'var(--fm)',fontSize:10.5,color:'var(--rose)',background:'rgba(177,78,92,0.07)',border:'1px solid var(--rose)',borderRadius:8,padding:'6px 10px'}}>{aviso}</div>}
    </div>
  );
  return (
    <div onClick={onClose} style={{position:'fixed',inset:0,background:'rgba(31,42,46,0.5)',backdropFilter:'blur(6px)',zIndex:8100,display:'flex',alignItems:'flex-start',justifyContent:'center',padding:'8vh 16px',overflowY:'auto'}}>
      <div onClick={e=>e.stopPropagation()} style={{width:'100%',maxWidth:520,background:'var(--cream)',borderRadius:22,padding:'24px 26px',boxShadow:'var(--shadow-lg)',border:'1px solid var(--line-soft)'}}>
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:6}}>
          <div style={{fontFamily:'var(--fs)',fontSize:22}}>{pt?<>Como <em style={{fontStyle:'italic',color:'var(--accent)'}}>aplicar</em> o plano?</>:<>How to <em style={{fontStyle:'italic',color:'var(--accent)'}}>apply</em> the plan?</>}</div>
          <button className="btn btn-sm" onClick={onClose}>{pt?'fechar':'close'}</button>
        </div>
        <div style={{fontFamily:'var(--fm)',fontSize:11,color:'var(--muted)',marginBottom:16}}>{pt?'Dois jeitos bem diferentes — escolha com atenção.':'Two very different ways — choose carefully.'}</div>
        <div style={{display:'grid',gap:12}}>
          {card('⚡', pt?'Aplicar agora':'Apply now',
            pt?'Executa a troca na hora: embarca, desembarca e realoca todo mundo já. Use quando a mudança vai acontecer neste momento.':'Runs the change now: boards, disembarks and reallocates everyone immediately. Use when the change happens right now.',
            'var(--accent)', onAgora, null)}
          {card('🔄', pt?'Aplicar conforme embarcam':'Apply as they board',
            pt?'(embarque reativo) Arma o plano e deixa a mágica acontecer sozinha: conforme as pessoas embarcam e desembarcam, o sistema cumpre as trocas automaticamente e mostra as pendências num painel. Ideal pra preparar uma troca de turma que rola ao longo de dias.':'Arms the plan and lets it happen on its own: as people board and leave at the gangway, the system fulfills the moves automatically. Ideal to prepare a crew change over the coming days.',
            'var(--teal)', onReativo,
            temLazy ? (pt?'⚠ já existe um embarque reativo armado — este substitui o anterior':'⚠ a reactive embark is already armed — this replaces it') : null)}
        </div>
      </div>
    </div>
  );
};

const ApplyPlanModal = ({ planAssign, usersById, users, planPool, onClose, onApplied, token, toast, lang, isMobile }) => {
  const rows0 = Object.entries(planAssign)
    .map(([berthId, userId]) => ({ berthId, user: usersById[userId] || usersById[String(userId)] }))
    .filter(r => r.user);
  const companies = [...new Set(rows0.map(r => r.user.empresa).filter(Boolean))].sort();

  const [q, setQ] = useState('');
  const [fCompany, setFCompany] = useState('all');
  const [fRole, setFRole] = useState('all');
  const [selected, setSelected] = useState(() => new Set(rows0.filter(r => r.user.role !== 'guest').map(r => r.user.id)));
  const [applying, setApplying] = useState(false);
  const [report, setReport] = useState(null);

  const aboardOf = (u) => u.status_bordo === 'a_bordo' || u.status === 'a_bordo';
  const blockedOf = (u) => u.role === 'guest';

  const filtered = rows0.filter(({ user }) => {
    const ql = q.toLowerCase();
    if (q && !((user.nome||'').toLowerCase().includes(ql) || (user.empresa||'').toLowerCase().includes(ql) || (user.genesis_id||'').toLowerCase().includes(ql))) return false;
    if (fCompany !== 'all' && user.empresa !== fCompany) return false;
    if (fRole !== 'all' && user.role !== fRole) return false;
    return true;
  });

  const toggle = (uid) => setSelected(s => { const n = new Set(s); n.has(uid) ? n.delete(uid) : n.add(uid); return n; });
  const selectableIds = filtered.filter(r => !blockedOf(r.user)).map(r => r.user.id);
  const allSelected = selectableIds.length && selectableIds.every(id => selected.has(id));
  const toggleAll = () => setSelected(s => { const n = new Set(s); if (allSelected) selectableIds.forEach(id=>n.delete(id)); else selectableIds.forEach(id=>n.add(id)); return n; });

  const willBoard = rows0.filter(r => selected.has(r.user.id) && !aboardOf(r.user) && !blockedOf(r.user)).length;
  const already   = rows0.filter(r => selected.has(r.user.id) && aboardOf(r.user) && !blockedOf(r.user)).length;
  const blockedCount = rows0.filter(r => blockedOf(r.user)).length;

  // Diff de estado completo: quem SAI (a bordo, fora do plano) e quem TROCA de cabine
  const cabDe = (berthId) => String(berthId).split('-')[0];
  const planUserIds = new Set([...(planPool || [])]);
  rows0.forEach(r => planUserIds.add(r.user.id));
  const willLeave = (users || []).filter(u => (u.status_bordo === 'a_bordo') && u.role !== 'guest' && u.role !== 'admin' && !planUserIds.has(u.id));
  const willMove = rows0.filter(r => aboardOf(r.user) && r.user.cabine_atual && cabDe(r.berthId) !== String(r.user.cabine_atual));
  const [desembarcarFora, setDesembarcarFora] = useState(true);

  const apply = async () => {
    const items = rows0.filter(r => selected.has(r.user.id) && !blockedOf(r.user)).map(r => ({ user_id: r.user.id, berth_id: r.berthId }));
    const disembark = desembarcarFora ? willLeave.map(u => u.id) : [];
    if (!items.length && !disembark.length) { toast.push({icon:'x', title: lang==='pt'?'Nada para aplicar':'Nothing to apply'}); return; }
    setApplying(true);
    try {
      const res = await fetch('/api/cabins/plans/apply', { method:'POST', headers:{ 'Content-Type':'application/json', Authorization:`Bearer ${token()}` }, body: JSON.stringify({ items, disembark }) });
      const data = await res.json();
      if (res.ok) { setReport(data); toast.push({icon:'check', title: lang==='pt'?'Plano aplicado':'Plan applied'}); }
      else toast.push({icon:'x', title: data.error || 'Erro ao aplicar'});
    } catch(e) { toast.push({icon:'x', title:'Erro de conexão'}); }
    finally { setApplying(false); }
  };

  const RStat = ({n,l,c}) => (
    <div style={{flex:1,minWidth:90,background:'var(--surface)',border:'1px solid var(--line-soft)',borderTop:`3px solid ${c}`,borderRadius:12,padding:'10px 14px'}}>
      <div style={{fontFamily:'var(--fs)',fontSize:22,fontWeight:500,lineHeight:1}}>{n}</div>
      <div className="t-eyebrow" style={{marginTop:3,fontSize:9}}>{l}</div>
    </div>
  );

  return (
    <div onClick={onClose} style={{position:'fixed',inset:0,background:'rgba(31,42,46,0.4)',backdropFilter:'blur(6px)',zIndex:8000,display:'flex',alignItems:'flex-start',justifyContent:'center',padding:'5vh 16px',overflowY:'auto'}}>
      <div onClick={e=>e.stopPropagation()} style={{width:'100%',maxWidth:isMobile?'100%':640,maxHeight:'90vh',background:'var(--cream)',borderRadius:isMobile?18:22,display:'flex',flexDirection:'column',boxShadow:'var(--shadow-lg)',border:'1px solid var(--line-soft)',overflow:'hidden'}}>
        <div style={{flex:1,overflowY:'auto',padding:'28px 30px 20px'}}>
          <div style={{display:'flex',justifyContent:'space-between',alignItems:'baseline',marginBottom:6}}>
            <div className="t-eyebrow">{lang==='pt'?'planejamento':'planning'}</div>
            <button className="btn ghost" onClick={onClose}><Icon n="x" size={14}/></button>
          </div>
          <div style={{fontFamily:'var(--fs)',fontSize:26,letterSpacing:'-0.4px',marginBottom:14}}>
            {lang==='pt'?<>Aplicar ao <em style={{fontStyle:'italic',color:'var(--accent)'}}>estado atual.</em></>:<>Apply to <em style={{fontStyle:'italic',color:'var(--accent)'}}>live.</em></>}
          </div>

          {report ? (
            <div>
              <div style={{display:'flex',gap:10,marginBottom:16,flexWrap:'wrap'}}>
                <RStat n={report.assigned.length} l={lang==='pt'?'atribuídos':'assigned'} c="var(--leaf)"/>
                <RStat n={report.boarded.length}  l={lang==='pt'?'embarcados':'boarded'}  c="var(--teal)"/>
                <RStat n={(report.disembarked||[]).length} l={lang==='pt'?'desembarcados':'disembarked'} c="var(--rose)"/>
                <RStat n={report.skipped.length}  l={lang==='pt'?'pulados':'skipped'}    c="var(--accent)"/>
              </div>
              {report.skipped.length > 0 && (
                <div>
                  <div className="t-eyebrow" style={{marginBottom:6}}>{lang==='pt'?'não aplicados':'not applied'}</div>
                  {report.skipped.map((s,i)=>((
                    <div key={i} style={{fontSize:12,color:'var(--muted)',padding:'5px 0',borderBottom:'1px dashed var(--line-soft)'}}>
                      <b style={{color:'var(--ink)'}}>{s.nome}</b> — {s.reason}
                    </div>
                  )))}
                </div>
              )}
              {report.skipped.length === 0 && (
                <div className="empty" style={{padding:20}}>{lang==='pt'?'tudo aplicado com sucesso ✓':'all applied successfully ✓'}</div>
              )}
            </div>
          ) : (
            <>
              <div style={{display:'flex',gap:8,flexWrap:'wrap',marginBottom:12}}>
                <input className="input" placeholder={lang==='pt'?'buscar nome/empresa/ID…':'search name/company/ID…'} value={q} onChange={e=>setQ(e.target.value)} style={{flex:'1 1 160px',boxSizing:'border-box'}}/>
                <select className="input select" value={fCompany} onChange={e=>setFCompany(e.target.value)} style={{minWidth:140,boxSizing:'border-box'}}>
                  <option value="all">{lang==='pt'?'Todas as empresas':'All companies'}</option>
                  {companies.map(c=><option key={c} value={c}>{c}</option>)}
                </select>
                <select className="input select" value={fRole} onChange={e=>setFRole(e.target.value)} style={{minWidth:130,boxSizing:'border-box'}}>
                  <option value="all">{lang==='pt'?'Todas as classes':'All roles'}</option>
                  <option value="crew">{lang==='pt'?'Tripulação':'Crew'}</option>
                  <option value="ops">{lang==='pt'?'Operações':'Operations'}</option>
                  <option value="catering">Catering</option>
                  <option value="terceirizada">{lang==='pt'?'Terceirizada':'Third-party'}</option>
                  <option value="admin">{lang==='pt'?'Administração':'Admin'}</option>
                </select>
              </div>

              <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:8,padding:'0 2px'}}>
                <label style={{display:'flex',alignItems:'center',gap:8,cursor:'pointer',fontFamily:'var(--fm)',fontSize:12,color:'var(--muted)'}}>
                  <input type="checkbox" checked={!!allSelected} onChange={toggleAll}/>
                  {lang==='pt'?'selecionar todos':'select all'} ({selectableIds.length})
                </label>
                <span style={{fontFamily:'var(--fm)',fontSize:11,color:'var(--muted-2)'}}>{filtered.length} {lang==='pt'?'no plano':'in plan'}</span>
              </div>

              <div style={{border:'1px solid var(--line-soft)',borderRadius:14,overflow:'hidden',marginBottom:14}}>
                {filtered.map(({ user, berthId }, i) => {
                  const aboard = aboardOf(user), blocked = blockedOf(user);
                  return (
                    <label key={user.id} style={{display:'flex',alignItems:'center',gap:10,padding:'9px 12px',borderTop:i?'1px solid var(--line-soft)':'none',background:i%2?'var(--cream)':'transparent',cursor:blocked?'not-allowed':'pointer',opacity:blocked?0.55:1}}>
                      <input type="checkbox" disabled={blocked} checked={selected.has(user.id)} onChange={()=>toggle(user.id)}/>
                      <Avatar user={user} size="sm"/>
                      <div style={{flex:1,minWidth:0}}>
                        <div style={{fontSize:13,fontWeight:500,whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>{user.nome}</div>
                        <div style={{fontSize:11,color:'var(--muted)',fontFamily:'var(--fm)'}}>{user.empresa||'—'} · {aboard && user.cabine_atual && cabDe(berthId) !== String(user.cabine_atual)
                          ? <>{user.cabine_atual} <span style={{color:'var(--teal)'}}>→ {berthId}</span></>
                          : <>{lang==='pt'?'vaga':'berth'} {berthId}</>}</div>
                      </div>
                      <span style={{fontFamily:'var(--fm)',fontSize:9.5,letterSpacing:0.4,textTransform:'uppercase',padding:'3px 8px',borderRadius:8,whiteSpace:'nowrap',
                        background: blocked?'rgba(217,105,75,0.12)':aboard?'rgba(123,182,126,0.16)':'rgba(232,180,83,0.18)',
                        color: blocked?'var(--accent-2)':aboard?'#2F5C3D':'#8B6313'}}>
                        {blocked?(lang==='pt'?'bloqueado':'blocked'):aboard?(lang==='pt'?'a bordo':'aboard'):(lang==='pt'?'vai embarcar':'will board')}
                      </span>
                    </label>
                  );
                })}
                {!filtered.length && <div className="empty" style={{padding:20}}>{lang==='pt'?'ninguém no filtro':'nobody in filter'}</div>}
              </div>

              <div style={{fontFamily:'var(--fm)',fontSize:12,color:'var(--muted)'}}>
                {selected.size} {lang==='pt'?'selecionados':'selected'} · {willBoard} {lang==='pt'?'embarcarão':'will board'} · {already} {lang==='pt'?'já a bordo':'already aboard'}{blockedCount?` · ${blockedCount} ${lang==='pt'?'bloqueados (visitante)':'blocked (visitor)'}`:''}
              </div>

              {willMove.length > 0 && (
                <div style={{marginTop:12,padding:'10px 14px',background:'var(--sky-soft)',border:'1px solid var(--sky)',borderRadius:12}}>
                  <div className="t-eyebrow" style={{marginBottom:6,color:'var(--teal)'}}>🔀 {willMove.length} {lang==='pt'?'trocam de cabine':'change cabin'}</div>
                  <div style={{fontFamily:'var(--fm)',fontSize:11.5,color:'var(--ink)',display:'grid',gap:3}}>
                    {willMove.map((r,i)=>(<div key={i}>{r.user.nome}: <b>{r.user.cabine_atual}</b> → <b style={{color:'var(--teal)'}}>{cabDe(r.berthId)}</b></div>))}
                  </div>
                </div>
              )}

              {willLeave.length > 0 && (
                <div style={{marginTop:12,padding:'10px 14px',background:'rgba(177,78,92,0.06)',border:'1px solid var(--rose)',borderRadius:12}}>
                  <label style={{display:'flex',alignItems:'center',gap:10,cursor:'pointer'}}>
                    <div onClick={()=>setDesembarcarFora(v=>!v)} style={{width:38,height:22,borderRadius:999,flexShrink:0,background:desembarcarFora?'var(--rose)':'var(--cream-3)',position:'relative',transition:'background .15s'}}>
                      <div style={{position:'absolute',top:2,left:desembarcarFora?18:2,width:18,height:18,borderRadius:'50%',background:'#fff',transition:'left .15s'}}/>
                    </div>
                    <div>
                      <div style={{fontFamily:'var(--fm)',fontSize:12.5,color:'var(--rose)',fontWeight:600}}>🚪 {lang==='pt'?`Desembarcar ${willLeave.length} que ficou fora do plano`:`Disembark ${willLeave.length} left out of the plan`}</div>
                      <div style={{fontFamily:'var(--fm)',fontSize:10.5,color:'var(--muted)',marginTop:2}}>{willLeave.slice(0,6).map(u=>u.nome).join(', ')}{willLeave.length>6?` +${willLeave.length-6}`:''}</div>
                    </div>
                  </label>
                </div>
              )}
            </>
          )}
        </div>

        <div style={{padding:'14px 30px',borderTop:'1px solid var(--line-soft)',display:'flex',gap:10,justifyContent:'flex-end',background:'var(--surface-2)'}}>
          {report ? (
            <button className="btn btn-primary" onClick={onApplied}>{lang==='pt'?'Concluir':'Done'}</button>
          ) : (
            <>
              <button className="btn" onClick={onClose}>{lang==='pt'?'Cancelar':'Cancel'}</button>
              <button className="btn btn-primary" onClick={apply} disabled={applying}>
                <Icon n="check" size={14}/>{applying?(lang==='pt'?'Aplicando…':'Applying…'):(lang==='pt'?'Aplicar agora':'Apply now')}
              </button>
            </>
          )}
        </div>
      </div>
    </div>
  );
};

// ─── Modal: carregar plano salvo ───
const LoadPlanModal = ({ plans, currentPlanId, onLoad, onDelete, onClose, lang, isMobile }) => {
  const fmtDate = (s) => { try { return new Date(s).toLocaleDateString(lang==='pt'?'pt-BR':'en-US', {day:'2-digit',month:'short'}); } catch(_) { return ''; } };
  return (
    <div onClick={onClose} style={{position:'fixed',inset:0,background:'rgba(31,42,46,0.4)',backdropFilter:'blur(6px)',zIndex:8000,display:'flex',alignItems:'flex-start',justifyContent:'center',padding:'5vh 16px',overflowY:'auto'}}>
      <div onClick={e=>e.stopPropagation()} style={{width:'100%',maxWidth:isMobile?'100%':520,maxHeight:'90vh',background:'var(--cream)',borderRadius:isMobile?18:22,display:'flex',flexDirection:'column',boxShadow:'var(--shadow-lg)',border:'1px solid var(--line-soft)',overflow:'hidden'}}>
        <div style={{flex:1,overflowY:'auto',padding:'28px 30px 20px'}}>
          <div style={{display:'flex',justifyContent:'space-between',alignItems:'baseline',marginBottom:6}}>
            <div className="t-eyebrow">{lang==='pt'?'planejamento':'planning'}</div>
            <button className="btn ghost" onClick={onClose}><Icon n="x" size={14}/></button>
          </div>
          <div style={{fontFamily:'var(--fs)',fontSize:26,letterSpacing:'-0.4px',marginBottom:16}}>
            {lang==='pt'?<>Carregar <em style={{fontStyle:'italic',color:'var(--accent)'}}>plano.</em></>:<>Load <em style={{fontStyle:'italic',color:'var(--accent)'}}>plan.</em></>}
          </div>
          {!plans.length ? (
            <div className="empty" style={{padding:30}}>{lang==='pt'?'nenhum plano salvo ainda':'no saved plans yet'}</div>
          ) : (
            <div style={{display:'flex',flexDirection:'column',gap:8}}>
              {plans.map(p=>((
                <div key={p.id} style={{display:'flex',alignItems:'center',gap:10,padding:'12px 14px',borderRadius:14,border:`1px solid ${p.id===currentPlanId?'var(--accent)':'var(--line-soft)'}`,background:'var(--surface)'}}>
                  <div style={{flex:1,minWidth:0,cursor:'pointer'}} onClick={()=>onLoad(p.id)}>
                    <div style={{fontSize:14,fontWeight:500}}>{p.nome}{p.id===currentPlanId && <span style={{fontSize:10,color:'var(--accent)',marginLeft:8,fontFamily:'var(--fm)'}}>{lang==='pt'?'atual':'current'}</span>}</div>
                    <div style={{fontSize:11,color:'var(--muted)',fontFamily:'var(--fm)',marginTop:2}}>
                      {p.itens} {lang==='pt'?'pessoas':'people'}{p.autor_nome?` · ${p.autor_nome}`:''}{p.atualizado_em?` · ${fmtDate(p.atualizado_em)}`:''}
                    </div>
                  </div>
                  <button className="btn btn-sm" onClick={()=>onLoad(p.id)}>{lang==='pt'?'Abrir':'Open'}</button>
                  <button className="btn btn-sm ghost" onClick={()=>onDelete(p.id)} style={{color:'var(--accent-2)'}} title={lang==='pt'?'Excluir':'Delete'}><Icon n="x" size={12}/></button>
                </div>
              )))}
            </div>
          )}
        </div>
        <div style={{padding:'14px 30px',borderTop:'1px solid var(--line-soft)',display:'flex',justifyContent:'flex-end',background:'var(--surface-2)'}}>
          <button className="btn" onClick={onClose}>{lang==='pt'?'Fechar':'Close'}</button>
        </div>
      </div>
    </div>
  );
};

Object.assign(window, { PlanModeModal, ApplyPlanModal, LoadPlanModal });
