/* global React, DictoIcons */
// backoffice.jsx — Dicto BO · Settings/Backoffice prototype
// Roles: Super Admin (dev / DictoAI team), Admin (cliente owner), Configurator (editor), Viewer (viewer)
// Re-runner is excluded as a simulated viewing role — it's a postazione that admins can assign.

const {
  IconBack, IconBuilding, IconUser, IconUsers, IconSettings,
  IconBook, IconLayers, IconCheck, IconChart, IconChevDown, IconChevRight,
  IconSparkles, IconPlus, IconX, IconSearch, IconBolt, IconLock,
  IconDots, IconTrash, IconUpload, IconTag, IconInfo,
} = window.DictoIcons;

// ─── Mock data: customer organizations (the orgs Dicto sells to) ─
const INITIAL_ORGANIZATIONS = [
  { id:'isp', name:'Intesa Sanpaolo', domain:'intesasanpaolo.com', color:'#0B6B3A', plan:'Enterprise', totalSeats:15, availableSeats:7, totalMembers:8, unassignedMembers:1, projects:4 },
  { id:'edi', name:'Edison',          domain:'edison.it',          color:'#1D4ED8', plan:'Growth',     totalSeats:10, availableSeats:4, totalMembers:6, unassignedMembers:0, projects:3 },
  { id:'ferr',name:'Ferrero S.p.A.',  domain:'ferrero.com',        color:'#E94E1B', plan:'Enterprise', totalSeats:20, availableSeats:8, totalMembers:12, unassignedMembers:2, projects:6 },
  { id:'gen', name:'Generali Italia', domain:'generali.it',        color:'#9B1B30', plan:'Growth',     totalSeats:8,  availableSeats:3, totalMembers:5,  unassignedMembers:0, projects:2 },
];

const TEAMS_BY_ORG = {
  isp:  ['Comms & Reputation', 'Investor Relations', 'Public Affairs', 'Risk & Compliance', 'Non assegnato'],
  edi:  ['Brand & Sustainability', 'Public Affairs', 'Marketing', 'Non assegnato'],
  ferr: ['Brand Intelligence', 'Comms & Reputation', 'Public Affairs', 'Non assegnato'],
  gen:  ['Brand & Reputation', 'Investor Relations', 'Non assegnato'],
};

const MEMBERS_BY_ORG = {
  isp: [
    { id:'i1', name:'Carlo Messina',     email:'carlo.messina@intesasanpaolo.com',     seat:'admin',         team:'Comms & Reputation', status:'active' },
    { id:'i2', name:'Marina Natale',     email:'marina.natale@intesasanpaolo.com',     seat:'configurator',  team:'Investor Relations', status:'active', isYou:true },
    { id:'i3', name:'Stefano Del Punta', email:'stefano.delpunta@intesasanpaolo.com',  seat:'configurator',  team:'Risk & Compliance',  status:'active' },
    { id:'i4', name:'Paola Angeletti',   email:'paola.angeletti@intesasanpaolo.com',   seat:'runner',        team:'Comms & Reputation', status:'active' },
    { id:'i5', name:'Andrea Munari',     email:'andrea.munari@intesasanpaolo.com',     seat:'runner',        team:'Public Affairs',     status:'active' },
    { id:'i6', name:'Elena Goitini',     email:'elena.goitini@intesasanpaolo.com',     seat:'viewer',        team:'Comms & Reputation', status:'active' },
    { id:'i7', name:'Marco Siracusano',  email:'marco.siracusano@intesasanpaolo.com',  seat:'viewer',        team:'Investor Relations', status:'invited' },
    { id:'i8', name:'Giulia Tonelli',    email:'giulia.tonelli@intesasanpaolo.com',    seat:'unassigned',    team:'Non assegnato',      status:'invited' },
  ],
  edi: [
    { id:'e1', name:'Nicola Monti',      email:'nicola.monti@edison.it',         seat:'admin',        team:'Brand & Sustainability', status:'active' },
    { id:'e2', name:'Cristina Parenti',  email:'cristina.parenti@edison.it',     seat:'configurator', team:'Brand & Sustainability', status:'active' },
    { id:'e3', name:'Marco Stangalini',  email:'marco.stangalini@edison.it',     seat:'configurator', team:'Public Affairs',         status:'active' },
    { id:'e4', name:'Federica Bertolini',email:'federica.bertolini@edison.it',   seat:'runner',       team:'Marketing',              status:'active' },
    { id:'e5', name:'Paolo Quaini',      email:'paolo.quaini@edison.it',         seat:'viewer',       team:'Public Affairs',         status:'active' },
    { id:'e6', name:'Sara Cervati',      email:'sara.cervati@edison.it',         seat:'viewer',       team:'Brand & Sustainability', status:'invited' },
  ],
  ferr: [
    { id:'f1', name:'Lapo Civiletti',    email:'lapo.civiletti@ferrero.com',     seat:'admin',        team:'Brand Intelligence',     status:'active' },
    { id:'f2', name:'Manuela Kron',      email:'manuela.kron@ferrero.com',       seat:'configurator', team:'Brand Intelligence',     status:'active' },
    { id:'f3', name:'Alessandro Bevolo', email:'alessandro.bevolo@ferrero.com',  seat:'configurator', team:'Comms & Reputation',     status:'active' },
    { id:'f4', name:'Chiara Lazzari',    email:'chiara.lazzari@ferrero.com',     seat:'runner',       team:'Public Affairs',         status:'active' },
  ],
  gen: [
    { id:'g1', name:'Philippe Donnet',   email:'philippe.donnet@generali.com',   seat:'admin',        team:'Brand & Reputation',     status:'active' },
    { id:'g2', name:'Cristiano Borean',  email:'cristiano.borean@generali.com',  seat:'configurator', team:'Investor Relations',     status:'active' },
    { id:'g3', name:'Lucia Silva',       email:'lucia.silva@generali.com',       seat:'viewer',       team:'Brand & Reputation',     status:'active' },
  ],
};

