/* Console partenaire — compte (design dev-prod.jsx, dev-kyc.jsx, dev-pages-b.jsx) : Entreprise (dossier de
   production en 6 étapes, vérification d'identité, profil une fois approuvé), Équipe, Paramètres, Aide
   (statut des services, incidents, tickets de support). */
const STEPS_P = ['Entreprise','Représentant légal','Vérification d\'identité','Documents','Contacts et tests','Récapitulatif'];
const PREFIXES_P = ['entreprise.','representant.','identite','document.','contacts.'];
const FORMES = [['','Choisir…'],['SA','Société anonyme (SA)'],['SARL','SARL'],['SAS','SAS'],['SUARL','SUARL'],['GIE','GIE'],['autre','Autre']];
const PIECES = [['cni_cedeao','Carte d\'identité CEDEAO','identification-card','Recto et verso'],['passeport','Passeport','book-open','Page photo uniquement'],['carte_sejour','Carte de séjour','identification-badge','Recto et verso']];
const LIB_MANQ = (x) => x.replace('entreprise.', 'Entreprise : ').replace('representant.', 'Représentant : ').replace(/^document\./, 'Document : ').replace('contacts.', 'Contacts : ').replace('tests_sandbox', 'Tests sandbox').replace(/^identite$/, 'Vérification d\'identité')
  .replace('raison_sociale','raison sociale').replace('forme_juridique','forme juridique').replace('adresse_siege','adresse du siège').replace('date_naissance','date de naissance').replace('email_alertes','email des alertes').replace('urgence','contact d\'urgence');

function StageBanner({d, onFix}){
  const nbCorr = (d.documents||[]).filter(x=>x.statut==='a_corriger').length;
  const t = {draft:['mute','Brouillon','Complétez les 6 étapes puis envoyez votre dossier. Chaque étape s\'enregistre quand vous passez à la suivante.'], submitted:['info',`Dossier soumis${d.soumis_le?` le ${D(d.soumis_le, false)}`:''}`,'Nous accusons réception. La revue commence sous 1 jour ouvré.'], review:['info','Dossier en revue','Un analyste LeMultiservice vérifie vos documents. Délai habituel : 2 à 3 jours ouvrés.'],
    info:['warn','Informations demandées', nbCorr ? `${nbCorr} document${nbCorr>1?'s sont':' est'} à corriger. Déposez les nouvelles versions puis renvoyez le dossier.` : 'Corrigez les éléments signalés puis renvoyez le dossier.'], approved:['ok','Dossier approuvé','La production est déverrouillée. Créez votre première clé live.'],
    refused:['bad','Dossier refusé', d.motif_refus ? `Motif : ${d.motif_refus} Vous pouvez corriger et soumettre à nouveau.` : 'Vous pouvez corriger et soumettre à nouveau.'], modification:['info','Modification en cours','La production reste active pendant la revue de vos modifications.']}[d.stage] || ['mute', d.stage, ''];
  const s = STAGES[d.stage] || STAGES.draft; const etapeRevue = d.stage==='review' ? 1 : 0;
  return <div role="status" style={{display:'flex', alignItems:'center', gap:14, padding:'16px 20px', borderRadius:22, background:TN[t[0]][0], flexWrap:'wrap'}}>
    <Tile icon={s[2]} s={42} c={TN[t[0]][1]} bg={V.card} fill/><span style={{flex:1, minWidth:220}}><span style={{display:'block', fontWeight:800, fontSize:15, color:TN[t[0]][1]}}>{t[1]}</span><span style={{display:'block', marginTop:2, fontWeight:500, fontSize:13, color:V.ink2, lineHeight:1.5}}>{t[2]}</span></span>
    {(d.stage==='info'||d.stage==='refused') && onFix && <Btn onClick={onFix} icon="pencil-simple">Corriger le dossier</Btn>}
    {['submitted','review'].includes(d.stage) && <div style={{display:'flex', gap:6, flexWrap:'wrap'}}>{['Soumis','En revue','Décision'].map((x,i)=><span key={x} style={{display:'flex', alignItems:'center', gap:5, fontSize:12, fontWeight:700, color:i<=etapeRevue?V.info:V.ink3}}><I n={i<=etapeRevue?'check-circle':'circle'} s={15} fill={i<=etapeRevue}/>{x}{i<2 && <span style={{width:14, height:1, background:V.line}}></span>}</span>)}</div>}
  </div>;
}

// Champs d'une section, enregistrés au passage à l'étape suivante
function Champs({def, v, set, ro}){
  return <Grid cols="1fr 1fr">{def.map(([k, l, type, opt])=><Field key={k} label={l} opt={opt}>{Array.isArray(type)
    ? <Sel label={l} opts={type} value={v[k]||''} onChange={x=>set({...v, [k]:x})} style={ro?{background:V.sub, color:V.ink2, pointerEvents:'none'}:undefined}/>
    : <Inp type={type||'text'} value={v[k]||''} disabled={ro} onChange={e=>set({...v, [k]:e.target.value})} style={ro?{background:V.sub, color:V.ink2}:undefined}/>}</Field>)}</Grid>;
}
const DEF_ENT = [['raison_sociale','Raison sociale'],['forme_juridique','Forme juridique',FORMES],['ninea','NINEA'],['rccm','RCCM'],['adresse_siege','Adresse du siège'],['site_web','Site web','url',true]];
const DEF_REP = [['prenom','Prénom'],['nom','Nom'],['fonction','Fonction'],['email','Email','email'],['telephone','Téléphone','tel'],['date_naissance','Date de naissance','date']];
const DEF_CON = [['technique','Contact technique','',false],['urgence','Contact d\'urgence (24/7)'],['finance','Contact finance'],['email_alertes','Email des alertes','email']];