const BILLING_BY_ORG = {
  isp: {
    plan: 'Enterprise', price: 4800,
    seatsIncl: 15, analysesIncl: 50, rerunsIncl: 200, frequencyMax: 'Giornaliera',
    seatsUsed: 8, analysesUsed: 12, rerunsUsed: 145,
    nextCharge: '01 maggio 2026',
    creditsBalance: 320, creditsValue: 640, creditPrice: 2,
    paymentMethod: { type:'card', brand:'VISA', last4:'4242', exp:'12/27', holder:'Intesa Sanpaolo S.p.A.' },
    fiscal: {
      ragione: 'Intesa Sanpaolo S.p.A.',
      address: 'Piazza San Carlo, 156',
      city: '10121 Torino (TO), Italia',
      piva: '11991500015',
      cf: '00799960158',
      pec: 'governance@pec.intesasanpaolo.com',
      cd: 'MMSGYUV',
    },
    invoices: [
      { date:'01/04/2026', n:'2026/0042', period:'Aprile 2026',                amount:4800,  status:'pending' },
      { date:'01/03/2026', n:'2026/0031', period:'Marzo 2026',                  amount:4800,  status:'paid' },
      { date:'01/02/2026', n:'2026/0023', period:'Febbraio 2026 + 50 cr extra', amount:4900,  status:'paid' },
      { date:'01/01/2026', n:'2026/0011', period:'Gennaio 2026',                amount:4800,  status:'paid' },
      { date:'01/12/2025', n:'2025/0240', period:'Dicembre 2025',               amount:4800,  status:'paid' },
      { date:'01/11/2025', n:'2025/0221', period:'Novembre 2025',               amount:4800,  status:'paid' },
    ],
    creditsTx: [
      { date:'29/04/2026', kind:'out', desc:'Re-run progetto "Reputazione Carlo Messina"',     delta:-5,  balance:320 },
      { date:'28/04/2026', kind:'out', desc:'Frequenza giornaliera "Sustainability narrative"', delta:-20, balance:325 },
      { date:'25/04/2026', kind:'out', desc:'Re-run progetto "AI nel banking — narrativa"',    delta:-5,  balance:345 },
      { date:'15/04/2026', kind:'in',  desc:'Ricarica pacchetto crediti aggiuntivi (200)',      delta:200, balance:350 },
      { date:'01/04/2026', kind:'in',  desc:'Crediti inclusi nel piano Enterprise',             delta:50,  balance:150 },
      { date:'28/03/2026', kind:'out', desc:'Re-run extra "Tassazione bancaria UE"',            delta:-10, balance:100 },
    ],
  },
  edi: {
    plan: 'Growth', price: 1800,
    seatsIncl: 10, analysesIncl: 20, rerunsIncl: 80, frequencyMax: 'Settimanale',
    seatsUsed: 6, analysesUsed: 8, rerunsUsed: 62,
    nextCharge: '01 maggio 2026',
    creditsBalance: 80, creditsValue: 160, creditPrice: 2,
    paymentMethod: { type:'sepa', iban:'IT60•••••••••••••••••0123', holder:'Edison S.p.A.' },
    fiscal: {
      ragione: 'Edison S.p.A.',
      address: 'Foro Buonaparte, 31',
      city: '20121 Milano (MI), Italia',
      piva: '06598640960',
      cf: '06598640960',
      pec: 'edison@pec.edison.it',
      cd: 'A4707H7',
    },
    invoices: [
      { date:'01/04/2026', n:'2026/0086', period:'Aprile 2026',  amount:1800, status:'pending' },
      { date:'01/03/2026', n:'2026/0061', period:'Marzo 2026',   amount:1800, status:'paid' },
      { date:'01/02/2026', n:'2026/0042', period:'Febbraio 2026',amount:1800, status:'paid' },
      { date:'01/01/2026', n:'2026/0019', period:'Gennaio 2026', amount:1800, status:'paid' },
    ],
    creditsTx: [
      { date:'27/04/2026', kind:'out', desc:'Re-run extra "Transizione energetica"', delta:-5, balance:80 },
      { date:'01/04/2026', kind:'in',  desc:'Crediti inclusi nel piano Growth',      delta:20, balance:85 },
      { date:'30/03/2026', kind:'out', desc:'Re-run extra "Edison brand reputation"', delta:-5, balance:65 },
    ],
  },
  ferr: {
    plan: 'Enterprise', price: 6500,
    seatsIncl: 20, analysesIncl: 80, rerunsIncl: 300, frequencyMax: 'Giornaliera',
    seatsUsed: 12, analysesUsed: 24, rerunsUsed: 218,
    nextCharge: '01 maggio 2026',
    creditsBalance: 540, creditsValue: 1080, creditPrice: 2,
    paymentMethod: { type:'card', brand:'AMEX', last4:'1003', exp:'08/28', holder:'Ferrero S.p.A.' },
    fiscal: {
      ragione: 'Ferrero S.p.A.',
      address: 'Piazzale Pietro Ferrero, 1',
      city: '12051 Alba (CN), Italia',
      piva: '02914930040',
      cf: '02914930040',
      pec: 'ferrero@pec.ferrero.com',
      cd: 'XL13LG4',
    },
    invoices: [
      { date:'01/04/2026', n:'2026/0044', period:'Aprile 2026',  amount:6500, status:'pending' },
      { date:'01/03/2026', n:'2026/0033', period:'Marzo 2026',   amount:6500, status:'paid' },
      { date:'01/02/2026', n:'2026/0021', period:'Febbraio 2026',amount:6700, status:'paid' },
    ],
    creditsTx: [
      { date:'29/04/2026', kind:'out', desc:'Re-run extra "Monitoraggio Nutella"', delta:-15, balance:540 },
      { date:'15/04/2026', kind:'in',  desc:'Ricarica pacchetto crediti (500)',     delta:500, balance:555 },
    ],
  },
  gen: {
    plan: 'Growth', price: 1800,
    seatsIncl: 10, analysesIncl: 20, rerunsIncl: 80, frequencyMax: 'Settimanale',
    seatsUsed: 5, analysesUsed: 4, rerunsUsed: 28,
    nextCharge: '01 maggio 2026',
    creditsBalance: 18, creditsValue: 36, creditPrice: 2,
    paymentMethod: { type:'card', brand:'MASTERCARD', last4:'8821', exp:'05/27', holder:'Generali Italia S.p.A.' },
    fiscal: {
      ragione: 'Generali Italia S.p.A.',
      address: 'Via Marocchesa, 14',
      city: '31021 Mogliano Veneto (TV), Italia',
      piva: '01333550323',
      cf: '00079760328',
      pec: 'generali@pec.generaligroup.com',
      cd: 'M5UXCR1',
    },
    invoices: [
      { date:'01/04/2026', n:'2026/0089', period:'Aprile 2026',  amount:1800, status:'pending' },
      { date:'01/03/2026', n:'2026/0064', period:'Marzo 2026',   amount:1800, status:'paid' },
    ],
    creditsTx: [
      { date:'01/04/2026', kind:'in', desc:'Crediti inclusi nel piano Growth', delta:20, balance:18 },
    ],
  },
};

const PROJECTS_BY_ORG = {
  isp:  [
    { id:'p1', name:'Reputazione Carlo Messina',     type:'Personal', subject:'Carlo Messina',  team:'Comms & Reputation', updated:'oggi',         status:'running' },
    { id:'p2', name:'Sustainability narrative ISP',  type:'Brand',    subject:'Intesa Sanpaolo',team:'Comms & Reputation', updated:'2 giorni fa',  status:'idle' },
    { id:'p3', name:'Tassazione bancaria UE',        type:'Topic',    subject:'Bank tax UE',    team:'Public Affairs',     updated:'1 settimana fa', status:'idle' },
    { id:'p4', name:'AI per il banking — narrativa', type:'Topic',    subject:'AI nel banking', team:'Risk & Compliance',  updated:'4 ore fa',      status:'running' },
  ],
  edi:  [
    { id:'p1', name:'Transizione energetica',         type:'Topic',    subject:'Transizione energetica',  team:'Public Affairs',          updated:'oggi',        status:'running' },
    { id:'p2', name:'Edison brand reputation',        type:'Brand',    subject:'Edison',                  team:'Brand & Sustainability',  updated:'5 giorni fa', status:'idle' },
    { id:'p3', name:'CEO reputation Nicola Monti',    type:'Personal', subject:'Nicola Monti',            team:'Brand & Sustainability',  updated:'oggi',        status:'idle' },
  ],
  ferr: [
    { id:'p1', name:'Monitoraggio Nutella',           type:'Brand',    subject:'Nutella',                 team:'Brand Intelligence',  updated:'oggi',         status:'running' },
    { id:'p2', name:'Cibi ultra processati',          type:'Topic',    subject:'UPF',                     team:'Public Affairs',      updated:'2 giorni fa',  status:'idle' },
    { id:'p3', name:'Ferrero Group reputation',       type:'Brand',    subject:'Ferrero Group',           team:'Comms & Reputation',  updated:'oggi',         status:'running' },
    { id:'p4', name:'Olio di palma narrativa',        type:'Topic',    subject:'Olio di palma',           team:'Public Affairs',      updated:'3 settimane fa', status:'idle' },
    { id:'p5', name:'Kinder portfolio',               type:'Brand',    subject:'Kinder',                  team:'Brand Intelligence',  updated:'1 settimana fa', status:'idle' },
    { id:'p6', name:'Ferrero CEO reputation',         type:'Personal', subject:'Lapo Civiletti',          team:'Comms & Reputation',  updated:'2 giorni fa',  status:'idle' },
  ],
  gen:  [
    { id:'p1', name:'Generali brand reputation',      type:'Brand',    subject:'Generali Italia',         team:'Brand & Reputation',     updated:'oggi',        status:'running' },
    { id:'p2', name:'Donnet — IR narrative',          type:'Personal', subject:'Philippe Donnet',         team:'Investor Relations',     updated:'5 giorni fa', status:'idle' },
  ],
};

const SEAT_LABELS = {
  configurator: 'Configurator',
  runner:       'Re-runner',
  viewer:       'Viewer',
  unassigned:   'Non assegnato',
};

const AVATAR_COLORS = [
  ['#FDEDE6', '#C03D0F'],
  ['#E6F7EC', '#15803D'],
  ['#EFF6FF', '#1D4ED8'],
  ['#F1EBFF', '#6D28D9'],
  ['#FFF7ED', '#9A3412'],
  ['#FCE7F3', '#BE185D'],
];
const colorFor = (s) => AVATAR_COLORS[(s || '').charCodeAt(0) % AVATAR_COLORS.length];
const initials = (name) => name.split(' ').slice(0,2).map(s => s[0]).join('').toUpperCase();

// ─── Role pill (top center) ────────────────────────────────────
function RolePill({ role, setRole }) {
  const roles = [
    { k:'superadmin',  t:'Super Admin' },
    { k:'admin',       t:'Admin' },
    { k:'configurator',t:'Configurator' },
    { k:'viewer',      t:'Viewer' },
  ];
  const lbl = roles.find(r => r.k === role)?.t;
  return (
    <div className={'role-pill ' + role}>
      <span className="lbl">Vista</span>
      <span className="val">{lbl}</span>
      <span style={{color:'rgba(255,255,255,0.3)'}}>·</span>
      <span style={{color:'rgba(255,255,255,0.7)', fontSize:11}}>simulazione ruolo</span>
      <div className="seg">
        {roles.map(r => (
          <button
            key={r.k}
            className={role === r.k ? 'on' : ''}
            onClick={() => setRole(r.k)}>
            {r.t}
          </button>
        ))}
      </div>
    </div>
  );
}

// ─── Org selector dropdown (super admin only) ────────────────
function OrgSelector({ org, onChange, role, onShowAll, organizations }) {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, []);

  const isSuper = role === 'superadmin';

  if (!isSuper) {
    return (
      <div className="org-selector" style={{cursor:'default'}}>
        <span className="lbl-sm">Organizzazione</span>
        <div className="ic" style={{background: org.color}}>{org.name[0]}</div>
        <span>{org.name}</span>
      </div>
    );
  }
  return (
    <div ref={ref} style={{position:'relative'}}>
      <div className="org-selector" onClick={() => setOpen(!open)}>
        <span className="lbl-sm">Cliente</span>
        <div className="ic" style={{background: org.color}}>{org.name[0]}</div>
        <span>{org.name}</span>
        <IconChevDown size={14} style={{color:'#8A8A93', marginLeft:2}}/>
      </div>
      {open && (
        <div className="org-selector-dropdown">
          <div style={{padding:'10px 14px', fontSize:11, fontWeight:600, color:'#8A8A93', textTransform:'uppercase', letterSpacing:'0.06em', borderBottom:'1px solid #F0F0F3'}}>
            Organizzazioni clienti
          </div>
          {organizations.map(o => (
            <div
              key={o.id}
              className="item"
              onClick={() => { onChange(o); setOpen(false); }}
              style={o.id === org.id ? {background:'#FAFAFB'} : null}>
              <div className="ic" style={{width:28, height:28, borderRadius:6, background:o.color, color:'#fff', fontWeight:700, fontSize:12, display:'grid', placeItems:'center', flex:'0 0 28px'}}>{o.name[0]}</div>
              <div style={{flex:1, minWidth:0}}>
                <div style={{fontSize:13, fontWeight:500, color:'#0A0A0B'}}>{o.name}</div>
                <div style={{fontSize:11, color:'#8A8A93'}}>{o.domain} · {o.totalMembers} membri</div>
              </div>
              {o.id === org.id && <IconCheck size={14} stroke={3} style={{color:'#0A0A0B'}}/>}
            </div>
          ))}
          <div className="item special" onClick={() => { onShowAll(); setOpen(false); }}>
            <div style={{width:28, height:28, borderRadius:6, background:'#EEF0FF', color:'#3B4AF5', display:'grid', placeItems:'center', flex:'0 0 28px'}}>
              <IconChart size={14}/>
            </div>
            <div style={{flex:1}}>Vedi tutte le organizzazioni →</div>
          </div>
        </div>
      )}
    </div>
  );
}

// ─── Page header ───────────────────────────────────────────────
function PageHead({ role, org, onChangeOrg, onShowAll, onBack, viewMode, organizations }) {
  return (
    <div className="bo-page-head">
      <div style={{display:'flex', alignItems:'center', gap:14}}>
        {viewMode === 'orgs-list' ? (
          <h1>Backoffice DictoAI · Organizations</h1>
        ) : (
          <>
            <h1>{role === 'viewer' ? 'Progetti' : 'Impostazioni organizzazione'}</h1>
            <OrgSelector org={org} onChange={onChangeOrg} role={role} onShowAll={onShowAll} organizations={organizations}/>
          </>
        )}
        {viewMode === 'orgs-list' && (
          <span className="chip" style={{height:22, fontSize:11, background:'#F1EBFF', color:'#6D28D9', borderColor:'transparent'}}>Solo Super Admin</span>
        )}
      </div>
      <div className="head-actions">
        {viewMode !== 'orgs-list' && role === 'superadmin' && (
          <button
            className="btn ghost sm"
            style={{height:36}}
            onClick={onShowAll}>
            <IconBack size={13}/> Tutte le organizzazioni
          </button>
        )}
        <button className="bell" aria-label="Notifiche">
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
            <path d="M18 8a6 6 0 00-12 0c0 7-3 9-3 9h18s-3-2-3-9"/>
            <path d="M13.7 21a2 2 0 01-3.4 0"/>
          </svg>
        </button>
        <div style={{
          width:36, height:36, borderRadius:'50%',
          background:'#F1EBFF', color:'#8B5CF6',
          fontSize:12, fontWeight:600,
          display:'grid', placeItems:'center'
        }}>{role === 'superadmin' ? 'DA' : 'GC'}</div>
      </div>
    </div>
  );
}

// ─── Top tabs (Organizzazione | Progetti) ─────────────────────
function TabBar({ activeTab, setActiveTab, projectsCount, membersCount, role }) {
  const isViewer = role === 'viewer';
  return (
    <div className="tab-bar">
      {!isViewer && (
        <button className={'tab' + (activeTab === 'organization' ? ' active' : '')} onClick={() => setActiveTab('organization')}>
          <IconBuilding size={15}/> Organizzazione
          <span className="tab-count">{membersCount}</span>
        </button>
      )}
      <button className={'tab' + (activeTab === 'projects' ? ' active' : '')} onClick={() => setActiveTab('projects')}>
        <IconLayers size={15}/> Progetti
        <span className="tab-count">{projectsCount}</span>
      </button>
    </div>
  );
}

// ─── Settings sidebar (left) ──────────────────────────────────
function SettingsSidebar({ active, setActive, role }) {
  const isSuper = role === 'superadmin';
  const isAdmin = role === 'admin' || isSuper;

  // Organizzazione & Progetti are tabs; this sidebar is sub-navigation INSIDE Organizzazione tab.
  const items = [
    { k:'overview', ic:<IconChart/>,  lbl:'Panoramica',           visible:true },
    { k:'members',  ic:<IconUsers/>,  lbl:'Membri & Postazioni',  visible:true },
    { k:'billing',  ic:<IconTag/>,    lbl:'Fatturazione & Crediti', visible:true,  locked: !isAdmin },
    { k:'audit',    ic:<IconCheck/>,  lbl:'Audit log',            visible:isSuper },
    { k:'danger',   ic:<IconX/>,      lbl:'Danger zone',          visible:isSuper },
  ];
  return (
    <aside className="settings-nav">
      <div className="settings-nav-group">Impostazioni organizzazione</div>
      {items.filter(it => it.visible).map(it => (
        <div
          key={it.k}
          className={'settings-nav-item' + (active === it.k ? ' active' : '') + (it.locked ? ' locked' : '')}
          onClick={() => !it.locked && setActive(it.k)}>
          {it.ic} {it.lbl}
          {it.locked && <IconLock size={12} style={{marginLeft:'auto', color:'#B8B8BF'}}/>}
        </div>
      ))}
    </aside>
  );
}

// ─── Section: Team overview ────────────────────────────────────
function TeamOverview({ role, org }) {
  const canEdit = role === 'admin' || role === 'superadmin';
  return (
    <div className="settings-section">
      <h2>Panoramica del team</h2>
      <div className="overview-grid">
        <div className="overview-cell">
          <div className="v">{org.domain}</div>
          <div className="lbl">Dominio email consentito</div>
          {canEdit && <button className="cta">Aggiorna →</button>}
        </div>
        <div className="overview-cell">
          <div className="v">{org.totalSeats} <span style={{color:'#8A8A93', fontWeight:500, fontSize:14}}>({org.availableSeats} disponibili)</span></div>
          <div className="lbl">Postazioni totali · piano <strong>{org.plan}</strong></div>
          {canEdit && <button className="cta">Gestisci postazioni →</button>}
        </div>
        <div className="overview-cell">
          <div className="v">{org.totalMembers} <span style={{color:'#8A8A93', fontWeight:500, fontSize:14}}>({org.unassignedMembers} non assegnato)</span></div>
          <div className="lbl">Membri totali</div>
          <button className="cta">Visualizza dettagli →</button>
        </div>
      </div>
    </div>
  );
}

// ─── Section: Org identity ─────────────────────────────────────
function OrgIdentity({ role, org }) {
  const canEdit = role === 'admin' || role === 'superadmin';
  const [name, setName] = React.useState(org.name);
  React.useEffect(() => { setName(org.name); }, [org.id]);
  const dirty = name !== org.name;
  return (
    <div className="settings-section">
      <h2>Identità organizzazione</h2>
      <div className="org-identity">
        <div className="org-logo" style={{background: org.color}}>
          <span style={{fontSize:18, fontWeight:700, color:'#fff'}}>{org.name[0]}</span>
        </div>
        <div className="org-logo-input">
          <small>Nome organizzazione</small>
          <input
            className="input"
            value={name}
            onChange={(e) => setName(e.target.value)}
            disabled={!canEdit}
            style={{maxWidth:340, background: canEdit ? '#fff' : '#F2F2F5'}}/>
        </div>
        <button
          className={'btn ' + (canEdit && dirty ? 'primary' : 'secondary')}
          disabled={!canEdit || !dirty}
          style={{opacity: !canEdit ? 0.5 : 1}}>
          Salva modifiche
        </button>
      </div>
    </div>
  );
}