function Prod(){
  const A = useApp(), m = useMob(); const toast = useToast(); const proprio = A.peut('proprio');
  const [d0, recharger, etat] = useDonnees(() => api('GET', 'dossier'), []);
  const [d, setD] = React.useState(null); React.useEffect(()=>{ if(d0) setD(d0); }, [d0]);
  const [s, setS] = React.useState(null), [edit, setEdit] = React.useState(false), [ok, setOk] = React.useState(false), [occ, setOcc] = React.useState(false), [err, setErr] = React.useState(null);
  const [ent, setEnt] = React.useState({}), [rep, setRep] = React.useState({}), [con, setCon] = React.useState({});
  React.useEffect(()=>{ if(!d) return; setEnt(d.entreprise||{}); setRep(d.representant||{}); setCon(d.contacts||{}); if(s==null) setS(d.stage==='info'||d.stage==='refused' ? 3 : ['submitted','review'].includes(d.stage) ? 5 : 0); }, [d]);
  if(etat.erreur) return <Page><PageHead title="Entreprise"/><ErreurCarte e={etat.erreur} recharger={recharger}/></Page>;
  if(!d || s==null) return <Page><Card><Skel h={56}/></Card><Skel h={70} r={22}/><Grid cols="260px minmax(0,1fr)"><Card><Skel h={260}/></Card><Card><Skel h={260}/></Card></Grid></Page>;
  const maj = (x) => { setD(x); A.rafraichir(); };
  if(d.stage==='approved' && !edit) return <CompanyProfile d={d} onEdit={async()=>{ try { maj(await api('POST', 'dossier/modifier')); setEdit(true); setS(0); } catch(e){ toast(e.message, 'bad'); } }}/>;
  const ro = !d.modifiable || !proprio;
  const manque = (i) => i<5 && (d.manquants||[]).some(x=>x.startsWith(PREFIXES_P[i]) || (i===4 && x==='tests_sandbox'));
  const sale = (a, b) => Object.keys(a).some(k=>(a[k]||'') !== ((b||{})[k]||''));
  const enregistrer = async () => { if(ro) return true; const corps = s===0 && sale(ent, d.entreprise) ? {entreprise:ent} : s===1 && sale(rep, d.representant) ? {representant:rep} : s===4 && sale(con, d.contacts) ? {contacts:con} : null;
    if(!corps) return true; setOcc(true); setErr(null); try { maj(await api('PATCH', 'dossier', corps)); toast('Enregistré'); setOcc(false); return true; } catch(e){ setErr(e); setOcc(false); return false; } };
  const aller2 = async (k) => { if(await enregistrer()) { setS(k); setErr(null); } };
  const soumettre = async () => { setOcc(true); setErr(null); try { const r = await api('POST', 'dossier/soumettre', {certifie:true}); maj(r); A.rechargerMoi(); setEdit(false); toast('Dossier envoyé'); } catch(e){ setErr(e); } setOcc(false); };
  const tests = d.tests_sandbox || [];
  const docsReq = (d.documents||[]).filter(x=>x.requis), docsOk = docsReq.filter(x=>['depose','valide'].includes(x.statut)).length;
  const idLib = {a_faire:'À faire', soumise:'Pièces envoyées, vérification pendant la revue', verifiee:'Identité vérifiée', echouee:'Vérification échouée'}[d.identite?.statut] || d.identite?.statut;
  const body = [
    <div key="e" style={{display:'flex', flexDirection:'column', gap:16}}><LogoEntreprise d={d} ro={ro} onFait={maj}/><Champs def={DEF_ENT} v={ent} set={setEnt} ro={ro}/></div>,
    <Champs key="r" def={DEF_REP} v={rep} set={setRep} ro={ro}/>,
    <KycFlow key="k" d={d} ro={ro} onFait={maj}/>,
    <Documents key="d" d={d} ro={ro} onFait={maj}/>,
    <div key="t" style={{display:'flex', flexDirection:'column', gap:16}}>
      <Champs def={DEF_CON} v={con} set={setCon} ro={ro}/><Muted style={{fontSize:12, marginTop:-6}}>Pour chaque contact : nom et téléphone, par exemple « Mamadou Ndiaye · +221 77 000 00 00 ».</Muted>
      <div style={{display:'flex', alignItems:'center', gap:10, padding:'12px 14px', borderRadius:16, background:V.sub, flexWrap:'wrap'}}><I n="code" s={19} c={V.accD}/><span style={{flex:1, minWidth:200, fontSize:13, fontWeight:600, color:V.ink2}}>Les IP autorisées et les webhooks se configurent dans les Paramètres développeur.</span><Btn kind="secondary" sm onClick={()=>A.go('devset')}>Ouvrir</Btn></div>
      <div style={{padding:16, borderRadius:20, background:V.sub}}><div style={{display:'flex', alignItems:'center', gap:8, marginBottom:10, flexWrap:'wrap'}}><I n="flask" s={18} c={V.accD}/><span style={{flex:1, fontWeight:800, fontSize:14}}>Tests sandbox</span><Muted style={{fontSize:12}}>Calculé depuis votre journal</Muted></div>
        {tests.map(c=><div key={c.code} style={{display:'flex', alignItems:'center', gap:10, padding:'8px 0', flexWrap:'wrap'}}><I n={c.fait?'check-circle':'circle-dashed'} s={20} c={c.fait?V.acc:V.ink3} fill={c.fait}/><span style={{flex:1, minWidth:160, fontWeight:600, fontSize:13.5, color:c.fait?V.ink:V.ink3}}>{c.code==='solde_insuffisant'?<>Gestion d'une erreur <Mono>solde_insuffisant</Mono></>:c.libelle}</span>{!c.fait && <Btn kind="ghost" sm onClick={()=>A.go('docs', c.code==='solde_insuffisant'?'errors':c.code==='annulation'?'annul':c.code==='contrat'?'contrat':'devis')}>Comment faire</Btn>}</div>)}</div></div>,
    <div key="s" style={{display:'flex', flexDirection:'column', gap:14}}>
      {(d.manquants||[]).length ? <Notice tone="warn" title={`${d.manquants.length} élément${d.manquants.length>1?'s':''} à compléter`}><span style={{display:'flex', flexWrap:'wrap', gap:6, marginTop:4}}>{d.manquants.map(x=><span key={x} style={{fontSize:12, fontWeight:600, padding:'3px 8px', borderRadius:8, background:V.card}}>{LIB_MANQ(x)}</span>)}</span></Notice> : <Notice tone="ok" title="Dossier complet">Tout est prêt pour l'envoi.</Notice>}
      {[['Entreprise',[ent.raison_sociale, ent.forme_juridique, ent.ninea && `NINEA ${ent.ninea}`].filter(Boolean).join(' · ') || 'À compléter',0],['Représentant légal',[rep.prenom, rep.nom, rep.fonction && `· ${rep.fonction}`].filter(Boolean).join(' ') || 'À compléter',1],['Vérification d\'identité',idLib,2],['Documents',`${docsOk} sur ${docsReq.length} déposés`,3],['Contacts et tests',`${['technique','urgence','finance'].filter(k=>(con[k]||'').trim()).length} contacts sur 3 · ${tests.filter(c=>c.fait).length}/${tests.length} tests réussis`,4]].map(r=>{ const man = manque(r[2]);
        return <div key={r[0]} style={{display:'flex', alignItems:'center', gap:12, padding:'14px 16px', borderRadius:18, border:`1px solid ${man?'var(--warnLine)':V.line}`}}>
        <I n={man?'warning-circle':'check-circle'} s={20} c={man?V.warn:V.acc} fill/><span style={{flex:1, minWidth:0}}><span style={{display:'block', fontWeight:700, fontSize:13.5}}>{r[0]}</span><span style={{display:'block', fontSize:12.5, color:V.ink3}}>{r[1]}</span></span><Btn kind="ghost" sm onClick={()=>aller2(r[2])}>{ro?'Voir':'Modifier'}</Btn></div>; })}
      {!ro && <Check on={ok} set={setOk}>Je certifie l'exactitude des informations et j'accepte les conditions générales de partenariat LeMultiservice.</Check>}
    </div>,
  ];
  return <Page max={1160}>
    <Card pad={m?16:22} style={{display:'flex', alignItems:'center', gap:16, flexWrap:'wrap'}}>
      <CoLogo s={m?48:56} nom={ent.raison_sociale || A.moi.entreprise.nom} logo={d.logo?.url}/><span style={{flex:1, minWidth:200}}><H s={m?19:22}>{ent.raison_sociale || A.moi.entreprise.nom}</H><Muted style={{marginTop:3}}>{[(FORMES.find(f=>f[0]===ent.forme_juridique)||[])[1], ent.adresse_siege, ent.ninea && `NINEA ${ent.ninea}`].filter(Boolean).join(' · ') || `${A.moi.entreprise.pays} · profil à compléter`}</Muted></span>
      <StageB st={d.stage}/></Card>
    <StageBanner d={d} onFix={!ro ? ()=>aller2(3) : null}/>
    {!proprio && <Notice tone="info">Seul le propriétaire du compte peut compléter et envoyer le dossier. Vous le consultez en lecture seule.</Notice>}
    <div style={{display:'grid', gridTemplateColumns:m?'minmax(0,1fr)':'260px minmax(0,1fr)', gap:m?12:20, alignItems:'start'}}>
      {m ? <><Progress steps={STEPS_P} i={s}/><Lbl>Étape {s+1} sur 6 · {STEPS_P[s]}</Lbl></>
      : <Card pad={8} style={{position:'sticky', top:0}}><Lbl style={{padding:'10px 12px 8px'}}>Dossier de production</Lbl>
        {STEPS_P.map((st,k)=>{ const on = s===k, dn = k<5 && !manque(k) && !on, bad = k===3 && (d.documents||[]).some(x=>x.statut==='a_corriger');
          return <button key={st} className="lb lr" onClick={()=>aller2(k)} aria-current={on?'step':undefined} style={{display:'flex', alignItems:'center', gap:12, width:'100%', padding:'11px 12px', border:0, borderRadius:14, cursor:'pointer', textAlign:'left', background:on?V.mint:'transparent', fontFamily:V.body}}>
            <span style={{width:26, height:26, borderRadius:99, flex:'none', display:'grid', placeItems:'center', background:dn?V.acc:on?V.card:V.sub, border:dn?0:`1.5px solid ${on?V.acc:V.line}`}}>{dn?<I n="check" s={14} c="#fff"/>:<span style={{fontWeight:800, fontSize:11.5, color:on?V.accD:V.ink3}}>{k+1}</span>}</span>
            <span style={{flex:1, fontWeight:700, fontSize:13.5, color:on?V.accD:V.ink}}>{st}</span>
            {bad && <span style={{width:7, height:7, borderRadius:99, background:'var(--bad)'}}></span>}</button>; })}
      </Card>}
      <Card pad={m?16:24} style={{display:'flex', flexDirection:'column', gap:18}}>
        <div><Lbl>Étape {s+1} sur 6</Lbl><H s={20} style={{marginTop:6}}>{STEPS_P[s]}</H></div>{body[s]}
        {err && <Notice tone="bad">{err.message}</Notice>}
        <div style={{display:'flex', gap:8, paddingTop:16, borderTop:`1px solid ${V.line}`, flexWrap:'wrap'}}>
          {s>0 && <Btn kind="secondary" icon="arrow-left" disabled={occ} onClick={()=>aller2(s-1)}>Précédent</Btn>}<span style={{flex:1}}></span>
          {s<5 ? <Btn iconR="arrow-right" disabled={occ} onClick={()=>aller2(s+1)}>{occ?'Enregistrement…':'Continuer'}</Btn>
            : !ro ? <Btn icon="paper-plane-tilt" disabled={!ok || !d.pret_a_envoyer || occ} onClick={soumettre}>{occ?'Envoi…':d.stage==='modification'?'Envoyer la modification':['info','refused'].includes(d.stage)?'Renvoyer le dossier':'Envoyer le dossier'}</Btn> : null}
        </div>
      </Card>
    </div>
  </Page>;
}

function LogoEntreprise({d, ro, onFait}){
  const toast = useToast(); const [occ, setOcc] = React.useState(false);
  const envoyer = async (f) => { if(f.size > 2*1048576){ toast('Logo trop lourd : 2 Mo maximum', 'bad'); return; } setOcc(true); try { const fd = new FormData(); fd.append('logo', f); await api('POST', 'dossier/logo', fd); onFait(await api('GET', 'dossier')); toast('Logo enregistré'); } catch(e){ toast(e.message, 'bad'); } setOcc(false); };
  return <div style={{display:'flex', alignItems:'center', gap:16, flexWrap:'wrap'}}>{d.logo?.url ? <img src={d.logo.url} alt="Logo de l'entreprise" style={{width:72, height:72, borderRadius:22, objectFit:'cover', background:'#fff', border:`1px solid ${V.line}`, flex:'none'}}/> : <span style={{display:'grid', placeItems:'center', width:72, height:72, borderRadius:22, background:V.sub, border:`1.5px dashed ${V.line}`, flex:'none'}}><I n="image" s={26} c={V.ink3}/></span>}
    <div style={{flex:1, minWidth:200}}>{ro ? <Muted>Logo de l'entreprise</Muted> : occ ? <Skel h={50} r={18}/> : <Drop compact onFile={envoyer} accept=".png,.jpg,.jpeg,.svg" hint="Logo · PNG, JPG ou SVG carré, 512 px minimum"/>}</div></div>;
}

function Documents({d, ro, onFait}){
  const toast = useToast(); const [occ, setOcc] = React.useState(null), [sup, setSup] = React.useState(null);
  const deposer = async (type, f) => { if(f.size > 10*1048576){ toast('Fichier trop lourd : 10 Mo maximum', 'bad'); return; } setOcc(type); try { const fd = new FormData(); fd.append('fichier', f); onFait(await api('POST', `dossier/documents/${type}`, fd)); toast('Pièce déposée'); } catch(e){ toast(e.message, 'bad'); } setOcc(null); };
  const retirer = async (type) => { setOcc(type); try { onFait(await api('DELETE', `dossier/documents/${type}`)); toast('Pièce retirée'); } catch(e){ toast(e.message, 'bad'); } setOcc(null); setSup(null); };
  const voir = async (type) => { setOcc(type); try { ouvrirFichier(await api('GET', `dossier/documents/${type}/fichier`)); } catch(e){ toast(e.message, 'bad'); } setOcc(null); };
  return <div style={{display:'flex', flexDirection:'column', gap:10}}>
    <div style={{display:'flex', alignItems:'center', gap:10, padding:'12px 14px', borderRadius:16, background:V.sub, flexWrap:'wrap'}}><I n="file-arrow-down" s={20} c={V.accD}/><span style={{flex:1, minWidth:200, fontSize:13, fontWeight:600, color:V.ink2}}>Le contrat de partenariat vous est transmis par LeMultiservice : signez-le, paraphez chaque page, puis déposez-le ci-dessous. Pièces stockées chiffrées.</span></div>
    {(d.documents||[]).filter(x=>x.requis || x.statut!=='a_fournir').map(x=>{ const st = x.statut, canUp = !ro && st!=='valide';
      return <div key={x.type} style={{padding:14, borderRadius:18, border:`1px solid ${st==='a_corriger'?'var(--badLine)':V.line}`, background:V.card, display:'flex', flexDirection:'column', gap:10}}>
        <div style={{display:'flex', alignItems:'center', gap:12, flexWrap:'wrap'}}><I n={st==='valide'?'file-check':'file-text'} s={22} c={st==='valide'?V.acc:V.ink3}/>
          <span style={{flex:1, minWidth:180}}><span style={{display:'block', fontWeight:700, fontSize:13.5}}>{x.libelle}{!x.requis && <span style={{fontWeight:500, color:V.ink3}}> (facultatif)</span>}</span>{x.fichier && <Mono s={11.5} c={V.ink3}>{x.fichier} · {(x.taille/1048576).toLocaleString('fr-FR', {maximumFractionDigits:1})} Mo{x.depose_le ? ` · ${D(x.depose_le, false)}` : ''}</Mono>}</span>
          {ST[st] ? <StatusB st={st}/> : <Badge>{st}</Badge>}
          {x.fichier && <Btn kind="ghost" sm icon={occ===x.type?'spinner':'eye'} label={`Voir ${x.libelle}`} disabled={occ===x.type} onClick={()=>voir(x.type)}/>}
          {canUp && x.fichier && st!=='a_corriger' && <Btn kind="ghost" sm icon="trash" label={`Retirer ${x.libelle}`} onClick={()=>setSup(x)}/>}</div>
        {x.commentaire && <div style={{display:'flex', gap:8, padding:'10px 12px', borderRadius:12, background:V.badBg}}><I n="chat-circle-text" s={17} c={V.bad}/><span style={{fontSize:12.5, fontWeight:600, color:V.ink2, lineHeight:1.45}}><b style={{color:V.bad}}>LeMultiservice :</b> {x.commentaire}</span></div>}
        {canUp && (!x.fichier || st==='a_corriger') && (occ===x.type ? <Skel h={50} r={18}/> : <Drop compact onFile={f=>deposer(x.type, f)} accept=".pdf,.jpg,.jpeg,.png"/>)}
      </div>; })}
    {sup && <Modal title="Retirer cette pièce ?" icon="trash" tone="bad" onClose={()=>setSup(null)} foot={<><Btn kind="secondary" onClick={()=>setSup(null)}>Annuler</Btn><Btn kind="danger" disabled={!!occ} onClick={()=>retirer(sup.type)}>Retirer</Btn></>}><Muted><b style={{color:V.ink}}>{sup.libelle}</b> sera supprimée du dossier. Vous pourrez en déposer une nouvelle.</Muted></Modal>}
  </div>;
}

// Vérification d'identité : type de pièce → recto → verso → selfie → envoi (vérifiée par LeMultiservice pendant la revue)
function Apercu({f, selfie, cote}){
  const [u, setU] = React.useState(null); React.useEffect(()=>{ if(!f || !/^image\//.test(f.type)) { setU(null); return; } const x = URL.createObjectURL(f); setU(x); return ()=>URL.revokeObjectURL(x); }, [f]);
  const st = selfie ? {width:260, height:300, borderRadius:28} : {width:'100%', maxWidth:440, aspectRatio:'1.586', borderRadius:22};
  return <div style={{position:'relative', margin:'0 auto', overflow:'hidden', background:f?V.sub:'#0E1F19', ...st}}>
    {!f && <><span style={{position:'absolute', inset:0, backgroundImage:'radial-gradient(rgba(159,224,198,.12) 1px, transparent 1px)', backgroundSize:'16px 16px'}}></span>
      {selfie ? <><span style={{position:'absolute', left:'50%', top:'46%', width:170, height:220, transform:'translate(-50%,-50%)', borderRadius:'50%', border:'3px dashed #9FE0C6', boxShadow:'0 0 0 400px rgba(14,31,25,.55)'}}></span><span style={{position:'absolute', left:0, right:0, bottom:14, textAlign:'center', color:'rgba(255,255,255,.8)', fontWeight:700, fontSize:12.5}}>Centrez votre visage dans l'ovale</span></>
      : <>{[[0,0,'borderTop','borderLeft'],[0,1,'borderTop','borderRight'],[1,0,'borderBottom','borderLeft'],[1,1,'borderBottom','borderRight']].map(([y,x,a,b],i)=><span key={i} style={{position:'absolute', [y?'bottom':'top']:16, [x?'right':'left']:16, width:34, height:34, [a]:'3px solid #9FE0C6', [b]:'3px solid #9FE0C6', borderRadius:y?(x?'0 0 12px 0':'0 0 0 12px'):(x?'0 12px 0 0':'12px 0 0 0')}}></span>)}
        <span style={{position:'absolute', left:'50%', top:'50%', transform:'translate(-50%,-50%)', display:'flex', flexDirection:'column', alignItems:'center', gap:8, color:'rgba(255,255,255,.75)', textAlign:'center', width:'80%'}}><I n={cote==='verso'?'barcode':'identification-card'} s={34} c="#9FE0C6"/><span style={{fontWeight:700, fontSize:13}}>Placez le {cote} de la pièce dans le cadre</span></span>
        <span className="kscan" style={{position:'absolute', left:16, right:16, height:2, background:'linear-gradient(90deg,transparent,#9FE0C6,transparent)'}}></span></>}</>}
    {f && (u ? <img src={u} alt="" style={{position:'absolute', inset:0, width:'100%', height:'100%', objectFit:'cover'}}/> : <span style={{position:'absolute', inset:0, display:'grid', placeItems:'center'}}><I n="file-pdf" s={40} c={V.bad}/></span>)}
    {f && <span style={{position:'absolute', left:10, bottom:10, right:10, display:'flex', alignItems:'center', gap:8, padding:'6px 10px', borderRadius:12, background:'rgba(14,31,25,.72)', color:'#fff', fontSize:12, fontWeight:600}}><I n="check-circle" s={16} c="#9FE0C6" fill/><Ellipse>{f.name}</Ellipse></span>}
  </div>;
}
function Tips({items}){ return <div style={{display:'grid', gridTemplateColumns:'repeat(auto-fit,minmax(150px,1fr))', gap:8}}>{items.map(t=><span key={t[1]} style={{display:'flex', alignItems:'center', gap:8, padding:'10px 12px', borderRadius:14, background:V.sub, fontSize:12.5, fontWeight:600, color:V.ink2}}><I n={t[0]} s={17} c={V.accD}/>{t[1]}</span>)}</div>; }
function Capture({f, set, selfie}){
  const cam = React.useRef(null), imp = React.useRef(null);
  const pris = e => { const x = e.target.files[0]; e.target.value = ''; if(x) set(x); };
  return <div style={{display:'flex', gap:8, justifyContent:'center', flexWrap:'wrap'}}>
    <input ref={cam} type="file" accept="image/*" capture={selfie?'user':'environment'} style={{display:'none'}} onChange={pris}/><input ref={imp} type="file" accept=".jpg,.jpeg,.png,.pdf" style={{display:'none'}} onChange={pris}/>
    {f ? <Btn kind="secondary" icon="arrow-counter-clockwise" onClick={()=>set(null)}>Reprendre</Btn> : <><Btn icon="camera" onClick={()=>cam.current.click()}>{selfie?'Prendre le selfie':'Prendre la photo'}</Btn><Btn kind="secondary" icon="upload-simple" onClick={()=>imp.current.click()}>Importer un fichier</Btn></>}</div>;
}
const KYC_STEPS = [['Pièce','identification-card'],['Recto','credit-card'],['Verso','credit-card'],['Selfie','user-focus'],['Vérification','shield-check']];
function KycFlow({d, ro, onFait}){
  const m = useMob(); const id = d.identite || {}; const envoye = ['soumise','verifiee'].includes(id.statut);
  const [k, setK] = React.useState(envoye ? 4 : 0), [doc, setDoc] = React.useState(Math.max(0, PIECES.findIndex(p=>p[0]===id.type_piece))), [f, setF] = React.useState({}), [occ, setOcc] = React.useState(false), [err, setErr] = React.useState(null);
  const needVerso = PIECES[doc][0] !== 'passeport';
  const envoyer = async () => { setOcc(true); setErr(null); try { const fd = new FormData(); fd.append('type_piece', PIECES[doc][0]); ['recto','verso','selfie'].forEach(x=>{ if(f[x] && (x!=='verso' || needVerso)) fd.append(x, f[x]); }); onFait(await api('POST', 'dossier/identite', fd)); setK(4); } catch(e){ setErr(e); } setOcc(false); };
  const suite = key => <div style={{display:'flex', justifyContent:'center'}}><Btn iconR="arrow-right" disabled={!f[key]} onClick={()=>setK(key==='recto'?(needVerso?2:3):3)}>Continuer</Btn></div>;
  return <div style={{display:'flex', flexDirection:'column', gap:18}}>
    <div style={{display:'flex', alignItems:'center', gap:m?4:0}}>{KYC_STEPS.map((x,i)=>{ if(i===2 && !needVerso) return null; const on = i===k, dn = i<k || (i===4 && envoye);
      return <React.Fragment key={x[0]}><div style={{display:'flex', alignItems:'center', gap:8, flex:'none'}}>
        <span style={{width:32, height:32, borderRadius:99, display:'grid', placeItems:'center', background:dn?V.acc:on?V.mint:V.sub, border:on&&!dn?`1.5px solid ${V.acc}`:0}}><I n={dn?'check':x[1]} s={16} c={dn?'#fff':on?V.accD:V.ink3}/></span>
        {!m && <span style={{fontWeight:700, fontSize:12.5, color:on?V.ink:dn?V.accD:V.ink3}}>{x[0]}</span>}</div>
        {i<4 && <span style={{flex:1, height:2, margin:'0 10px', borderRadius:99, background:i<k?V.acc:V.line, minWidth:12}}></span>}</React.Fragment>; })}</div>
    <div style={{padding:m?16:24, borderRadius:24, border:`1px solid ${V.line}`, background:V.card, display:'flex', flexDirection:'column', gap:18}}>
      {k===0 && <><div><H s={18}>Vérifions l'identité du représentant légal</H><Muted style={{marginTop:4}}>3 photos, moins de 2 minutes. Les images sont chiffrées et servent uniquement à la vérification.</Muted></div>
        {id.statut==='echouee' && <Notice tone="bad" title="Vérification échouée">{id.commentaire || 'Recommencez avec des photos nettes et une pièce en cours de validité.'}</Notice>}
        <div><Lbl style={{marginBottom:10}}>Type de pièce</Lbl><div style={{display:'grid', gridTemplateColumns:m?'1fr':'repeat(3,1fr)', gap:10}}>{PIECES.map((p,i)=><button key={p[0]} className="lb lc" disabled={ro} onClick={()=>setDoc(i)} aria-pressed={doc===i} style={{display:'flex', flexDirection:'column', alignItems:'flex-start', gap:10, padding:16, borderRadius:18, border:`1.5px solid ${doc===i?V.acc:V.line}`, background:doc===i?V.mint:V.card, cursor:ro?'default':'pointer', textAlign:'left', fontFamily:V.body}}>
          <Tile icon={p[2]} s={40} c={doc===i?V.accD:V.ink2} bg={doc===i?V.card:V.sub}/><span><span style={{display:'block', fontWeight:800, fontSize:13.5, color:V.ink}}>{p[1]}</span><span style={{display:'block', fontSize:12, color:V.ink3, marginTop:2}}>{p[3]}</span></span></button>)}</div></div>
        <Tips items={[['sun','Bonne lumière'],['drop-slash','Sans reflet'],['frame-corners','Pièce entière visible'],['calendar-check','Pièce en cours de validité']]}/>
        {ro ? <Notice tone="info">Seul le propriétaire du compte peut envoyer les pièces d'identité.</Notice> : <div style={{display:'flex', justifyContent:'flex-end'}}><Btn iconR="arrow-right" onClick={()=>setK(1)}>Commencer</Btn></div>}</>}
      {k===1 && <><div style={{textAlign:'center'}}><H s={18}>{needVerso?'Recto de la pièce':'Page photo du passeport'}</H><Muted style={{marginTop:4}}>Posez la pièce à plat sur une surface sombre.</Muted></div><Apercu f={f.recto} cote="recto"/><Capture f={f.recto} set={x=>setF({...f, recto:x})}/>{suite('recto')}</>}
      {k===2 && <><div style={{textAlign:'center'}}><H s={18}>Verso de la pièce</H><Muted style={{marginTop:4}}>Retournez la pièce, la zone de lecture automatique doit être nette.</Muted></div><Apercu f={f.verso} cote="verso"/><Capture f={f.verso} set={x=>setF({...f, verso:x})}/>{suite('verso')}</>}
      {k===3 && <><div style={{textAlign:'center'}}><H s={18}>Selfie</H><Muted style={{marginTop:4}}>Votre visage est comparé à la photo de la pièce.</Muted></div><Apercu f={f.selfie} selfie/>
        <Tips items={[['eyeglasses','Sans lunettes ni casquette'],['smiley-blank','Visage neutre, regard vers l\'objectif'],['lightbulb','Lumière de face']]}/>
        <Capture f={f.selfie} set={x=>setF({...f, selfie:x})} selfie/>
        {err && <Notice tone="bad">{err.message}</Notice>}
        <div style={{display:'flex', gap:8, justifyContent:'center'}}><Btn icon="shield-check" disabled={!f.selfie || !f.recto || (needVerso && !f.verso) || occ} onClick={envoyer}>{occ?'Envoi…':'Envoyer pour vérification'}</Btn></div></>}
      {k===4 && <><div style={{display:'flex', alignItems:'center', gap:14, padding:16, borderRadius:20, background:id.statut==='verifiee'?V.mint:V.infoBg}}><span style={{display:'grid', placeItems:'center', width:52, height:52, borderRadius:18, background:id.statut==='verifiee'?V.acc:V.info, flex:'none'}}><I n={id.statut==='verifiee'?'shield-check':'hourglass'} s={28} c="#fff" fill/></span>
          <span><span style={{display:'block', fontWeight:800, fontSize:16, color:id.statut==='verifiee'?V.accD:V.info}}>{id.statut==='verifiee'?'Identité vérifiée':'Pièces reçues'}</span><span style={{display:'block', fontSize:13, color:V.ink2, marginTop:2}}>{(PIECES.find(p=>p[0]===id.type_piece)||[])[1] || 'Pièce d\'identité'} · {id.statut==='verifiee' ? 'contrôlée par LeMultiservice' : 'la vérification est faite par l\'équipe LeMultiservice pendant la revue du dossier.'}</span></span></div>
        {id.commentaire && <Notice tone="info">{id.commentaire}</Notice>}
        {!ro && id.statut!=='verifiee' && <div><Btn kind="ghost" icon="arrow-counter-clockwise" onClick={()=>{setK(0); setF({});}}>Envoyer d'autres pièces</Btn></div>}</>}
    </div>
  </div>;
}

function CompanyProfile({d, onEdit}){
  const A = useApp(), m = useMob(); const toast = useToast();
  const [cles] = useDonnees(() => api('GET', 'cles?mode=live').catch(()=>({donnees:[]})), []);
  const cleVue = 'lms_bienvenue_vu'; const [vu, setVu] = React.useState(() => { try { return localStorage.getItem(cleVue) === '1'; } catch(e){ return false; } });
  const fermer = () => { setVu(true); try { localStorage.setItem(cleVue, '1'); } catch(e){} };
  const recent = d.approuve_le && Date.now() - new Date(d.approuve_le) < 14*864e5;
  const e = d.entreprise||{}, r = d.representant||{}, c = d.contacts||{}; const tests = d.tests_sandbox||[];
  const sec = (t, icon, rows) => <Card><div style={{display:'flex', alignItems:'center', gap:10, marginBottom:8}}><I n={icon} s={19} c={V.accD}/><H s={16} style={{flex:1}}>{t}</H></div><KV rows={rows}/></Card>;
  const voir = async (type) => { try { ouvrirFichier(await api('GET', `dossier/documents/${type}/fichier`)); } catch(x){ toast(x.message, 'bad'); } };
  const docs = (d.documents||[]).filter(x=>x.fichier);
  return <Page max={1160}>
    {recent && !vu && <div role="status" style={{display:'flex', alignItems:'center', gap:14, padding:'16px 20px', borderRadius:22, background:V.mint, flexWrap:'wrap'}}><Tile icon="seal-check" s={42} bg={V.card} fill/><span style={{flex:1, minWidth:220}}><span style={{display:'block', fontWeight:800, fontSize:15, color:V.accD}}>Dossier validé · production activée</span><span style={{display:'block', marginTop:2, fontSize:13, color:V.ink2}}>Créez votre première clé live, rechargez votre solde et vérifiez vos IP autorisées.</span></span>
      <Btn kind="ghost" sm onClick={fermer}>Plus tard</Btn><Btn icon="key" onClick={()=>{fermer(); A.setMode('live'); A.go('keys');}}>Créer ma première clé live</Btn></div>}
    <Card pad={0} style={{overflow:'hidden'}}>
      <div style={{height:m?70:96, background:'#113025', position:'relative', overflow:'hidden'}}><span style={{position:'absolute', inset:0, backgroundImage:'radial-gradient(rgba(159,224,198,.18) 1.2px, transparent 1.2px)', backgroundSize:'20px 20px'}}></span></div>
      <div style={{display:'flex', alignItems:m?'flex-start':'flex-end', gap:16, padding:m?'0 16px 16px':'0 24px 22px', marginTop:m?-28:-36, flexWrap:'wrap', flexDirection:m?'column':'row'}}>
        <span style={{padding:4, borderRadius:26, background:V.card, position:'relative', zIndex:1, flex:'none'}}><CoLogo s={m?60:80} nom={e.raison_sociale || A.moi.entreprise.nom} logo={d.logo?.url}/></span>
        <span style={{flex:1, minWidth:0, paddingTop:m?0:44}}><H s={m?20:24}>{e.raison_sociale || A.moi.entreprise.nom}</H><span style={{display:'flex', flexWrap:'wrap', gap:8, marginTop:8}}><Badge tone="ok" icon="seal-check">Dossier approuvé{d.approuve_le ? ` le ${D(d.approuve_le, false)}` : ''}</Badge><Badge tone="ok" dot>Production active</Badge><Badge>{(SECTEURS.find(x=>x[0]===A.moi.entreprise.secteur)||[0, A.moi.entreprise.secteur])[1]}</Badge></span></span>
        {A.peut('proprio') && <div style={{display:'flex', gap:8, paddingTop:m?0:44}}><Btn kind="secondary" icon="pencil-simple" onClick={onEdit}>Demander une modification</Btn></div>}
      </div>
    </Card>
    <Grid cols="1fr 1fr">
      {sec('Identité légale','buildings',[['Raison sociale',e.raison_sociale||'—'],['Forme juridique',(FORMES.find(f=>f[0]===e.forme_juridique)||[0,e.forme_juridique||'—'])[1]],['NINEA',e.ninea||'—',null,1],['RCCM',e.rccm||'—',null,1],['Siège',e.adresse_siege||'—'],['Site web',e.site_web||'—']])}
      {sec('Représentant légal','identification-card',[['Nom',[r.prenom, r.nom].filter(Boolean).join(' ')||'—'],['Fonction',r.fonction||'—'],['Email',r.email||'—'],['Identité',d.identite?.statut==='verifiee'?'Vérifiée':d.identite?.statut==='soumise'?'Pièces envoyées':'—',d.identite?.statut==='verifiee'?V.accD:undefined]])}
      {sec('Contacts','address-book',[['Propriétaire du compte',`${A.moi.membre.prenom} ${A.moi.membre.nom}`],['Technique',c.technique||'—'],['Finance',c.finance||'—'],['Urgence (24/7)',c.urgence||'—'],['Alertes',c.email_alertes||'—']])}
      <Card onClick={()=>A.go('devset')} style={{display:'flex', flexDirection:'column', gap:8}}><div style={{display:'flex', alignItems:'center', gap:10}}><I n="code" s={19} c={V.accD}/><H s={16} style={{flex:1}}>Intégration</H><I n="caret-right" s={16} c={V.ink3}/></div><KV rows={[['Clés live actives',cles?String((cles.donnees||[]).filter(k=>k.statut==='active').length):'…'],['Tests sandbox',`${tests.filter(t=>t.fait).length} sur ${tests.length} réussis`,V.accD],['IP et webhooks','Paramètres développeur']]}/></Card>
    </Grid>
    <Card pad={0}><div style={{display:'flex', alignItems:'center', padding:'16px 20px', gap:10, flexWrap:'wrap'}}><H s={16} style={{flex:1}}>Documents</H><Badge tone="ok" icon="check-circle">{docs.filter(x=>x.statut==='valide').length} sur {docs.length} validés</Badge></div>
      {docs.map(x=><div key={x.type} style={{display:'flex', alignItems:'center', gap:12, padding:'12px 20px', borderTop:`1px solid ${V.line}`, flexWrap:'wrap'}}><I n={x.statut==='valide'?'file-check':'file-text'} s={20} c={x.statut==='valide'?V.acc:V.ink3}/><span style={{flex:1, minWidth:180}}><span style={{display:'block', fontWeight:700, fontSize:13.5}}>{x.libelle}</span><Mono s={11.5} c={V.ink3}>{x.fichier}{x.depose_le ? ` · déposé le ${D(x.depose_le, false)}` : ''}</Mono></span>{ST[x.statut]?<StatusB st={x.statut}/>:<Badge>{x.statut}</Badge>}<Btn kind="ghost" sm icon="download-simple" label={`Ouvrir ${x.libelle}`} onClick={()=>voir(x.type)}/></div>)}
      {!docs.length && <Muted style={{padding:'0 20px 16px'}}>Aucun document.</Muted>}</Card>
    <Notice tone="info" icon="info">Toute modification des informations légales ou des documents repasse en revue. La production reste active pendant la revue.</Notice>
  </Page>;
}

const ROLES_D = [['proprietaire','Propriétaire','Tout, y compris le dossier de production et les membres'],['developpeur','Développeur','Clés, journaux, webhooks, documentation'],['finance','Finance','Solde, recharges, relevés'],['lecteur','Lecteur','Consultation seule']];
function Team(){
  const A = useApp(); const toast = useToast(); const proprio = A.peut('proprio');
  const [d, recharger, etat] = useDonnees(() => api('GET', 'equipe'), []);
  const [inv, setInv] = React.useState(false), [rm, setRm] = React.useState(null), [email, setEmail] = React.useState(''), [role, setRole] = React.useState('developpeur'), [err, setErr] = React.useState(null), [occ, setOcc] = React.useState(null);
  const agir = async (cle, fn, ok) => { setOcc(cle); try { await fn(); toast(ok); recharger(); } catch(e){ toast(e.message, 'bad'); } setOcc(null); };
  const inviter = async () => { setOcc('inv'); setErr(null); try { await api('POST', 'equipe/invitations', {email:email.trim(), role}); toast('Invitation envoyée, valable 7 jours'); setInv(false); setEmail(''); recharger(); } catch(e){ setErr(e); } setOcc(null); };
  const membres = d?.membres || [], invits = d?.invitations || [];
  return <Page>
    <PageHead title="Équipe" sub="Donnez à chacun les accès dont il a besoin. Double authentification obligatoire pour tous." actions={proprio && <Btn icon="user-plus" onClick={()=>{setInv(true); setErr(null);}}>Inviter un membre</Btn>}/>
    {etat.erreur ? <ErreurCarte e={etat.erreur} recharger={recharger}/> :
    <Tbl chargement={!d} cols={[{k:'n',l:'Membre',w:'2fr'},{k:'r',l:'Rôle',w:'1.1fr'},{k:'f',l:'2FA',w:'.7fr',hideM:1},{k:'l',l:'Dernière activité',w:'1fr',hideM:1},{k:'x',l:'',w:'60px',r:1}]}
      rows={membres.map(x=>{ const nom = `${x.prenom} ${x.nom}`; return {n:<span style={{display:'flex', alignItems:'center', gap:10, minWidth:0}}><Av n={nom}/><span style={{minWidth:0}}><span style={{display:'block', fontWeight:700}}>{nom}{x.vous && <span style={{fontWeight:500, color:V.ink3}}> (vous)</span>}</span><Ellipse style={{display:'block', fontSize:12, color:V.ink3, fontWeight:500}}>{x.email}</Ellipse></span></span>,
        r:x.role==='proprietaire' ? <Badge tone="deep">Propriétaire</Badge> : proprio && !x.vous ? <div style={{width:150}}><Sel label={`Rôle de ${nom}`} opts={ROLES_D.slice(1).map(y=>[y[0], y[1]])} value={x.role} onChange={v=>agir('r'+x.id, ()=>api('PATCH', `equipe/membres/${x.id}`, {role:v}), 'Rôle modifié')} style={{height:36, fontSize:13}}/></div> : <Badge>{ROLES_M[x.role]||x.role}</Badge>,
        f:<Badge tone={x.double_auth?'ok':'warn'} icon={x.double_auth?'check-circle':'warning'}>{x.double_auth?'Active':'À activer'}</Badge>, l:<span style={{color:V.ink2}}>{x.derniere_activite ? `Il y a ${Depuis(x.derniere_activite)}` : '—'}</span>,
        x:proprio && x.role!=='proprietaire' && !x.vous ? <Btn kind="ghost" sm icon="user-minus" label={`Retirer ${nom}`} onClick={()=>setRm(x)} style={{color:V.bad}}/> : null}; })}/>}
    {invits.length > 0 && <Card pad={0}><div style={{padding:'16px 20px 8px'}}><H s={16}>Invitations en attente</H></div>
      {invits.map(x=><div key={x.id} style={{display:'flex', alignItems:'center', gap:12, padding:'12px 20px', borderTop:`1px solid ${V.line}`, flexWrap:'wrap'}}><Tile icon="envelope-simple" s={34} c={V.ink3} bg={V.sub}/><span style={{flex:1, minWidth:180}}><span style={{display:'block', fontWeight:700, fontSize:13.5}}>{x.email}</span><span style={{display:'block', fontSize:12, color:V.ink3}}>{ROLES_M[x.role]||x.role}{x.cree_le ? ` · envoyée le ${D(x.cree_le, false)}` : ''}{x.expire_le ? ` · expire le ${D(x.expire_le, false)}` : ''}</span></span>
        {proprio && <><Btn kind="secondary" sm disabled={!!occ} onClick={()=>agir('i'+x.id, ()=>api('POST', `equipe/invitations/${x.id}/renvoyer`), 'Invitation renvoyée')}>Renvoyer</Btn><Btn kind="ghost" sm disabled={!!occ} style={{color:V.bad}} onClick={()=>agir('a'+x.id, ()=>api('DELETE', `equipe/invitations/${x.id}`), 'Invitation annulée')}>Annuler</Btn></>}</div>)}</Card>}
    <Grid cols="repeat(4,1fr)" mcols="1fr 1fr">{ROLES_D.map(r=><Card key={r[0]} pad={16}><span style={{display:'block', fontWeight:800, fontSize:13.5}}>{r[1]}</span><span style={{display:'block', marginTop:4, fontSize:12, color:V.ink3, lineHeight:1.45}}>{r[2]}</span></Card>)}</Grid>
    {inv && <Modal title="Inviter un membre" icon="user-plus" onClose={()=>setInv(false)} foot={<><Btn kind="secondary" onClick={()=>setInv(false)}>Annuler</Btn><Btn icon="paper-plane-tilt" disabled={!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email.trim()) || occ==='inv'} onClick={inviter}>{occ==='inv'?'Envoi…':'Envoyer l\'invitation'}</Btn></>}>
      <Field label="Email professionnel"><Inp placeholder="prenom.nom@entreprise.sn" type="email" value={email} onChange={e=>setEmail(e.target.value)} autoFocus/></Field>
      <div role="radiogroup" aria-label="Rôle"><Lbl style={{marginBottom:10}}>Rôle</Lbl><div style={{display:'flex', flexDirection:'column', gap:8}}>{ROLES_D.slice(1).map(r=><label key={r[0]} className="lc" style={{display:'flex', gap:12, alignItems:'center', padding:'12px 14px', borderRadius:16, border:`1.5px solid ${role===r[0]?V.acc:V.line}`, background:role===r[0]?V.mint:V.card, cursor:'pointer'}}><input type="radio" name="role" checked={role===r[0]} onChange={()=>setRole(r[0])} style={{accentColor:'#3E9378'}}/><span><span style={{display:'block', fontWeight:700, fontSize:13.5}}>{r[1]}</span><span style={{display:'block', fontSize:12, color:V.ink3}}>{r[2]}</span></span></label>)}</div></div>
      <Muted>La double authentification sera exigée à sa première connexion. L'invitation est valable 7 jours.</Muted>
      {err && <Notice tone="bad">{err.message}</Notice>}</Modal>}
    {rm && <Modal title={`Retirer ${rm.prenom} ${rm.nom} ?`} icon="user-minus" tone="bad" onClose={()=>setRm(null)} foot={<><Btn kind="secondary" onClick={()=>setRm(null)}>Annuler</Btn><Btn kind="danger" disabled={!!occ} onClick={()=>agir('m', ()=>api('DELETE', `equipe/membres/${rm.id}`), 'Membre retiré, sessions fermées').then(()=>setRm(null))}>Retirer</Btn></>}><Muted>Ses sessions sont fermées immédiatement. Les clés qu'il a créées restent actives.</Muted></Modal>}
  </Page>;
}

function Settings(){
  const A = useApp(); const toast = useToast(); const [tab, setTab] = React.useState(0);
  const [ses, rS, {erreur:eS}] = useDonnees(() => api('GET', 'sessions'), []);
  const [eq] = useDonnees(() => api('GET', 'equipe'), []);
  const [occ, setOcc] = React.useState(null), [lien, setLien] = React.useState(false);
  const fermerSession = async (id) => { setOcc(id); try { await api('DELETE', `sessions/${id}`); toast('Session fermée'); rS(); } catch(e){ toast(e.message, 'bad'); } setOcc(null); };
  const membres = eq?.membres || []; const mb = A.moi.membre;
  return <Page>
    <PageHead title="Paramètres"/>
    <Tabs opts={['Sécurité','Mon compte']} i={tab} set={setTab}/>
    {tab===0 && <div style={{display:'flex', flexDirection:'column', gap:16}}>
      <Card style={{display:'flex', alignItems:'center', gap:14, flexWrap:'wrap'}}><Tile icon="shield-check" fill/><span style={{flex:1, minWidth:200}}><span style={{display:'block', fontWeight:800, fontSize:14}}>Double authentification obligatoire</span><span style={{display:'block', fontSize:12.5, color:V.ink3}}>{eq ? `Activée pour ${membres.filter(x=>x.double_auth).length} membre${membres.filter(x=>x.double_auth).length>1?'s':''} sur ${membres.length}. Ne peut pas être désactivée.` : 'Ne peut pas être désactivée.'}</span></span><Badge tone="ok" icon="check-circle">Active</Badge></Card>
      {eS ? <ErreurCarte e={eS} recharger={rS}/> : <Tbl chargement={!ses} head={<div style={{padding:'16px 20px 12px'}}><H s={16}>Sessions actives</H></div>} cols={[{k:'d',l:'Appareil',w:'1.6fr'},{k:'l',l:'Lieu',w:'1fr'},{k:'t',l:'Activité',w:'1fr'},{k:'x',l:'',w:'120px',r:1}]}
        rows={(ses?.donnees||[]).map(s=>({d:<span style={{display:'flex', alignItems:'center', gap:10, minWidth:0}}><I n={/iphone|android|mobile/i.test(s.appareil)?'device-mobile':'desktop'} s={19} c={V.ink3}/><Ellipse>{s.appareil}</Ellipse></span>, l:<span style={{color:V.ink2}}>{s.lieu || <Mono>{s.ip}</Mono>}</span>, t:s.courante?<Badge tone="ok" dot>Cet appareil</Badge>:<span style={{color:V.ink2}}>Il y a {Depuis(s.derniere_activite)}</span>, x:s.courante?null:<Btn kind="ghost" sm disabled={occ===s.id} style={{color:V.bad}} onClick={()=>fermerSession(s.id)}>Déconnecter</Btn>}))}
        empty={<Muted style={{padding:'14px 20px'}}>Aucune session.</Muted>}/>}
      <Card onClick={()=>A.go('devset')} style={{display:'flex', alignItems:'center', gap:12}}><Tile icon="code"/><span style={{flex:1}}><span style={{display:'block', fontWeight:800, fontSize:14}}>IP autorisées et webhooks</span><span style={{display:'block', fontSize:12.5, color:V.ink3}}>Dans les Paramètres développeur</span></span><I n="caret-right" s={16} c={V.ink3}/></Card></div>}
    {tab===1 && <Grid cols="1fr 1fr">
      <Card style={{display:'flex', flexDirection:'column', gap:8}}><div style={{display:'flex', alignItems:'center', gap:12, marginBottom:6}}><Av n={`${mb.prenom} ${mb.nom}`} s={44}/><span><H s={17}>{mb.prenom} {mb.nom}</H><Muted style={{fontSize:12.5}}>{ROLES_M[mb.role]} · {A.moi.entreprise.nom}</Muted></span></div>
        <KV rows={[['Email',mb.email],['Téléphone',mb.telephone||'—'],['Fonction',mb.fonction||'—'],['Double authentification',mb.double_auth?'Active':'À activer',mb.double_auth?V.accD:V.warn]]}/></Card>
      <Card style={{display:'flex', flexDirection:'column', gap:12}}><div style={{display:'flex', alignItems:'center', gap:10}}><I n="key" s={20} c={V.accD}/><H s={16}>Mot de passe</H></div>
        <Muted>Pour changer de mot de passe, recevez un lien par email (valable 1 heure). Vos autres sessions seront déconnectées.</Muted>
        {lien ? <Notice tone="ok">Lien envoyé à {mb.email}.</Notice> : <div><Btn kind="secondary" icon="envelope-simple" disabled={occ==='mdp'} onClick={async()=>{ setOcc('mdp'); try { await api('POST', 'auth/mdp/oublie', {email:mb.email}); setLien(true); } catch(e){ toast(e.message, 'bad'); } setOcc(null); }}>Recevoir le lien</Btn></div>}</Card>
    </Grid>}
  </Page>;
}

const SERVICES_ST = [['api','API LeMultiservice'],['askia','Askia'],['providence','La Providence'],['diotali','Diotali (registre)'],['wave','Paiements Wave'],['orange_money','Paiements Orange Money']];
const ST_SVC = {operationnel:['Opérationnel','ok','#2F8F6E'], ralenti:['Ralenti','warn','var(--warnDot)'], indisponible:['Indisponible','bad','var(--bad)'], maintenance:['Maintenance','info','var(--info)']};
const TK = {ouvert:['Ouvert','warn'], en_cours:['En cours','info'], resolu:['Résolu','ok'], ferme:['Fermé','mute']};
const PRIO = [['basse','Basse'],['normale','Normale'],['haute','Haute (production bloquée)']];
function Help(){
  const A = useApp(), m = useMob(); const toast = useToast();
  const [st, rSt, {erreur:eSt}] = useDonnees(() => api('GET', 'statut'), []);
  const [tk, rTk, {erreur:eTk}] = useDonnees(() => api('GET', 'tickets'), []);
  const [nt, setNt] = React.useState(false), [sel, setSel] = React.useState(null);
  const [f, setF] = React.useState({cat:'Intégration technique', prio:'normale', sujet:'', ref:'', msg:''}), [err, setErr] = React.useState(null), [occ, setOcc] = React.useState(false);
  const etats = {...Object.fromEntries(SERVICES_ST.map(s=>[s[0],'operationnel'])), ...(st?.statut_services||{})};
  const pert = SERVICES_ST.filter(s=>etats[s[0]]!=='operationnel').length;
  const creer = async () => { setOcc(true); setErr(null); try { const r = await api('POST', 'tickets', {sujet:f.sujet.trim(), priorite:f.prio, message:`Catégorie : ${f.cat}${f.ref.trim() ? `\nRéférence : ${f.ref.trim()}` : ''}\n\n${f.msg.trim()}`}); setNt(false); setF({cat:'Intégration technique', prio:'normale', sujet:'', ref:'', msg:''}); toast('Demande envoyée'); rTk(); setSel(r.id); } catch(e){ setErr(e); } setOcc(false); };
  const incidents = st?.incidents || [];
  return <Page>
    <PageHead title="Aide" sub="Statut des services, incidents et demandes au support LeMultiservice." actions={<><Btn kind="secondary" icon="book-open-text" onClick={()=>A.go('docs')}>Documentation</Btn><Btn icon="plus" onClick={()=>{setNt(true); setErr(null);}}>Nouveau ticket</Btn></>}/>
    <Grid cols="minmax(0,1.4fr) minmax(0,1fr)">
      {eTk ? <ErreurCarte e={eTk} recharger={rTk}/> : <Tbl chargement={!tk} head={<div style={{padding:'16px 20px 12px'}}><H s={16}>Mes tickets</H></div>} cols={[{k:'s',l:'Sujet',w:'2fr'},{k:'d',l:'Ouvert',w:'.9fr'},{k:'st',l:'Statut',w:'.9fr'}]}
        rows={(tk?.donnees||[]).map(t=>({s:<span style={{display:'flex', flexDirection:'column', minWidth:0}}><Ellipse style={{fontWeight:700}}>{t.sujet}</Ellipse>{t.priorite==='haute' && <span style={{fontSize:11.5, color:V.bad, fontWeight:700}}>Priorité haute</span>}</span>, d:<span style={{color:V.ink2}}>Il y a {Depuis(t.cree_le)}</span>, st:<Badge tone={(TK[t.statut]||[0,'mute'])[1]}>{(TK[t.statut]||[t.statut])[0]}</Badge>}))}
        onRow={i=>setSel(tk.donnees[i].id)} empty={<EmptyS icon="lifebuoy" title="Aucune demande" sub="Une question d'intégration, un contrat bloqué, un dépôt ? Écrivez-nous." action={<Btn kind="secondary" icon="plus" onClick={()=>setNt(true)}>Nouveau ticket</Btn>}/>}/>}
      <Card><div style={{display:'flex', alignItems:'center', marginBottom:10, gap:8}}><H s={16} style={{flex:1}}>Statut des services</H>{st && (pert ? <Badge tone="warn" dot>{pert} perturbation{pert>1?'s':''}</Badge> : <Badge tone="ok" dot>Tout fonctionne</Badge>)}</div>
        {eSt ? <Notice tone="bad">{eSt.message}</Notice> : !st ? <Skel h={200}/> : SERVICES_ST.map((s,i)=>{ const e = ST_SVC[etats[s[0]]] || [etats[s[0]], 'mute', V.ink3]; return <div key={s[0]} style={{display:'flex', alignItems:'center', gap:10, padding:'10px 0', borderTop:i?`1px solid ${V.line}`:'none'}}><span style={{width:9, height:9, borderRadius:99, background:e[2], flex:'none'}}></span><span style={{flex:1, fontWeight:600, fontSize:13.5}}>{s[1]}</span><span style={{fontSize:12, fontWeight:700, color:TN[e[1]][1]}}>{e[0]}</span></div>; })}</Card>
    </Grid>
    <Card pad={0}><div style={{display:'flex', alignItems:'center', padding:'16px 20px 12px'}}><H s={16} style={{flex:1}}>Incidents</H><Muted style={{fontSize:12}}>En cours et résolus depuis 7 jours</Muted></div>
      {!st ? <SkelRows n={2}/> : incidents.length ? incidents.map((x,i)=>{ const ok = x.statut==='resolu'; return <div key={i} style={{display:'flex', gap:12, padding:'14px 20px', borderTop:`1px solid ${V.line}`}}>
        <I n={ok?'check-circle':x.gravite==='maintenance'?'wrench':'warning'} s={20} c={TN[ok?'ok':x.gravite==='indisponible'?'bad':x.gravite==='maintenance'?'info':'warn'][1]} fill/>
        <span style={{flex:1, minWidth:0}}><span style={{display:'flex', alignItems:'center', gap:8, flexWrap:'wrap'}}><span style={{fontWeight:700, fontSize:13.5}}>{x.titre}</span><Badge tone={ok?'ok':'warn'}>{ok?'Résolu':'En cours'}</Badge></span>
          {x.message && <span style={{display:'block', fontSize:13, color:V.ink2, marginTop:3}}>{x.message}</span>}
          {(x.mises_a_jour||[]).map((u,j)=><span key={j} style={{display:'block', fontSize:12.5, color:V.ink2, marginTop:6, paddingLeft:10, borderLeft:`2px solid ${V.line}`}}>{u.message}<span style={{display:'block', fontSize:11.5, color:V.ink3}}>{DC(u.le)}</span></span>)}
          <span style={{display:'block', fontSize:12, color:V.ink3, marginTop:6}}>{(SERVICES_ST.find(y=>y[0]===x.service)||[0,x.service])[1]} · depuis le {DC(x.cree_le)}</span></span></div>; })
        : <div style={{display:'flex', alignItems:'center', gap:10, padding:'4px 20px 18px'}}><I n="check-circle" s={20} c={V.acc} fill/><Muted>Aucun incident depuis 7 jours.</Muted></div>}</Card>
    {nt && <Modal title="Nouveau ticket" icon="lifebuoy" onClose={()=>setNt(false)} w={600} foot={<><Btn kind="secondary" onClick={()=>setNt(false)}>Annuler</Btn><Btn icon="paper-plane-tilt" disabled={f.sujet.trim().length<5 || f.msg.trim().length<10 || occ} onClick={creer}>{occ?'Envoi…':'Envoyer'}</Btn></>}>
      <Grid cols="1fr 1fr" mcols="1fr"><Field label="Catégorie"><Sel label="Catégorie" opts={['Intégration technique','Opération / contrat','Solde et dépôts','Mise en production','Autre']} value={f.cat} onChange={v=>setF({...f, cat:v})}/></Field><Field label="Priorité"><Sel label="Priorité" opts={PRIO} value={f.prio} onChange={v=>setF({...f, prio:v})}/></Field></Grid>
      <Field label="Sujet" hint="5 caractères au moins."><Inp value={f.sujet} onChange={e=>setF({...f, sujet:e.target.value})} placeholder="Résumez le problème"/></Field>
      <Field label="Référence liée" opt><Inp value={f.ref} onChange={e=>setF({...f, ref:e.target.value})} placeholder="Référence de contrat, ctr_… ou req_…" mono/></Field>
      <Field label="Description" hint="10 caractères au moins."><textarea className="li" rows={5} value={f.msg} onChange={e=>setF({...f, msg:e.target.value})} style={{...inpCss, height:'auto', padding:12, resize:'vertical', lineHeight:1.5}} placeholder="Ce que vous avez fait, ce qui s'est passé, ce que vous attendiez."></textarea></Field>
      {err && <Notice tone="bad">{err.message}</Notice>}</Modal>}
    {sel && <TicketFil id={sel} onClose={()=>setSel(null)} onChange={rTk}/>}
  </Page>;
}
function TicketFil({id, onClose, onChange}){
  const toast = useToast(); const [t, recharger, etat] = useDonnees(() => api('GET', `tickets/${encodeURIComponent(id)}`), [id]);
  const [rep, setRep] = React.useState(''), [occ, setOcc] = React.useState(false); const bas = React.useRef(null);
  React.useEffect(()=>{ if(bas.current) bas.current.scrollIntoView({block:'end'}); }, [t]);
  const envoyer = async () => { setOcc(true); try { await api('POST', `tickets/${encodeURIComponent(id)}/messages`, {texte:rep.trim()}); setRep(''); recharger(); onChange && onChange(); } catch(e){ toast(e.message, 'bad'); } setOcc(false); };
  return <Modal title={t ? t.sujet : 'Demande'} icon="lifebuoy" onClose={onClose} w={640}
    foot={t && t.statut!=='ferme' && <div style={{display:'flex', gap:8, width:'100%'}}><div style={{flex:1, minWidth:0}}><Inp value={rep} onChange={e=>setRep(e.target.value)} placeholder="Votre réponse…" aria-label="Votre réponse" onKeyDown={e=>{ if(e.key==='Enter' && rep.trim().length>1 && !occ) envoyer(); }}/></div><Btn icon="paper-plane-tilt" disabled={rep.trim().length<2||occ} onClick={envoyer}>Envoyer</Btn></div>}>
    {etat.erreur ? <Notice tone="bad">{etat.erreur.message}</Notice> : !t ? <><Skel h={60} r={18}/><Skel h={60} r={18}/></> : <>
      <div style={{display:'flex', gap:8, flexWrap:'wrap', alignItems:'center'}}><Badge tone={(TK[t.statut]||[0,'mute'])[1]}>{(TK[t.statut]||[t.statut])[0]}</Badge><Badge>Priorité {(PRIO.find(p=>p[0]===t.priorite)||[0,t.priorite])[1].split(' ')[0].toLowerCase()}</Badge><Mono s={11.5}>{t.id}</Mono><span style={{fontSize:12, color:V.ink3}}>· ouvert le {DC(t.cree_le)}</span></div>
      <div style={{display:'flex', flexDirection:'column', gap:10}}>{t.messages.map((x,i)=>{ const sup = x.auteur_type==='staff'; return <div key={i} style={{alignSelf:sup?'flex-start':'flex-end', maxWidth:'88%', padding:'12px 14px', borderRadius:sup?'18px 18px 18px 6px':'18px 18px 6px 18px', background:sup?V.sub:V.mint, fontSize:13.5, lineHeight:1.5, whiteSpace:'pre-wrap', wordBreak:'break-word'}}>{x.texte}<span style={{display:'flex', alignItems:'center', gap:5, marginTop:6, fontSize:11.5, fontWeight:600, color:sup?V.accD:V.ink3}}>{sup && <I n="seal-check" s={13} fill/>}{x.auteur || (sup?'Support LMS':'Vous')} · {DC(x.le)}</span></div>; })}</div>
      {t.statut==='ferme' && <Notice tone="info">Demande fermée. Ouvrez un nouveau ticket si besoin.</Notice>}
      <span ref={bas}></span></>}
  </Modal>;
}

Object.assign(window, {Prod, StageBanner, KycFlow, Documents, LogoEntreprise, CompanyProfile, Team, Settings, Help, TicketFil});