// ─── Section: Members table ────────────────────────────────────
function MembersSection({ role, members, setMembers, onAdd, teams }) {
  const canEdit = role === 'admin' || role === 'superadmin';
  const [filter, setFilter] = React.useState('all');
  const [query, setQuery] = React.useState('');

  const filtered = members.filter(m => {
    if (filter !== 'all' && m.seat !== filter) return false;
    if (query && !(m.name.toLowerCase().includes(query.toLowerCase()) || m.email.toLowerCase().includes(query.toLowerCase()))) return false;
    return true;
  });

  const updateSeat = (id, seat) => setMembers(members.map(m => m.id === id ? {...m, seat} : m));
  const updateTeam = (id, team) => setMembers(members.map(m => m.id === id ? {...m, team} : m));
  const removeMember = (id) => setMembers(members.filter(m => m.id !== id));

  return (
    <div className="settings-section">
      <h2>Membri</h2>

      <div className="members-toolbar">
        <div className="left">
          <select className="filter-pill" value={filter} onChange={(e) => setFilter(e.target.value)}>
            <option value="all">Tutti i membri</option>
            <option value="admin">Proprietari</option>
            <option value="configurator">Configurator</option>
            <option value="runner">Re-runner</option>
            <option value="viewer">Viewer</option>
            <option value="unassigned">Non assegnati</option>
          </select>
          <div className="input-group has-leading" style={{width:280}}>
            <span className="leading"><IconSearch size={14}/></span>
            <input
              className="input"
              style={{height:36, fontSize:13}}
              placeholder="Cerca per nome o email…"
              value={query}
              onChange={(e) => setQuery(e.target.value)}/>
          </div>
        </div>
        <div className="right">
          <button className="btn secondary sm" style={{height:36}}>
            <IconUpload size={13}/> Esporta CSV
          </button>
          <button
            className="btn primary sm"
            style={{height:36, opacity: canEdit ? 1 : 0.5}}
            disabled={!canEdit}
            onClick={onAdd}>
            <IconPlus size={13}/> Aggiungi membro
          </button>
        </div>
      </div>

      <table className="members-table">
        <thead>
          <tr>
            <th style={{width:36}}><input type="checkbox" disabled={!canEdit}/></th>
            <th>Nome</th>
            <th style={{width:170}}>Postazione</th>
            <th style={{width:200}}>Team</th>
            <th style={{width:110}}>Stato</th>
            <th style={{width:36}}/>
          </tr>
        </thead>
        <tbody>
          {filtered.map(m => {
            const [bg, fg] = colorFor(m.name);
            const isAdminRow = m.seat === 'admin';
            return (
              <tr key={m.id}>
                <td><input type="checkbox" disabled={!canEdit || isAdminRow}/></td>
                <td>
                  <div className="name-cell">
                    <div className="avatar" style={{background:bg, color:fg}}>{initials(m.name)}</div>
                    <div className="name-stack">
                      <div className="n">
                        {m.name}
                        {m.isYou && <span style={{marginLeft:6, fontSize:10.5, color:'#8A8A93', fontWeight:500}}>(tu)</span>}
                      </div>
                      <div className="e">{m.email}</div>
                    </div>
                  </div>
                </td>
                <td>
                  {isAdminRow ? (
                    <span className="role-badge"><IconCheck size={10} stroke={3}/> Admin (Proprietario)</span>
                  ) : canEdit ? (
                    <select
                      className={'seat-select ' + m.seat}
                      value={m.seat}
                      onChange={(e) => updateSeat(m.id, e.target.value)}>
                      <option value="configurator">Configurator</option>
                      <option value="runner">Re-runner</option>
                      <option value="viewer">Viewer</option>
                      <option value="unassigned">Non assegnato</option>
                    </select>
                  ) : (
                    <span className={'seat-select ' + m.seat} style={{display:'inline-block', cursor:'default'}}>{SEAT_LABELS[m.seat]}</span>
                  )}
                </td>
                <td>
                  {canEdit ? (
                    <select
                      className="team-select"
                      value={m.team}
                      onChange={(e) => updateTeam(m.id, e.target.value)}>
                      {teams.map(t => <option key={t} value={t}>{t}</option>)}
                    </select>
                  ) : (
                    <span style={{fontSize:12.5, color:'#1F1F23'}}>{m.team}</span>
                  )}
                </td>
                <td>
                  <span className={'status-chip ' + m.status}>
                    <span className="dot"/>
                    {m.status === 'active' ? 'Attivo' : m.status === 'invited' ? 'Invitato' : 'Sospeso'}
                  </span>
                </td>
                <td>
                  {canEdit && !isAdminRow && (
                    <button
                      onClick={() => removeMember(m.id)}
                      title="Rimuovi membro"
                      style={{background:'transparent', border:0, color:'#8A8A93', cursor:'pointer', padding:6, borderRadius:6}}>
                      <IconDots size={14}/>
                    </button>
                  )}
                </td>
              </tr>
            );
          })}
          {filtered.length === 0 && (
            <tr><td colSpan="6" style={{textAlign:'center', padding:'40px 16px', color:'#8A8A93'}}>Nessun membro corrisponde ai filtri.</td></tr>
          )}
        </tbody>
      </table>

      <div style={{marginTop:14, fontSize:12, color:'#8A8A93'}}>
        Mostrati <strong style={{color:'#1F1F23'}}>{filtered.length}</strong> di {members.length} membri ·
        Configurator: <strong style={{color:'#1F1F23'}}>{members.filter(m=>m.seat==='configurator').length}</strong> ·
        Re-runner: <strong style={{color:'#1F1F23'}}>{members.filter(m=>m.seat==='runner').length}</strong> ·
        Viewer: <strong style={{color:'#1F1F23'}}>{members.filter(m=>m.seat==='viewer').length}</strong>
      </div>
    </div>
  );
}

// ─── Add organization modal (Super Admin only) ────────────────
const ORG_PLANS = [
  { k:'starter',    label:'Starter',    price:'€ 490 / mese',  meta:'3 postazioni · 5 analisi/mese · 20 ri-esecuzioni · frequenza mensile' },
  { k:'growth',     label:'Growth',     price:'€ 1.800 / mese',meta:'10 postazioni · 20 analisi/mese · 80 ri-esecuzioni · frequenza settimanale' },
  { k:'enterprise', label:'Enterprise', price:'su preventivo',  meta:'15+ postazioni · 50+ analisi/mese · 200+ ri-esecuzioni · frequenza giornaliera · SSO · audit log' },
];
const ORG_COLORS = ['#0B6B3A', '#1D4ED8', '#E94E1B', '#9B1B30', '#6D28D9', '#0E7490', '#B45309', '#0A0A0B'];

const cleanRagione = (s) => s.replace(/\s+(S\.p\.A\.?|S\.r\.l\.?|S\.A\.S\.?|S\.r\.l\.s\.?|Inc\.?|LLC|Ltd\.?|N\.V\.?|GmbH)\s*$/i, '').trim();

function AddOrgModal({ onClose, onConfirm }) {
  const [ragione, setRagione]     = React.useState('');
  const [nameBreve, setNameBreve] = React.useState('');
  const [touchedBreve, setTouchedBreve] = React.useState(false);
  const [domain, setDomain]       = React.useState('');
  const [plan, setPlan]           = React.useState('growth');
  const [color, setColor]         = React.useState(ORG_COLORS[0]);
  const [adminEmail, setAdminEmail] = React.useState('');
  const [adminName, setAdminName]   = React.useState('');

  const updateRagione = (v) => {
    setRagione(v);
    if (!touchedBreve) setNameBreve(cleanRagione(v));
  };

  const updateBreve = (v) => {
    setNameBreve(v);
    setTouchedBreve(true);
  };

  // Auto-suggest dominio from email Admin (if user hasn't typed it)
  React.useEffect(() => {
    if (!domain && adminEmail.includes('@')) {
      const guess = adminEmail.split('@')[1];
      if (guess && guess.includes('.')) setDomain(guess);
    }
  }, [adminEmail]);

  const valid = ragione.trim() && nameBreve.trim() && domain.trim() && /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(adminEmail);
  const planObj = ORG_PLANS.find(p => p.k === plan);

  const submit = () => {
    if (!valid) return;
    const id = nameBreve.toLowerCase().replace(/[^a-z0-9]+/g,'').slice(0,8) + Date.now().toString().slice(-3);
    onConfirm({
      org: {
        id, name: nameBreve.trim(), ragione: ragione.trim(),
        domain: domain.trim().toLowerCase(),
        color, plan: planObj.label,
        totalSeats: plan === 'starter' ? 3 : plan === 'growth' ? 10 : 20,
        availableSeats: (plan === 'starter' ? 3 : plan === 'growth' ? 10 : 20) - 1,
        totalMembers: 1, unassignedMembers: 0, projects: 0,
      },
      admin: {
        email: adminEmail.trim().toLowerCase(),
        name: adminName.trim() || adminEmail.split('@')[0].replace(/[._]/g,' ').replace(/\b\w/g, c => c.toUpperCase()),
      },
      planKey: plan,
    });
  };

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" style={{width:580}} onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <h3>Nuova organizzazione cliente</h3>
          <button className="close" onClick={onClose}><IconX size={14}/></button>
        </div>
        <div className="modal-body" style={{display:'grid', gap:18, maxHeight:'68vh', overflowY:'auto'}}>

          {/* ── Sezione Organizzazione ── */}
          <div>
            <div style={{fontSize:11, fontWeight:600, color:'#8A8A93', textTransform:'uppercase', letterSpacing:'0.06em', marginBottom:10}}>
              Organizzazione
            </div>
            <div style={{display:'grid', gap:14}}>
              <div className="field">
                <label className="field-label">Ragione sociale <span className="req">*</span></label>
                <input
                  className="input"
                  placeholder="Es. Intesa Sanpaolo S.p.A."
                  value={ragione}
                  onChange={(e) => updateRagione(e.target.value)}
                  autoFocus/>
                <div className="field-hint">Denominazione legale completa, usata in fattura.</div>
              </div>

              <div className="field">
                <label className="field-label">Nome breve (display) <span className="req">*</span></label>
                <input
                  className="input"
                  placeholder="Es. Intesa Sanpaolo"
                  value={nameBreve}
                  onChange={(e) => updateBreve(e.target.value)}/>
                <div className="field-hint">Mostrato nella sidebar e nei breadcrumb. Auto-compilato dalla ragione sociale.</div>
              </div>

              <div className="field">
                <label className="field-label">Dominio email consentito <span className="req">*</span></label>
                <div className="input-group has-leading">
                  <span className="leading" style={{fontSize:14, fontWeight:500, color:'#8A8A93'}}>@</span>
                  <input
                    className="input"
                    placeholder="intesasanpaolo.com"
                    value={domain}
                    onChange={(e) => setDomain(e.target.value)}/>
                </div>
                <div className="field-hint">L'Admin potrà invitare solo email di questo dominio.</div>
              </div>

              <div className="field">
                <label className="field-label">Piano iniziale <span className="req">*</span></label>
                <div style={{display:'grid', gap:8}}>
                  {ORG_PLANS.map(p => (
                    <div
                      key={p.k}
                      onClick={() => setPlan(p.k)}
                      style={{
                        padding:'12px 14px',
                        border:'1.5px solid ' + (plan === p.k ? '#0A0A0B' : '#EBEBEF'),
                        background: plan === p.k ? '#FAFAFB' : '#fff',
                        borderRadius:10,
                        cursor:'pointer',
                        boxShadow: plan === p.k ? '0 0 0 3px rgba(10,10,11,0.05)' : 'none',
                        display:'grid', gridTemplateColumns:'20px 1fr auto', gap:12, alignItems:'center',
                      }}>
                      <div style={{
                        width:18, height:18, borderRadius:'50%',
                        border:'1.5px solid ' + (plan === p.k ? '#0A0A0B' : '#DDDDE2'),
                        background: plan === p.k ? '#0A0A0B' : 'transparent',
                        display:'grid', placeItems:'center',
                      }}>
                        {plan === p.k && <div style={{width:6, height:6, borderRadius:'50%', background:'#fff'}}/>}
                      </div>
                      <div>
                        <div style={{fontSize:13.5, fontWeight:600, color:'#0A0A0B'}}>{p.label}</div>
                        <div style={{fontSize:11.5, color:'#4A4A52', marginTop:2}}>{p.meta}</div>
                      </div>
                      <div style={{fontSize:13, fontWeight:600, color: plan === p.k ? '#0A0A0B' : '#8A8A93', whiteSpace:'nowrap', fontVariantNumeric:'tabular-nums'}}>{p.price}</div>
                    </div>
                  ))}
                </div>
              </div>

              <div className="field">
                <label className="field-label">Colore identificativo</label>
                <div style={{display:'flex', gap:8, flexWrap:'wrap'}}>
                  {ORG_COLORS.map(c => (
                    <button
                      key={c}
                      onClick={() => setColor(c)}
                      style={{
                        width:32, height:32, borderRadius:8,
                        background:c, cursor:'pointer',
                        border: color === c ? '2px solid #0A0A0B' : '2px solid transparent',
                        outline: color === c ? '2px solid #fff' : 'none',
                        outlineOffset: color === c ? -2 : 0,
                        padding:0,
                      }}
                      title={c}/>
                  ))}
                </div>
                <div className="field-hint">Usato come accent della sidebar. Il logo immagine può essere caricato in seguito.</div>
              </div>
            </div>
          </div>

          {/* ── Sezione Primo Admin ── */}
          <div style={{borderTop:'1px solid #F0F0F3', paddingTop:18}}>
            <div style={{fontSize:11, fontWeight:600, color:'#8A8A93', textTransform:'uppercase', letterSpacing:'0.06em', marginBottom:4}}>
              Primo Admin (proprietario)
            </div>
            <div style={{fontSize:12, color:'#4A4A52', marginBottom:12, lineHeight:1.5}}>
              Riceverà un invito email per attivare l'organizzazione e configurarla. Potrà invitare altri membri, assegnare team e completare i dati di fatturazione.
            </div>
            <div className="grid-2">
              <div className="field">
                <label className="field-label">Email <span className="req">*</span></label>
                <input
                  className="input"
                  type="email"
                  placeholder={domain ? 'nome.cognome@' + domain : 'admin@azienda.com'}
                  value={adminEmail}
                  onChange={(e) => setAdminEmail(e.target.value)}/>
              </div>
              <div className="field">
                <label className="field-label">Nome e cognome <span className="muted" style={{fontWeight:400}}>opz.</span></label>
                <input
                  className="input"
                  placeholder="Es. Carlo Messina"
                  value={adminName}
                  onChange={(e) => setAdminName(e.target.value)}/>
              </div>
            </div>
          </div>

          <div className="banner" style={{margin:0}}>
            <IconInfo size={16} className="ic"/>
            <div>
              <strong>Cosa configura l'Admin dopo l'accept dell'invito:</strong> dati fiscali (P.IVA, sede legale, PEC, codice destinatario), metodo di pagamento, team, membri e progetti. Non sono richiesti qui.
            </div>
          </div>
        </div>
        <div className="modal-foot">
          <button className="btn ghost" onClick={onClose}>Annulla</button>
          <button className={'btn ' + (valid ? 'primary' : 'secondary')} disabled={!valid} onClick={submit}>
            Crea organizzazione
          </button>
        </div>
      </div>
    </div>
  );
}

// ─── Add member modal ──────────────────────────────────────────
function AddMemberModal({ onClose, onConfirm, org, teams }) {
  const [email, setEmail] = React.useState('');
  const [seat, setSeat] = React.useState('configurator');
  const [team, setTeam] = React.useState(teams[0]);

  const submit = () => {
    if (!email) return;
    const name = email.split('@')[0].replace(/[._]/g, ' ').replace(/\b\w/g, s => s.toUpperCase());
    onConfirm({
      id: 'u' + Date.now(),
      name, email, seat, team, status:'invited',
    });
  };

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <h3>Aggiungi membro a {org.name}</h3>
          <button className="close" onClick={onClose}><IconX size={14}/></button>
        </div>
        <div className="modal-body">
          <div className="field">
            <label className="field-label">Email <span className="req">*</span></label>
            <input
              className="input"
              type="email"
              placeholder={'nome.cognome@' + org.domain}
              value={email}
              onChange={(e) => setEmail(e.target.value)}
              autoFocus/>
            <div className="field-hint">Riceverà un'email d'invito. Deve appartenere al dominio <strong>{org.domain}</strong>.</div>
          </div>
          <div className="grid-2">
            <div className="field">
              <label className="field-label">Postazione</label>
              <select className={'seat-select ' + seat} style={{height:40, fontSize:13.5}} value={seat} onChange={(e) => setSeat(e.target.value)}>
                <option value="configurator">Configurator</option>
                <option value="runner">Re-runner</option>
                <option value="viewer">Viewer</option>
                <option value="unassigned">Non assegnato (decidi dopo)</option>
              </select>
              <div className="field-hint">
                {seat === 'configurator' && 'Crea, modifica e lancia progetti.'}
                {seat === 'runner' && 'Può solo rilanciare analisi già configurate.'}
                {seat === 'viewer' && 'Sola lettura sui progetti a cui è assegnato.'}
                {seat === 'unassigned' && 'L\'utente verrà invitato senza accesso ai progetti.'}
              </div>
            </div>
            <div className="field">
              <label className="field-label">Team</label>
              <select className="team-select" style={{height:40, fontSize:13.5}} value={team} onChange={(e) => setTeam(e.target.value)}>
                {teams.map(t => <option key={t} value={t}>{t}</option>)}
              </select>
              <div className="field-hint">Determina a quali progetti ha accesso di default.</div>
            </div>
          </div>
        </div>
        <div className="modal-foot">
          <button className="btn ghost" onClick={onClose}>Annulla</button>
          <button className={'btn ' + (email ? 'primary' : 'secondary')} disabled={!email} onClick={submit}>
            Invia invito
          </button>
        </div>
      </div>
    </div>
  );
}

// ─── Billing & Credits section ────────────────────────────────
function BillingSection({ role, org, billing }) {
  const fmt = (n) => '€ ' + Number(n).toLocaleString('it-IT', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  const fmtNoDec = (n) => '€ ' + Number(n).toLocaleString('it-IT', { minimumFractionDigits: 0, maximumFractionDigits: 0 });
  const pct = (used, max) => Math.min(100, Math.round((used / max) * 100));
  const meterClass = (p) => p >= 85 ? 'red' : p >= 70 ? 'amber' : 'green';

  const seatsP = pct(billing.seatsUsed, billing.seatsIncl);
  const analysesP = pct(billing.analysesUsed, billing.analysesIncl);
  const rerunsP = pct(billing.rerunsUsed, billing.rerunsIncl);

  return (
    <div className="settings-main">
      {/* ─── Plan hero ─── */}
      <div className="settings-section" style={{paddingTop:8}}>
        <h2>Piano corrente</h2>
        <div className="plan-hero">
          <div>
            <div className="plan-name">
              <h3>{billing.plan}</h3>
              <span className="plan-badge">Attivo</span>
            </div>
            <div className="plan-price">
              <strong>{fmtNoDec(billing.price)}</strong> / mese · IVA esclusa · prossimo addebito {billing.nextCharge}
            </div>
            <div className="plan-meta">
              <span className="plan-meta-item">
                <IconUsers size={13}/> <strong>{billing.seatsIncl}</strong> postazioni
              </span>
              <span className="plan-meta-item">
                <IconLayers size={13}/> <strong>{billing.analysesIncl}</strong> analisi/mese
              </span>
              <span className="plan-meta-item">
                <IconBolt size={13}/> <strong>{billing.rerunsIncl}</strong> ri-esecuzioni/mese
              </span>
              <span className="plan-meta-item">
                <IconCheck size={13}/> Frequenza fino a <strong>{billing.frequencyMax.toLowerCase()}</strong>
              </span>
            </div>
          </div>
          <div className="plan-hero-actions">
            <button className="btn primary">Cambia piano</button>
            <button className="btn secondary">Aggiungi postazioni</button>
          </div>
        </div>
      </div>

      {/* ─── Usage of period + Credits wallet (side by side) ─── */}
      <div className="settings-section">
        <h2>Utilizzo del periodo · aprile 2026</h2>
        <div style={{display:'grid', gridTemplateColumns:'1.4fr 1fr', gap:16}}>
          <div className="usage-card">
            <div className="usage-row">
              <div className="usage-row-head">
                <div className="lbl"><strong>Postazioni attive</strong> sui posti inclusi</div>
                <div className="val">{billing.seatsUsed} <span className="max">/ {billing.seatsIncl}</span></div>
              </div>
              <div className={'bar-meter ' + meterClass(seatsP)}>
                <span style={{width: seatsP + '%'}}/>
              </div>
              <div className="hint">Postazioni aggiuntive: € 240 / postazione / mese</div>
            </div>

            <div className="usage-row">
              <div className="usage-row-head">
                <div className="lbl"><strong>Analisi configurate</strong> questo mese</div>
                <div className="val">{billing.analysesUsed} <span className="max">/ {billing.analysesIncl}</span></div>
              </div>
              <div className={'bar-meter ' + meterClass(analysesP)}>
                <span style={{width: analysesP + '%'}}/>
              </div>
              <div className="hint">Comprende creazione e modifica di progetti</div>
            </div>

            <div className="usage-row">
              <div className="usage-row-head">
                <div className="lbl"><strong>Ri-esecuzioni / iterazioni</strong> questo mese</div>
                <div className="val">{billing.rerunsUsed} <span className="max">/ {billing.rerunsIncl}</span></div>
              </div>
              <div className={'bar-meter ' + meterClass(rerunsP)}>
                <span style={{width: rerunsP + '%'}}/>
              </div>
              <div className={'hint ' + (rerunsP >= 85 ? 'warn' : '')}>
                {rerunsP >= 85
                  ? `Superato l'85% della quota — eventuali ri-esecuzioni extra saranno scalate dal borsellino crediti.`
                  : `Le ri-esecuzioni oltre quota sono scalate dal borsellino crediti (${fmt(billing.creditPrice)} / ri-esecuzione extra).`}
              </div>
            </div>
          </div>

          {/* Credits wallet */}
          <div className="credits-card">
            <div className="lbl">Borsellino crediti</div>
            <div className="val">{billing.creditsBalance}<span className="unit">crediti</span></div>
            <div className="sub">
              Equivalente a <strong style={{color:'#fff'}}>{fmtNoDec(billing.creditsValue)}</strong>.<br/>
              1 credito = {fmt(billing.creditPrice)} = 1 ri-esecuzione extra o 1 settimana di frequenza giornaliera su un progetto.
            </div>
            <div className="actions">
              <button className="btn-fill"><IconPlus size={13}/> Ricarica crediti</button>
              <button className="btn-line">Storico →</button>
            </div>
          </div>
        </div>
      </div>

      {/* ─── Payment + Fiscal data (side by side) ─── */}
      <div className="settings-section">
        <h2>Metodo di pagamento e dati fiscali</h2>
        <div className="card-row">
          <div className="info-card">
            <h4>Metodo di pagamento <button className="edit-link">Aggiorna →</button></h4>
            {billing.paymentMethod.type === 'card' ? (
              <>
                <div className="kv">
                  <div className="k">Tipo</div>
                  <div className="v">Carta {billing.paymentMethod.brand} ••••&nbsp;{billing.paymentMethod.last4}</div>
                </div>
                <div className="kv">
                  <div className="k">Scadenza</div>
                  <div className="v">{billing.paymentMethod.exp}</div>
                </div>
                <div className="kv">
                  <div className="k">Intestatario</div>
                  <div className="v">{billing.paymentMethod.holder}</div>
                </div>
              </>
            ) : (
              <>
                <div className="kv">
                  <div className="k">Tipo</div>
                  <div className="v">SEPA Direct Debit</div>
                </div>
                <div className="kv">
                  <div className="k">IBAN</div>
                  <div className="v mono">{billing.paymentMethod.iban}</div>
                </div>
                <div className="kv">
                  <div className="k">Intestatario</div>
                  <div className="v">{billing.paymentMethod.holder}</div>
                </div>
              </>
            )}
            <div style={{marginTop:14, padding:'10px 12px', background:'#FAFAFB', borderRadius:8, fontSize:11.5, color:'#4A4A52', display:'flex', alignItems:'center', gap:8}}>
              <IconLock size={13} style={{color:'#16A34A'}}/>
              I dati di pagamento sono gestiti da Stripe. Dicto non li conserva.
            </div>
          </div>

          <div className="info-card">
            <h4>Dati per fatturazione elettronica <button className="edit-link">Modifica →</button></h4>
            <div className="kv">
              <div className="k">Ragione sociale</div>
              <div className="v">{billing.fiscal.ragione}</div>
            </div>
            <div className="kv">
              <div className="k">Sede legale</div>
              <div className="v">{billing.fiscal.address}<br/>{billing.fiscal.city}</div>
            </div>
            <div className="kv">
              <div className="k">Partita IVA</div>
              <div className="v mono">{billing.fiscal.piva}</div>
            </div>
            <div className="kv">
              <div className="k">Codice fiscale</div>
              <div className="v mono">{billing.fiscal.cf}</div>
            </div>
            <div className="kv">
              <div className="k">PEC</div>
              <div className="v mono">{billing.fiscal.pec}</div>
            </div>
            <div className="kv">
              <div className="k">Cod. destinatario</div>
              <div className="v mono">{billing.fiscal.cd}</div>
            </div>
          </div>
        </div>
      </div>

      {/* ─── Invoices history ─── */}
      <div className="settings-section">
        <h2 style={{display:'flex', justifyContent:'space-between', alignItems:'center'}}>
          <span>Storico fatture</span>
          <select className="filter-pill" defaultValue="2026" style={{height:32, fontSize:12}}>
            <option value="2026">2026</option>
            <option value="2025">2025</option>
          </select>
        </h2>
        <table className="members-table">
          <thead>
            <tr>
              <th style={{width:120}}>Data</th>
              <th style={{width:140}}>Numero</th>
              <th>Periodo</th>
              <th style={{width:120, textAlign:'right'}}>Importo</th>
              <th style={{width:110}}>Stato</th>
              <th style={{width:120}}>Documento</th>
            </tr>
          </thead>
          <tbody>
            {billing.invoices.map(inv => (
              <tr key={inv.n}>
                <td><span style={{fontVariantNumeric:'tabular-nums', color:'#4A4A52'}}>{inv.date}</span></td>
                <td><span className="kv mono" style={{fontFamily:'JetBrains Mono, monospace', fontSize:12, color:'#1F1F23'}}>{inv.n}</span></td>
                <td><span style={{color:'#1F1F23'}}>{inv.period}</span></td>
                <td style={{textAlign:'right', fontVariantNumeric:'tabular-nums', fontWeight:500}}>{fmt(inv.amount)}</td>
                <td>
                  <span className={'invoice-status ' + inv.status}>
                    <span style={{width:6, height:6, borderRadius:'50%', background:'currentColor'}}/>
                    {inv.status === 'paid' ? 'Pagata' : inv.status === 'pending' ? 'In attesa' : 'Scaduta'}
                  </span>
                </td>
                <td>
                  <button className="btn ghost sm" style={{padding:'0 8px', height:28, color:'#3B4AF5', fontWeight:500}}>
                    <IconUpload size={12} style={{transform:'rotate(180deg)'}}/> Scarica PDF
                  </button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      {/* ─── Credits transactions ─── */}
      <div className="settings-section">
        <h2>Movimenti borsellino crediti</h2>
        <table className="members-table">
          <thead>
            <tr>
              <th style={{width:110}}>Data</th>
              <th style={{width:110}}>Tipo</th>
              <th>Descrizione</th>
              <th style={{width:120, textAlign:'right'}}>Variazione</th>
              <th style={{width:120, textAlign:'right'}}>Saldo</th>
            </tr>
          </thead>
          <tbody>
            {billing.creditsTx.map((t,i) => (
              <tr key={i}>
                <td><span style={{fontVariantNumeric:'tabular-nums', color:'#4A4A52'}}>{t.date}</span></td>
                <td>
                  <span style={{
                    display:'inline-flex', alignItems:'center', gap:6,
                    height:22, padding:'0 10px', borderRadius:999,
                    fontSize:11, fontWeight:500,
                    background: t.kind === 'in' ? '#E6F7EC' : '#FEECEC',
                    color: t.kind === 'in' ? '#15803D' : '#B91C1C',
                  }}>
                    {t.kind === 'in' ? 'Ricarica' : 'Consumo'}
                  </span>
                </td>
                <td><span style={{color:'#1F1F23', fontSize:13}}>{t.desc}</span></td>
                <td style={{textAlign:'right'}}>
                  <span className={'credit-tx-amount ' + t.kind}>
                    {t.delta > 0 ? '+' : ''}{t.delta} cr
                  </span>
                </td>
                <td style={{textAlign:'right', fontVariantNumeric:'tabular-nums', color:'#4A4A52'}}>{t.balance} cr</td>
              </tr>
            ))}
          </tbody>
        </table>
        <div style={{marginTop:14, padding:'12px 14px', background:'#FAFAFB', borderRadius:10, display:'flex', alignItems:'center', justifyContent:'space-between', fontSize:12.5, color:'#4A4A52'}}>
          <span>I crediti residui non scadono. Possono essere usati per ri-esecuzioni extra, frequenze più alte (giornaliera) e set di provider AI premium oltre la quota inclusa nel piano.</span>
          <a style={{color:'#3B4AF5', fontWeight:500, marginLeft:14, whiteSpace:'nowrap'}}>Tariffario crediti →</a>
        </div>
      </div>
    </div>
  );
}

// ─── Projects tab ──────────────────────────────────────────────
function ProjectsTab({ role, org, projects }) {
  const canEdit = role === 'admin' || role === 'configurator' || role === 'superadmin';
  const typeColor = (t) => t === 'Brand' ? '#DC2626' : t === 'Personal' ? '#059669' : '#7C3AED';
  return (
    <div style={{padding:'32px 48px', overflowY:'auto', height:'100%', background:'#fff'}}>
      <div className="hstack" style={{justifyContent:'space-between', marginBottom:20}}>
        <div>
          <h2 style={{fontSize:18, fontWeight:600, margin:0, color:'#0A0A0B', letterSpacing:'-0.015em'}}>Progetti dell'organizzazione</h2>
          <p style={{fontSize:13, color:'#4A4A52', margin:'4px 0 0'}}>Tutti i progetti di analisi configurati per <strong>{org.name}</strong>.</p>
        </div>
        <div className="hstack" style={{gap:10}}>
          <div className="input-group has-leading" style={{width:240}}>
            <span className="leading"><IconSearch size={14}/></span>
            <input className="input" style={{height:36, fontSize:13}} placeholder="Cerca progetto…"/>
          </div>
          <button className={'btn primary sm'} style={{height:36, opacity: canEdit ? 1 : 0.5}} disabled={!canEdit}>
            <IconPlus size={13}/> Nuovo progetto
          </button>
        </div>
      </div>

      <table className="members-table">
        <thead>
          <tr>
            <th>Progetto</th>
            <th style={{width:120}}>Tipologia</th>
            <th style={{width:200}}>Team</th>
            <th style={{width:120}}>Aggiornato</th>
            <th style={{width:100}}>Stato</th>
            <th style={{width:36}}/>
          </tr>
        </thead>
        <tbody>
          {projects.map(p => (
            <tr key={p.id}>
              <td>
                <div className="name-stack">
                  <div className="n" style={{fontSize:13.5}}>{p.name}</div>
                  <div className="e">Soggetto: {p.subject}</div>
                </div>
              </td>
              <td>
                <span style={{display:'inline-flex', alignItems:'center', gap:6, padding:'3px 10px', borderRadius:999, fontSize:11.5, fontWeight:600, color: typeColor(p.type), background: typeColor(p.type) + '15'}}>
                  {p.type}
                </span>
              </td>
              <td><span style={{fontSize:12.5, color:'#1F1F23'}}>{p.team}</span></td>
              <td><span style={{fontSize:12.5, color:'#4A4A52'}}>{p.updated}</span></td>
              <td>
                <span className={'status-chip ' + (p.status === 'running' ? 'active' : 'invited')}>
                  <span className="dot"/>
                  {p.status === 'running' ? 'In esecuzione' : 'Idle'}
                </span>
              </td>
              <td>
                <button style={{background:'transparent', border:0, color:'#8A8A93', cursor:'pointer', padding:6, borderRadius:6}}>
                  <IconDots size={14}/>
                </button>
              </td>
            </tr>
          ))}
        </tbody>
      </table>

      <div style={{marginTop:14, fontSize:12, color:'#8A8A93'}}>
        {projects.length} progetti · {projects.filter(p => p.status === 'running').length} in esecuzione
      </div>
    </div>
  );
}

// ─── Super admin · Organizations list ─────────────────────────
function OrgsListView({ onSelect, organizations, onAddOrg }) {
  return (
    <div style={{padding:'32px 48px', overflowY:'auto', height:'100%', background:'#fff'}}>
      <div style={{marginBottom:24, display:'flex', alignItems:'center', justifyContent:'space-between'}}>
        <div>
          <h2 style={{fontSize:18, fontWeight:600, margin:0, color:'#0A0A0B', letterSpacing:'-0.015em'}}>Organizzazioni clienti</h2>
          <p style={{fontSize:13, color:'#4A4A52', margin:'4px 0 0'}}>Tutte le organizzazioni gestite dal team DictoAI. Click su una card per accedere alle sue impostazioni.</p>
        </div>
        <div className="hstack" style={{gap:10}}>
          <div className="input-group has-leading" style={{width:260}}>
            <span className="leading"><IconSearch size={14}/></span>
            <input className="input" style={{height:36, fontSize:13}} placeholder="Cerca organizzazione…"/>
          </div>
          <button className="btn primary sm" style={{height:36}} onClick={onAddOrg}><IconPlus size={13}/> Nuova organizzazione</button>
        </div>
      </div>
      <div className="orgs-grid">
        {organizations.map((o,i) => (
          <div key={i} className="org-card" onClick={() => onSelect(o)}>
            <div className="org-card-head">
              <div className="ic" style={{background: `linear-gradient(135deg, ${o.color}, ${o.color}DD)`}}>{o.name[0]}</div>
              <div style={{flex:1, minWidth:0}}>
                <div className="name">{o.name}</div>
                <div className="domain">{o.domain}</div>
              </div>
              <span className="chip" style={{height:22, fontSize:11, background:'#F1EBFF', color:'#6D28D9', borderColor:'transparent'}}>{o.plan}</span>
            </div>
            <div className="org-card-meta">
              <div>Postazioni <strong>{o.totalSeats - o.availableSeats}/{o.totalSeats}</strong></div>
              <div>Membri <strong>{o.totalMembers}</strong></div>
              <div>Progetti <strong>{o.projects}</strong></div>
            </div>
            <div style={{display:'flex', gap:8, marginTop:6}}>
              <button className="btn secondary sm" style={{flex:1}} onClick={(e) => { e.stopPropagation(); onSelect(o); }}>Apri</button>
              <button className="btn ghost sm" style={{padding:'0 8px'}} onClick={(e) => e.stopPropagation()}><IconDots size={14}/></button>
            </div>
          </div>
        ))}
        <div className="org-card add" onClick={onAddOrg}>
          <div style={{width:44, height:44, borderRadius:11, background:'#fff', border:'1px solid #EBEBEF', display:'grid', placeItems:'center', marginBottom:10}}>
            <IconPlus size={18}/>
          </div>
          <div style={{fontSize:13.5, fontWeight:600, color:'#0A0A0B', marginBottom:4}}>Nuova organizzazione</div>
          <div style={{fontSize:12, color:'#8A8A93'}}>Crea un nuovo tenant cliente</div>
        </div>
      </div>
    </div>
  );
}

// ─── Locked / placeholder section ──────────────────────────────
function PlaceholderSection({ title, role, lockedFor }) {
  const isLocked = lockedFor && lockedFor.includes(role);
  return (
    <div className="locked-empty">
      <div className="ic" style={isLocked ? null : {background:'#FDEDE6', color:'#C03D0F'}}>
        {isLocked ? <IconLock size={22}/> : <IconSettings size={22}/>}
      </div>
      <h3>{title}</h3>
      <p>
        {isLocked
          ? <>Sezione riservata ad Admin e Super Admin DictoAI. Stai navigando come <strong>{role === 'configurator' ? 'Configurator' : 'Viewer'}</strong>.</>
          : 'Layout dettagliato — alla prossima iterazione del prototipo.'}
      </p>
    </div>
  );
}

// ─── Stage scaler ──────────────────────────────────────────────
function useScaledStage(w = 1440, h = 900) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const node = ref.current;
    if (!node) return;
    const fit = () => {
      const padding = 80;
      const sx = (window.innerWidth - padding) / w;
      const sy = (window.innerHeight - padding) / h;
      const s = Math.min(1, Math.min(sx, sy));
      node.style.transform = `scale(${s})`;
    };
    fit();
    window.addEventListener('resize', fit);
    return () => window.removeEventListener('resize', fit);
  }, [w, h]);
  return ref;
}

// ─── Main App ──────────────────────────────────────────────────
function App() {
  const [role, setRole] = React.useState('admin');
  const [orgId, setOrgId] = React.useState('isp');
  const [activeTab, setActiveTab] = React.useState('organization'); // organization | projects
  const [activeNav, setActiveNav] = React.useState('overview');     // overview | members | billing | audit | danger
  const [viewMode, setViewMode] = React.useState('settings');       // settings | orgs-list (super admin only)
  const [showAddModal, setShowAddModal] = React.useState(false);
  const [showAddOrgModal, setShowAddOrgModal] = React.useState(false);
  const [organizations, setOrganizations] = React.useState(INITIAL_ORGANIZATIONS);
  const [membersByOrg, setMembersByOrg] = React.useState(MEMBERS_BY_ORG);
  const [teamsByOrg, setTeamsByOrg] = React.useState(TEAMS_BY_ORG);
  const [billingByOrg, setBillingByOrg] = React.useState(BILLING_BY_ORG);
  const [projectsByOrg, setProjectsByOrg] = React.useState(PROJECTS_BY_ORG);
  const [toast, setToast] = React.useState(null);
  const stageRef = useScaledStage(1440, 900);

  const org = organizations.find(o => o.id === orgId) || organizations[0];
  const teams = teamsByOrg[orgId] || ['Non assegnato'];
  const members = membersByOrg[orgId] || [];
  const projects = projectsByOrg[orgId] || [];

  const setMembers = (newMembers) => setMembersByOrg({...membersByOrg, [orgId]: newMembers});

  // Snap nav off locked entries when role changes
  React.useEffect(() => {
    if ((role === 'viewer' || role === 'configurator') && ['billing', 'audit', 'danger'].includes(activeNav)) {
      setActiveNav('overview');
    }
    if (role !== 'superadmin' && ['audit', 'danger'].includes(activeNav)) {
      setActiveNav('overview');
    }
    if (role !== 'superadmin' && viewMode === 'orgs-list') {
      setViewMode('settings');
    }
    // Viewer vede solo la tab Progetti
    if (role === 'viewer') {
      setActiveTab('projects');
    }
  }, [role]);

  const handleAdd = (newMember) => {
    setMembers([...members, newMember]);
    setShowAddModal(false);
    setToast('Invito inviato a ' + newMember.email);
    setTimeout(() => setToast(null), 2400);
  };

  const handleSelectOrg = (newOrg) => {
    setOrgId(newOrg.id);
    setViewMode('settings');
    setActiveTab('organization');
    setActiveNav('overview');
  };

  const handleCreateOrg = ({ org: newOrg, admin, planKey }) => {
    // Pricing per piano
    const planConfig = {
      starter:    { price:490,  seatsIncl:3,  analysesIncl:5,  rerunsIncl:20,  frequencyMax:'Mensile',     creditsIncl:10 },
      growth:     { price:1800, seatsIncl:10, analysesIncl:20, rerunsIncl:80,  frequencyMax:'Settimanale', creditsIncl:20 },
      enterprise: { price:0,    seatsIncl:20, analysesIncl:80, rerunsIncl:300, frequencyMax:'Giornaliera', creditsIncl:50 },
    }[planKey];

    // 1. Aggiungi org
    setOrganizations([...organizations, newOrg]);

    // 2. Aggiungi primo Admin come membro
    setMembersByOrg({
      ...membersByOrg,
      [newOrg.id]: [{
        id: 'a' + Date.now(),
        name: admin.name, email: admin.email,
        seat: 'admin', team: 'Generale',
        status: 'invited',
      }],
    });

    // 3. Team default
    setTeamsByOrg({
      ...teamsByOrg,
      [newOrg.id]: ['Generale', 'Non assegnato'],
    });

    // 4. Billing iniziale (vuoto, da configurare dall'admin)
    setBillingByOrg({
      ...billingByOrg,
      [newOrg.id]: {
        plan: newOrg.plan, price: planConfig.price,
        seatsIncl: planConfig.seatsIncl,
        analysesIncl: planConfig.analysesIncl,
        rerunsIncl: planConfig.rerunsIncl,
        frequencyMax: planConfig.frequencyMax,
        seatsUsed: 1, analysesUsed: 0, rerunsUsed: 0,
        nextCharge: 'Da configurare',
        creditsBalance: planConfig.creditsIncl,
        creditsValue: planConfig.creditsIncl * 2,
        creditPrice: 2,
        paymentMethod: { type:'card', brand:'—', last4:'••••', exp:'—', holder:'Da configurare' },
        fiscal: {
          ragione: newOrg.ragione || newOrg.name,
          address: '— da compilare', city: '— da compilare',
          piva: '—', cf: '—', pec: '—', cd: '—',
        },
        invoices: [], creditsTx: [],
      },
    });

    // 5. Progetti vuoti
    setProjectsByOrg({ ...projectsByOrg, [newOrg.id]: [] });

    setShowAddOrgModal(false);
    setToast(`Organizzazione "${newOrg.name}" creata · invito inviato a ${admin.email}`);
    setTimeout(() => setToast(null), 3200);
  };

  // ─── Render ──────────────────────────────────────────────────
  const renderOrganizationContent = () => {
    if (activeNav === 'overview') {
      return (
        <div className="settings-main">
          <TeamOverview role={role} org={org}/>
          <OrgIdentity role={role} org={org}/>
          <MembersSection
            role={role}
            members={members}
            setMembers={setMembers}
            onAdd={() => setShowAddModal(true)}
            teams={teams}/>
        </div>
      );
    }
    if (activeNav === 'members') {
      return (
        <div className="settings-main">
          <MembersSection
            role={role}
            members={members}
            setMembers={setMembers}
            onAdd={() => setShowAddModal(true)}
            teams={teams}/>
        </div>
      );
    }
    if (activeNav === 'billing') {
      const billing = BILLING_BY_ORG[orgId];
      if (!billing) return <div className="settings-main"><PlaceholderSection title="Fatturazione & Crediti" role={role}/></div>;
      return <BillingSection role={role} org={org} billing={billing}/>;
    }
    const titles = {
      audit: 'Audit log',
      danger: 'Danger zone',
    };
    return (
      <div className="settings-main">
        <PlaceholderSection
          title={titles[activeNav] || 'Sezione'}
          role={role}
          lockedFor={[]}/>
      </div>
    );
  };

  return (
    <>
      <RolePill role={role} setRole={setRole}/>

      <div className="stage" ref={stageRef}>
        <div className="step-wrap" key={role + orgId + viewMode + activeTab}>
          <div className="dicto bo-frame">
            <PageHead
              role={role}
              org={org}
              onChangeOrg={handleSelectOrg}
              onShowAll={() => setViewMode('orgs-list')}
              onBack={() => setViewMode('settings')}
              viewMode={viewMode}
              organizations={organizations}/>

            {viewMode === 'orgs-list' ? (
              <OrgsListView
                organizations={organizations}
                onSelect={handleSelectOrg}
                onAddOrg={() => setShowAddOrgModal(true)}/>
            ) : (
              <>
                <TabBar
                  activeTab={activeTab}
                  setActiveTab={setActiveTab}
                  projectsCount={projects.length}
                  membersCount={members.length}
                  role={role}/>
                {activeTab === 'organization' ? (
                  <div className="bo-body">
                    <SettingsSidebar active={activeNav} setActive={setActiveNav} role={role}/>
                    <div style={{overflowY:'auto'}}>
                      {renderOrganizationContent()}
                    </div>
                  </div>
                ) : (
                  <ProjectsTab role={role} org={org} projects={projects}/>
                )}
              </>
            )}
          </div>

          {showAddModal && (
            <AddMemberModal
              org={org}
              teams={teams.filter(t => t !== 'Non assegnato')}
              onClose={() => setShowAddModal(false)}
              onConfirm={handleAdd}/>
          )}
          {showAddOrgModal && (
            <AddOrgModal
              onClose={() => setShowAddOrgModal(false)}
              onConfirm={handleCreateOrg}/>
          )}
        </div>
      </div>

      {toast && (
        <div className="toast">
          <IconCheck size={16} stroke={3}/>
          {toast}
        </div>
      )}
    </>
  );
}

window.DictoBackoffice = { App };
