// Main app — TI_StockConnect
// Wires together login, role-based shells, and view routing.

const { useState: useStateApp, useEffect: useEffectApp } = React;

const API_BASE = window.APP_CONFIG?.API_URL || "/api";

// Helper: date inizio/fine mese corrente
function getMonthStartDate() {
  const d = new Date();
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-01`;
}
function getMonthEndDate() {
  const d = new Date();
  const lastDay = new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate();
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(lastDay).padStart(2, '0')}`;
}

// Navigazione dinamica basata su config e permessi utente
function getNavForRole(role, config, userPermissions) {
  const clientLabel = config?.label_client_plural || t('nav_clients');
  const clientName = config?.client_name || "Cliente";

  if (role === 'c2') {
    // Per utenti c2, filtra in base ai permessi del cliente
    const items = [];
    if (userPermissions?.enable_saldi !== false) {
      items.push({ id: "saldi", label: t('nav_saldi') });
    }
    if (userPermissions?.enable_movimenti === true) {
      items.push({ id: "movimenti", label: t('nav_movimenti') });
    }
    return items;
  }

  return {
    c: [
      { id: "clienti", label: t('nav_clients') },
      { id: "utenti", label: t('nav_users') },
      { id: "saldi", label: t('nav_saldi') },
      { id: "movimenti", label: t('nav_movimenti') },
      { id: "import", label: t('nav_import_log') },
      { id: "audit", label: t('nav_audit_log') },
    ],
    admin: [
      { id: "clients", label: clientName },
      { id: "audit", label: t('nav_audit_log') },
      { id: "config", label: t('nav_system') },
    ],
  }[role] || [];
}

const TWEAK_DEFAULTS = {
  "theme": "light",
  "direction": "default",
  "density": "balanced"
};

function App() {
  const [logged, setLogged] = useStateApp(false);
  const [currentUser, setCurrentUser] = useStateApp(null);
  const [config, setConfig] = useStateApp({});
  const [selectedClient, setSelectedClient] = useStateApp(null);
  const [, forceUpdate] = useStateApp(0);

  const tweaksHook = (typeof useTweaks === "function") ? useTweaks(TWEAK_DEFAULTS) : [TWEAK_DEFAULTS, () => {}];
  const tweaks = tweaksHook[0];
  const setTweak = tweaksHook[1];

  // Listener cambio lingua
  useEffectApp(() => {
    const handleLangChange = () => forceUpdate(n => n + 1);
    window.addEventListener('languageChange', handleLangChange);
    return () => window.removeEventListener('languageChange', handleLangChange);
  }, []);

  // Carica configurazione all'avvio
  useEffectApp(() => {
    fetch(`${API_BASE}/config`)
      .then(r => r.json())
      .then(data => {
        if (data.success) setConfig(data.config);
      });

    // Verifica sessione esistente
    const token = localStorage.getItem("token");
    const savedUser = localStorage.getItem("user");
    if (token && savedUser) {
      try {
        setCurrentUser(JSON.parse(savedUser));
        setLogged(true);
      } catch (e) {
        localStorage.removeItem("token");
        localStorage.removeItem("user");
      }
    }
  }, []);

  useEffectApp(() => {
    document.body.classList.toggle("dark", tweaks.theme === "dark");
    document.body.classList.remove("dir-warm", "dir-green");
    if (tweaks.direction === "warm") document.body.classList.add("dir-warm");
    if (tweaks.direction === "green") document.body.classList.add("dir-green");
  }, [tweaks.theme, tweaks.direction]);

  const role = currentUser?.role || "c2";
  const [tab, setTab] = useStateApp("clients");

  useEffectApp(() => {
    // reset tab when role changes
    const nav = getNavForRole(role, config, currentUser?.permissions);
    if (nav.length > 0) setTab(nav[0].id);
  }, [role, config, currentUser]);

  const handleLogin = (user) => {
    setCurrentUser(user);
    setLogged(true);
  };

  const handleLogout = () => {
    localStorage.removeItem("token");
    localStorage.removeItem("user");
    setCurrentUser(null);
    setLogged(false);
    setSelectedClient(null);
  };

  if (!logged) return <LoginPage onLogin={handleLogin}/>;

  const navItems = getNavForRole(role, config, currentUser?.permissions);
  const userDisplay = {
    name: currentUser?.full_name || currentUser?.username || "Utente",
    role: role === "admin" ? "Amministratore Team" : role === "c" ? "Cliente" : "Utilizzatore",
    initials: (currentUser?.full_name || currentUser?.username || "U").slice(0, 2).toUpperCase()
  };

  return (
    <div className="app">
      <AppHeader
        user={userDisplay}
        role={role}
        config={config}
      />
      <TopNav
        items={navItems}
        active={tab}
        onSelect={(t) => { setTab(t); setSelectedClient(null); }}
        onLogout={handleLogout}
      />
      <main className="app-main">
        {/* Admin views */}
        {role === "admin" && tab === "clients" && !selectedClient && (
          <AdminClients
            onOpenClient={(client) => setSelectedClient(client)}
            config={config}
          />
        )}
        {role === "admin" && tab === "clients" && selectedClient && (
          <AdminClientDetail
            client={selectedClient}
            onBack={() => setSelectedClient(null)}
            onRefresh={() => {
              // Ricarica il client aggiornato
              fetch(`${API_BASE}/clients/${selectedClient.id}`, {
                headers: { Authorization: `Bearer ${localStorage.getItem("token")}` }
              })
                .then(r => r.json())
                .then(data => {
                  if (data.success) setSelectedClient(data.client);
                });
            }}
            config={config}
          />
        )}
        {role === "admin" && tab === "audit" && <AdminAudit />}
        {role === "admin" && tab === "config" && (
          <AdminConfig
            config={config}
            onConfigUpdate={() => {
              fetch(`${API_BASE}/config`)
                .then(r => r.json())
                .then(data => {
                  if (data.success) setConfig(data.config);
                });
            }}
          />
        )}

        {/* Client views */}
        {role === "c" && tab === "clienti" && <ClientClienti user={currentUser} config={config} onOpenUsers={(client) => { setSelectedClient(client); setTab("utenti"); }} />}
        {role === "c" && tab === "utenti" && <ClientAllUsers user={currentUser} config={config} initialClient={selectedClient} />}
        {role === "c" && tab === "saldi" && <ClientSaldiView user={currentUser} config={config} />}
        {role === "c" && tab === "movimenti" && <ClientMovimentiView user={currentUser} config={config} />}
        {role === "c" && tab === "import" && <ClientImportLog user={currentUser} config={config} />}
        {role === "c" && tab === "audit" && <AdminAudit />}

        {/* C2 views */}
        {role === "c2" && tab === "saldi" && <C2SaldiView user={currentUser} config={config} />}
        {role === "c2" && tab === "movimenti" && <C2MovimentiView user={currentUser} config={config} />}
      </main>
      {typeof TweaksPanel === "function" && (
        <TweaksPanel title="Tweaks">
          <TweakSection title="Tema">
            <TweakRadio
              label="Modalità"
              value={tweaks.theme}
              options={[{value: "light", label: "Chiaro"}, {value: "dark", label: "Scuro"}]}
              onChange={(v) => setTweak("theme", v)}
            />
          </TweakSection>
          <TweakSection title="Direzione visiva">
            <TweakRadio
              label="Palette"
              value={tweaks.direction}
              options={[
                {value: "default", label: "Blu TI (originale)"},
                {value: "warm", label: "Warm minimal"},
                {value: "green", label: "Green ops"},
              ]}
              onChange={(v) => setTweak("direction", v)}
            />
          </TweakSection>
        </TweaksPanel>
      )}
    </div>
  );
}

function DisabledModule({ name }) {
  return (
    <div className="panel">
      <div className="panel-body empty">
        <div className="icon" style={{width: 32, height: 32, margin: "0 auto 8px", color: "var(--text-3)"}}>{Icon.shield}</div>
        <div style={{fontWeight: 600, fontSize: 15, color: "var(--text)"}}>Modulo «{name}» non abilitato</div>
        <div style={{maxWidth: 420, margin: "8px auto 0", fontSize: 13}}>
          L'amministratore non ha attivato questo modulo per il tuo profilo.
        </div>
      </div>
    </div>
  );
}

function AdminAudit() {
  const [logs, setLogs] = useStateApp([]);
  const [loading, setLoading] = useStateApp(true);
  const [total, setTotal] = useStateApp(0);
  const [filters, setFilters] = useStateApp({
    data_da: getMonthStartDate(),
    data_a: getMonthEndDate(),
    username: "",
    action: "",
    level: ""
  });

  useEffectApp(() => {
    loadLogs();
  }, []);

  const loadLogs = async () => {
    setLoading(true);
    const token = localStorage.getItem("token");
    const params = new URLSearchParams({ limit: 500 });
    if (filters.data_da) params.append("data_da", filters.data_da);
    if (filters.data_a) params.append("data_a", filters.data_a);
    if (filters.username) params.append("username", filters.username);
    if (filters.action) params.append("action", filters.action);
    if (filters.level) params.append("level", filters.level);

    const res = await fetch(`${API_BASE}/audit?${params}`, {
      headers: { Authorization: `Bearer ${token}` }
    }).then(r => r.json());

    if (res.success) {
      setLogs(res.logs);
      setTotal(res.total);
    }
    setLoading(false);
  };

  const formatDate = (ts) => {
    if (!ts) return "-";
    const d = new Date(ts);
    return d.toLocaleString('it-CH', { dateStyle: 'short', timeStyle: 'medium' });
  };

  const handleFilterChange = (field, value) => {
    setFilters(prev => ({ ...prev, [field]: value }));
  };

  const exportExcel = () => {
    const headers = ["Timestamp", "Utente", "Azione", "Target", "Dettagli", "Livello", "IP"];
    const rows = logs.map(e => [
      formatDate(e.timestamp),
      e.username || "",
      e.action || "",
      e.target || "",
      e.details || "",
      (e.level || "info").toUpperCase(),
      e.ip || ""
    ]);
    const csvContent = "﻿" + [headers, ...rows].map(r => r.map(c => `"${String(c).replace(/"/g, '""')}"`).join(";")).join("\n");
    const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = `audit_log_${new Date().toISOString().slice(0, 10)}.csv`;
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <div>
      <SectionH>Audit log</SectionH>

      <div className="filter-panel mb-16">
        <div className="filter-panel-header">
          <span className="filter-panel-icon">{Icon.filter}</span>
          <span>{t('filters_title')}</span>
        </div>
        <div className="filter-panel-body">
          <div className="filter-grid">
            <div className="field">
              <label>{t('date_from')}</label>
              <input type="date" value={filters.data_da} onChange={e => handleFilterChange("data_da", e.target.value)} />
            </div>
            <div className="field">
              <label>{t('date_to')}</label>
              <input type="date" value={filters.data_a} onChange={e => handleFilterChange("data_a", e.target.value)} />
            </div>
            <div className="field">
              <label>Utente</label>
              <input type="text" value={filters.username} onChange={e => handleFilterChange("username", e.target.value)} placeholder="Cerca utente..." />
            </div>
            <div className="field">
              <label>Azione</label>
              <input type="text" value={filters.action} onChange={e => handleFilterChange("action", e.target.value)} placeholder="Cerca azione..." />
            </div>
            <div className="field">
              <label>Livello</label>
              <select value={filters.level} onChange={e => handleFilterChange("level", e.target.value)}>
                <option value="">Tutti</option>
                <option value="ok">OK</option>
                <option value="info">INFO</option>
                <option value="warn">WARN</option>
              </select>
            </div>
          </div>
          <div className="filter-actions">
            <button className="btn btn-primary" onClick={loadLogs}>
              {Icon.search} {t('search')}
            </button>
            <button className="btn btn-export" onClick={exportExcel} disabled={logs.length === 0}>
              <span className="btn-export-icon">{Icon.download}</span>
              {t('export_excel')}
            </button>
          </div>
        </div>
      </div>

      <div style={{fontSize: 13, color: "var(--text-3)", marginBottom: 12}}>
        {total} eventi totali
      </div>

      <div className="panel">
        {loading ? (
          <div className="panel-body">Caricamento...</div>
        ) : logs.length === 0 ? (
          <div className="panel-body empty">
            <div style={{padding: "40px 20px", textAlign: "center", color: "var(--text-3)"}}>
              Nessun evento registrato con i criteri selezionati.
            </div>
          </div>
        ) : (
          <table className="data">
            <thead><tr><th style={{width: "14%"}}>{t('timestamp')}</th><th>{t('user')}</th><th>{t('action')}</th><th>{t('details')}</th><th>{t('level')}</th></tr></thead>
            <tbody>
              {logs.map((e, i) => (
                <tr key={i}>
                  <td className="mono muted" style={{fontSize: 12}}>{formatDate(e.timestamp)}</td>
                  <td className="mono">{e.username}</td>
                  <td><strong>{e.action}</strong></td>
                  <td className="muted">{e.target || e.details || "-"}</td>
                  <td><Badge type={e.level === "warn" ? "warn" : e.level === "ok" ? "ok" : "info"} dot>{(e.level || "info").toUpperCase()}</Badge></td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>
    </div>
  );
}

function AdminAllTenants({ config }) {
  const [tenants, setTenants] = useStateApp([]);
  const [loading, setLoading] = useStateApp(true);

  useEffectApp(() => {
    const token = localStorage.getItem("token");
    fetch(`${API_BASE}/tenants`, {
      headers: { Authorization: `Bearer ${token}` }
    })
      .then(r => r.json())
      .then(data => {
        if (data.success) setTenants(data.tenants);
        setLoading(false);
      });
  }, []);

  if (loading) return <div className="panel"><div className="panel-body">Caricamento...</div></div>;

  return (
    <div>
      <SectionH>Tutti gli utilizzatori <span className="sub">· {tenants.length} totali</span></SectionH>
      <div className="panel">
        {tenants.length === 0 ? (
          <div className="panel-body empty">
            <div style={{padding: "40px 20px", textAlign: "center", color: "var(--text-3)"}}>
              Nessun utilizzatore presente.
            </div>
          </div>
        ) : (
          <table className="data">
            <thead><tr>
              <th>{t('tenant')}</th>
              <th>{t('client')}</th>
              <th>{t('permissions')}</th>
              <th>{t('nav_users')}</th>
              <th>{t('created_by')}</th>
              <th>{t('status')}</th>
            </tr></thead>
            <tbody>
              {tenants.map(t => (
                <tr key={t.id}>
                  <td><strong>{t.name}</strong> <span className="mono muted" style={{fontSize: 11, marginLeft: 6}}>{t.code}</span></td>
                  <td><Badge type="info">{t.client_name}</Badge></td>
                  <td>
                    <div style={{display: "flex", gap: 4}}>
                      {t.enable_saldi && <Badge type="ok">Saldi</Badge>}
                      {t.enable_movimenti && <Badge type="ok">Mvt</Badge>}
                    </div>
                  </td>
                  <td>{t.user_count || 0}</td>
                  <td>{t.created_by_team ? <Badge type="info">Team</Badge> : <Badge type="neutral">Cliente</Badge>}</td>
                  <td>{t.active ? <Badge type="ok" dot>attivo</Badge> : <Badge type="warn" dot>disattivo</Badge>}</td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>
    </div>
  );
}

function AdminConfig({ config, onConfigUpdate }) {
  const [form, setForm] = useStateApp({
    client_name: config?.client_name || "Ronda",
    app_name: config?.app_name || "StockConnect",
    app_description: config?.app_description || "Gestione saldi & movimenti di magazzino",
    label_client_plural: config?.label_client_plural || "Logisti",
    label_client_singular: config?.label_client_singular || "Logista",
    label_tenant_plural: config?.label_tenant_plural || "Clienti",
    label_tenant_singular: config?.label_tenant_singular || "Cliente",
    tenant_auto_limit: config?.tenant_auto_limit || "3",
    // Visibilità colonne per logista
    vis_saldi_col_articolo: config?.vis_saldi_col_articolo !== false,
    vis_saldi_col_descrizione: config?.vis_saldi_col_descrizione !== false,
    vis_saldi_col_quantita: config?.vis_saldi_col_quantita !== false,
    vis_saldi_col_um: config?.vis_saldi_col_um !== false,
    vis_saldi_col_lotto: config?.vis_saldi_col_lotto !== false,
    vis_saldi_col_ubicazione: config?.vis_saldi_col_ubicazione !== false,
    vis_saldi_col_paletta: config?.vis_saldi_col_paletta !== false,
    vis_mov_col_articolo: config?.vis_mov_col_articolo !== false,
    vis_mov_col_data: config?.vis_mov_col_data !== false,
    vis_mov_col_segno: config?.vis_mov_col_segno !== false,
    vis_mov_col_causale: config?.vis_mov_col_causale !== false,
    vis_mov_col_descrizione: config?.vis_mov_col_descrizione !== false,
    vis_mov_col_quantita: config?.vis_mov_col_quantita !== false,
    vis_mov_col_lotto: config?.vis_mov_col_lotto !== false
  });
  const [saving, setSaving] = useStateApp(false);
  const [saved, setSaved] = useStateApp(false);
  const [error, setError] = useStateApp("");

  // Gestione utenti
  const [users, setUsers] = useStateApp([]);
  const [clients, setClients] = useStateApp([]);
  const [loadingUsers, setLoadingUsers] = useStateApp(true);
  const [newUserOpen, setNewUserOpen] = useStateApp(false);
  const [editingUser, setEditingUser] = useStateApp(null);

  const loadUsers = async () => {
    const token = localStorage.getItem("token");
    const [usersRes, clientsRes] = await Promise.all([
      fetch(`${API_BASE}/users`, { headers: { Authorization: `Bearer ${token}` } }).then(r => r.json()),
      fetch(`${API_BASE}/clients`, { headers: { Authorization: `Bearer ${token}` } }).then(r => r.json())
    ]);
    if (usersRes.success) setUsers(usersRes.users);
    if (clientsRes.success) setClients(clientsRes.clients);
    setLoadingUsers(false);
  };

  useEffectApp(() => {
    loadUsers();
  }, []);

  useEffectApp(() => {
    setForm({
      client_name: config?.client_name || "Ronda",
      app_name: config?.app_name || "StockConnect",
      app_description: config?.app_description || "Gestione saldi & movimenti di magazzino",
      label_client_plural: config?.label_client_plural || "Logisti",
      label_client_singular: config?.label_client_singular || "Logista",
      label_tenant_plural: config?.label_tenant_plural || "Clienti",
      label_tenant_singular: config?.label_tenant_singular || "Cliente",
      tenant_auto_limit: config?.tenant_auto_limit || "3",
      vis_saldi_col_articolo: config?.vis_saldi_col_articolo !== false,
      vis_saldi_col_descrizione: config?.vis_saldi_col_descrizione !== false,
      vis_saldi_col_quantita: config?.vis_saldi_col_quantita !== false,
      vis_saldi_col_um: config?.vis_saldi_col_um !== false,
      vis_saldi_col_lotto: config?.vis_saldi_col_lotto !== false,
      vis_saldi_col_ubicazione: config?.vis_saldi_col_ubicazione !== false,
      vis_saldi_col_paletta: config?.vis_saldi_col_paletta !== false,
      vis_mov_col_articolo: config?.vis_mov_col_articolo !== false,
      vis_mov_col_data: config?.vis_mov_col_data !== false,
      vis_mov_col_segno: config?.vis_mov_col_segno !== false,
      vis_mov_col_causale: config?.vis_mov_col_causale !== false,
      vis_mov_col_descrizione: config?.vis_mov_col_descrizione !== false,
      vis_mov_col_quantita: config?.vis_mov_col_quantita !== false,
      vis_mov_col_lotto: config?.vis_mov_col_lotto !== false
    });
  }, [config]);

  const handleChange = (key, value) => {
    setForm(prev => ({ ...prev, [key]: value }));
    setSaved(false);
  };

  const handleSave = async () => {
    setSaving(true);
    setError("");
    setSaved(false);

    const token = localStorage.getItem("token");

    try {
      for (const [key, value] of Object.entries(form)) {
        const res = await fetch(`${API_BASE}/config/${key}`, {
          method: "PUT",
          headers: {
            "Content-Type": "application/json",
            "Authorization": `Bearer ${token}`
          },
          body: JSON.stringify({ value })
        });
        const data = await res.json();
        if (!data.success) {
          throw new Error(data.error || `Errore salvataggio ${key}`);
        }
      }
      setSaved(true);
      if (onConfigUpdate) onConfigUpdate();
    } catch (err) {
      setError(err.message);
    }

    setSaving(false);
  };

  return (
    <div>
      <SectionH>Configurazione di sistema</SectionH>

      {error && (
        <div style={{marginBottom: 16, padding: "10px 12px", background: "rgba(220,53,69,0.1)", border: "1px solid rgba(220,53,69,0.3)", borderRadius: 4, color: "#dc3545", fontSize: 13}}>
          {error}
        </div>
      )}

      {saved && (
        <div style={{marginBottom: 16, padding: "10px 12px", background: "rgba(40,167,69,0.1)", border: "1px solid rgba(40,167,69,0.3)", borderRadius: 4, color: "#28a745", fontSize: 13}}>
          Configurazione salvata con successo. Ricarica la pagina per vedere le modifiche.
        </div>
      )}

      {/* Nome Cliente - in alto */}
      <div className="panel mb-16">
        <div className="panel-header"><h3>Cliente</h3></div>
        <div className="panel-body">
          <div className="setting-row">
            <div className="left">
              <div className="title">Nome cliente</div>
              <div className="desc">Nome del cliente visualizzato nell'interfaccia</div>
            </div>
            <input type="text" value={form.client_name} onChange={(e) => handleChange("client_name", e.target.value)} style={{width: 200, padding: "6px 10px", border: "1px solid var(--border-strong)", borderRadius: 3}}/>
          </div>
          <div className="setting-row" style={{marginTop: 16, paddingTop: 16, borderTop: "1px solid var(--border)"}}>
            <div className="left">
              <div className="title">Logo cliente</div>
              <div className="desc">Logo visualizzato al centro dell'header (max 2MB, jpg/png/svg)</div>
            </div>
            <div style={{display: "flex", alignItems: "center", gap: 12}}>
              {config?.client_logo && (
                <img src={config.client_logo} alt="Logo" style={{height: 36, maxWidth: 120, objectFit: "contain", background: "var(--bg-2)", padding: 4, borderRadius: 4}}/>
              )}
              <label className="btn btn-secondary" style={{cursor: "pointer"}}>
                {config?.client_logo ? "Cambia" : "Carica logo"}
                <input type="file" accept="image/*" style={{display: "none"}} onChange={async (e) => {
                  const file = e.target.files[0];
                  if (!file) return;
                  const formData = new FormData();
                  formData.append("logo", file);
                  const token = localStorage.getItem("token");
                  const res = await fetch(`${API_BASE}/config/logo`, {
                    method: "POST",
                    headers: { "Authorization": `Bearer ${token}` },
                    body: formData
                  }).then(r => r.json());
                  if (res.success) {
                    if (onConfigUpdate) onConfigUpdate();
                  } else {
                    setError(res.error || "Errore upload logo");
                  }
                  e.target.value = "";
                }}/>
              </label>
              {config?.client_logo && (
                <button className="btn btn-secondary" onClick={async () => {
                  const token = localStorage.getItem("token");
                  const res = await fetch(`${API_BASE}/config/logo`, {
                    method: "DELETE",
                    headers: { "Authorization": `Bearer ${token}` }
                  }).then(r => r.json());
                  if (res.success) {
                    if (onConfigUpdate) onConfigUpdate();
                  }
                }}>Rimuovi</button>
              )}
            </div>
          </div>
        </div>
      </div>

      {/* Utenti - subito dopo */}
      <div className="toolbar">
        <SectionH>{t('nav_users')}</SectionH>
        <div className="right">
          <button className="btn btn-primary" onClick={() => setNewUserOpen(true)}>
            <span className="icon">{Icon.plus}</span>Nuovo Utente
          </button>
        </div>
      </div>

      <div className="panel">
        {loadingUsers ? (
          <div className="panel-body">Caricamento...</div>
        ) : users.length === 0 ? (
          <div className="panel-body empty">
            <div style={{padding: "40px 20px", textAlign: "center", color: "var(--text-3)"}}>
              Nessun utente. Clicca "Nuovo Utente" per crearne uno.
            </div>
          </div>
        ) : (
          <table className="data">
            <thead>
              <tr>
                <th>{t('username')}</th>
                <th>2FA</th>
                <th>{t('status')}</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {users.filter(u => u.role === 'c').map(u => (
                <tr key={u.id}>
                  <td><strong>{u.username}</strong></td>
                  <td>{u.twofa_enabled ? <Badge type="ok">Attivo</Badge> : <Badge type="neutral">No</Badge>}</td>
                  <td>{u.active ? <Badge type="ok" dot>attivo</Badge> : <Badge type="warn" dot>disattivo</Badge>}</td>
                  <td>
                    <button className="btn btn-secondary btn-sm" onClick={() => setEditingUser(u)}>{t('edit')}</button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>

      {(newUserOpen || editingUser) && (
        <UserModal
          user={editingUser}
          clients={clients}
          onClose={() => { setNewUserOpen(false); setEditingUser(null); }}
          onSaved={() => { setNewUserOpen(false); setEditingUser(null); loadUsers(); }}
        />
      )}

      {/* Piattaforma */}
      <div className="panel mb-16" style={{marginTop: 24}}>
        <div className="panel-header"><h3>Piattaforma</h3></div>
        <div className="panel-body">
          <div className="setting-row">
            <div className="left">
              <div className="title">Nome applicazione</div>
              <div className="desc">Titolo visualizzato nell'interfaccia</div>
            </div>
            <input type="text" value={form.app_name} onChange={(e) => handleChange("app_name", e.target.value)} style={{width: 200, padding: "6px 10px", border: "1px solid var(--border-strong)", borderRadius: 3}}/>
          </div>
          <div className="setting-row">
            <div className="left">
              <div className="title">Descrizione applicazione</div>
              <div className="desc">Descrizione mostrata nella pagina di login</div>
            </div>
            <input type="text" value={form.app_description} onChange={(e) => handleChange("app_description", e.target.value)} style={{width: 300, padding: "6px 10px", border: "1px solid var(--border-strong)", borderRadius: 3}}/>
          </div>
          <div className="setting-row">
            <div className="left">
              <div className="title">Versione attuale</div>
              <div className="desc">Rilasciata il 2026-06-26</div>
            </div>
            <Badge type="ok" dot>v 1.0.3</Badge>
          </div>
        </div>
      </div>

      {/* Default per nuovi Clienti */}
      <div className="panel mb-16">
        <div className="panel-header"><h3>Default per nuovi Clienti</h3></div>
        <div className="panel-body">
          <div className="setting-row">
            <div className="left">
              <div className="title">Limite utilizzatori autonomi</div>
              <div className="desc">Numero di utilizzatori che un nuovo Cliente puo' creare senza intervento Team</div>
            </div>
            <input type="number" value={form.tenant_auto_limit} onChange={(e) => handleChange("tenant_auto_limit", e.target.value)} style={{width: 80, padding: "6px 10px", border: "1px solid #d4a017", borderRadius: 3, textAlign: "center", background: "#fffde7"}}/>
          </div>
        </div>
      </div>

      {/* Visibilità colonne per Logista */}
      <div className="panel mb-16">
        <div className="panel-header"><h3>Visibilità colonne per Logista</h3></div>
        <div className="panel-body">
          <p style={{fontSize: 13, color: "var(--text-3)", marginBottom: 16}}>
            Definisci quali colonne il Logista può vedere e configurare per i propri clienti.
          </p>

          <div style={{marginBottom: 20}}>
            <div style={{fontWeight: 600, marginBottom: 10, fontSize: 13}}>Colonne Saldi</div>
            <div style={{display: "flex", flexWrap: "wrap", gap: 16}}>
              <Checkbox checked={form.vis_saldi_col_articolo} onChange={(v) => handleChange("vis_saldi_col_articolo", v)} label="Articolo"/>
              <Checkbox checked={form.vis_saldi_col_descrizione} onChange={(v) => handleChange("vis_saldi_col_descrizione", v)} label="Descrizione"/>
              <Checkbox checked={form.vis_saldi_col_quantita} onChange={(v) => handleChange("vis_saldi_col_quantita", v)} label="Quantità"/>
              <Checkbox checked={form.vis_saldi_col_um} onChange={(v) => handleChange("vis_saldi_col_um", v)} label="Unità misura"/>
              <Checkbox checked={form.vis_saldi_col_lotto} onChange={(v) => handleChange("vis_saldi_col_lotto", v)} label="Lotto"/>
              <Checkbox checked={form.vis_saldi_col_ubicazione} onChange={(v) => handleChange("vis_saldi_col_ubicazione", v)} label="Ubicazione"/>
              <Checkbox checked={form.vis_saldi_col_paletta} onChange={(v) => handleChange("vis_saldi_col_paletta", v)} label="Paletta"/>
            </div>
          </div>

          <div>
            <div style={{fontWeight: 600, marginBottom: 10, fontSize: 13}}>Colonne Movimenti</div>
            <div style={{display: "flex", flexWrap: "wrap", gap: 16}}>
              <Checkbox checked={form.vis_mov_col_articolo} onChange={(v) => handleChange("vis_mov_col_articolo", v)} label="Articolo"/>
              <Checkbox checked={form.vis_mov_col_data} onChange={(v) => handleChange("vis_mov_col_data", v)} label="Data"/>
              <Checkbox checked={form.vis_mov_col_segno} onChange={(v) => handleChange("vis_mov_col_segno", v)} label="Segno (+/-)"/>
              <Checkbox checked={form.vis_mov_col_causale} onChange={(v) => handleChange("vis_mov_col_causale", v)} label="Causale"/>
              <Checkbox checked={form.vis_mov_col_descrizione} onChange={(v) => handleChange("vis_mov_col_descrizione", v)} label="Descrizione"/>
              <Checkbox checked={form.vis_mov_col_quantita} onChange={(v) => handleChange("vis_mov_col_quantita", v)} label="Quantità"/>
              <Checkbox checked={form.vis_mov_col_lotto} onChange={(v) => handleChange("vis_mov_col_lotto", v)} label="Lotto"/>
            </div>
          </div>
        </div>
      </div>

      {/* Bottone salva */}
      <div style={{display: "flex", justifyContent: "flex-end", gap: 8}}>
        <button className="btn btn-primary" onClick={handleSave} disabled={saving}>
          {saving ? t('saving') : t('save_config')}
        </button>
      </div>
    </div>
  );
}

// Modal Nuovo/Modifica Utente
function UserModal({ user, clients, onClose, onSaved }) {
  const isEdit = !!user;
  const [form, setForm] = useStateApp({
    username: user?.username || "",
    password: "",
    client_id: user?.client_id || (clients[0]?.id || ""),
    twofa_enabled: user?.twofa_enabled || false,
    active: user?.active !== false
  });
  const [saving, setSaving] = useStateApp(false);
  const [error, setError] = useStateApp("");

  const handleChange = (field, value) => {
    setForm(prev => ({ ...prev, [field]: value }));
  };

  const handleSubmit = async () => {
    if (!form.username || (!isEdit && !form.password)) {
      setError(t('username_password_required'));
      return;
    }

    setSaving(true);
    setError("");

    const token = localStorage.getItem("token");
    const url = isEdit ? `${API_BASE}/users/${user.id}` : `${API_BASE}/users`;
    const method = isEdit ? "PUT" : "POST";

    const body = { ...form };
    if (isEdit && !form.password) delete body.password;

    try {
      const res = await fetch(url, {
        method,
        headers: {
          "Content-Type": "application/json",
          "Authorization": `Bearer ${token}`
        },
        body: JSON.stringify(body)
      });
      const data = await res.json();

      if (data.success) {
        onSaved();
      } else {
        setError(data.error || "Errore salvataggio");
      }
    } catch (err) {
      setError("Errore di connessione");
    }

    setSaving(false);
  };

  return (
    <Modal title={isEdit ? "Modifica Utente" : "Nuovo Utente"} size="md" onClose={onClose} footer={<>
      <button className="btn btn-secondary" onClick={onClose} disabled={saving}>{t('cancel')}</button>
      <button className="btn btn-primary" onClick={handleSubmit} disabled={saving}>
        {saving ? t('saving') : (isEdit ? t('save') : t('create_user'))}
      </button>
    </>}>
      {error && (
        <div style={{marginBottom: 16, padding: "10px 12px", background: "rgba(220,53,69,0.1)", border: "1px solid rgba(220,53,69,0.3)", borderRadius: 4, color: "#dc3545", fontSize: 13}}>
          {error}
        </div>
      )}

      <div className="field" style={{marginBottom: 14}}>
        <label>Username *</label>
        <input type="text" value={form.username} onChange={(e) => handleChange("username", e.target.value)} disabled={isEdit}/>
      </div>

      {isEdit && user?.client_name && (
        <div className="field" style={{marginBottom: 14}}>
          <label>{t('client')}</label>
          <input type="text" value={user.client_name} disabled/>
        </div>
      )}

      <div className="field" style={{marginBottom: 14}}>
        <label>Password {isEdit ? "(lascia vuoto per non modificare)" : "*"}</label>
        <input type="password" value={form.password} onChange={(e) => handleChange("password", e.target.value)} placeholder={isEdit ? "••••••" : ""}/>
      </div>

      <div style={{display: "grid", gap: 10, marginTop: 16}}>
        <Checkbox checked={form.twofa_enabled} onChange={(v) => handleChange("twofa_enabled", v)} label="2FA Attivo"/>
        {isEdit && <Checkbox checked={form.active} onChange={(v) => handleChange("active", v)} label="Utente attivo"/>}
      </div>
    </Modal>
  );
}

// Vista Cliente - Gestione Clienti (del logista)
function ClientClienti({ user, config, onOpenUsers }) {
  const [clients, setClients] = useStateApp([]);
  const [limitInfo, setLimitInfo] = useStateApp({ limit: 3, created: 0, canCreate: true });
  const [stats, setStats] = useStateApp({ clienti: 0, utenti: 0, articoli: 0, movimenti_mese: 0 });
  const [loading, setLoading] = useStateApp(true);
  const [newOpen, setNewOpen] = useStateApp(false);
  const [editingClient, setEditingClient] = useStateApp(null);

  const loadData = async () => {
    setLoading(true);
    const token = localStorage.getItem("token");

    // Carica i clienti creati dall'utente
    const clientsRes = await fetch(`${API_BASE}/clients`, {
      headers: { Authorization: `Bearer ${token}` }
    }).then(r => r.json());

    if (clientsRes.success) {
      setClients(clientsRes.clients);
    }

    // Carica info limite
    const limitRes = await fetch(`${API_BASE}/clients/limit`, {
      headers: { Authorization: `Bearer ${token}` }
    }).then(r => r.json());

    if (limitRes.success) {
      setLimitInfo(limitRes);
    }

    // Carica statistiche
    const statsRes = await fetch(`${API_BASE}/clients/stats`, {
      headers: { Authorization: `Bearer ${token}` }
    }).then(r => r.json());

    if (statsRes.success) {
      setStats(statsRes.stats);
    }

    setLoading(false);
  };

  useEffectApp(() => {
    loadData();
  }, []);

  const handleCreated = () => {
    setNewOpen(false);
    loadData();
  };

  if (loading) {
    return <div className="panel"><div className="panel-body">Caricamento...</div></div>;
  }

  return (
    <div>
      <div className="stats-grid">
        <div className="stat-card accent-blue">
          <div className="stat-icon">{Icon.users}</div>
          <div className="stat-content">
            <div className="label">{t('nav_clients')}</div>
            <div className="value">{stats.clienti}</div>
            <div className="delta">{limitInfo.created} / {limitInfo.limit} {t('available')}</div>
          </div>
        </div>
        <div className="stat-card accent-green">
          <div className="stat-icon">{Icon.user}</div>
          <div className="stat-content">
            <div className="label">{t('nav_users')}</div>
            <div className="value">{stats.utenti}</div>
            <div className="delta">{t('active_users')}</div>
          </div>
        </div>
        <div className="stat-card accent-purple">
          <div className="stat-icon">{Icon.box}</div>
          <div className="stat-content">
            <div className="label">{t('card_articles')}</div>
            <div className="value">{stats.articoli.toLocaleString('it-CH')}</div>
            <div className="delta">{t('in_stock')}</div>
          </div>
        </div>
        <div className="stat-card accent-orange">
          <div className="stat-icon">{Icon.activity}</div>
          <div className="stat-content">
            <div className="label">{t('nav_movimenti')}</div>
            <div className="value">{stats.movimenti_mese.toLocaleString('it-CH')}</div>
            <div className="delta">{t('this_month')}</div>
          </div>
        </div>
      </div>

      <div className="toolbar">
        <SectionH>{t('your_clients')}</SectionH>
        <div className="right">
          {limitInfo.canCreate ? (
            <button className="btn btn-primary" onClick={() => setNewOpen(true)}>
              <span className="icon">{Icon.plus}</span>{t('new_client')}
            </button>
          ) : (
            <span style={{fontSize: 13, color: "var(--text-3)"}}>
              Limite raggiunto. Contatta Team per aggiungerne altri.
            </span>
          )}
        </div>
      </div>

      <div className="panel">
        {clients.length === 0 ? (
          <div className="panel-body empty">
            <div style={{padding: "40px 20px", textAlign: "center", color: "var(--text-3)"}}>
              Nessun cliente. Clicca "Nuovo Cliente" per crearne uno.
            </div>
          </div>
        ) : (
          <table className="data">
            <thead>
              <tr>
                <th>{t('code')}</th>
                <th>{t('client_name')}</th>
                <th>{t('gestionale_code')}</th>
                <th>{t('permissions')}</th>
                <th>{t('status')}</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {clients.map(c => (
                <tr key={c.id}>
                  <td className="mono">{c.code}</td>
                  <td><strong>{c.name}</strong></td>
                  <td className="mono">{c.gestionale_code || "-"}</td>
                  <td>
                    <div style={{display: "flex", gap: 4, flexWrap: "wrap"}}>
                      {c.enable_saldi && <Badge type="ok">Saldi</Badge>}
                      {c.enable_movimenti && <Badge type="ok">Movimenti</Badge>}
                    </div>
                  </td>
                  <td>{c.active ? <Badge type="ok" dot>attivo</Badge> : <Badge type="warn" dot>disattivo</Badge>}</td>
                  <td style={{display: "flex", gap: 6}}>
                    <button className="btn btn-secondary btn-sm" onClick={() => setEditingClient(c)}>{t('edit')}</button>
                    <button className="btn btn-primary btn-sm" onClick={() => onOpenUsers(c)}>{t('nav_users')}</button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>

      {newOpen && (
        <ClientNewClientModal
          config={config}
          onClose={() => setNewOpen(false)}
          onCreated={handleCreated}
        />
      )}

      {editingClient && (
        <ClientEditClientModal
          client={editingClient}
          config={config}
          onClose={() => setEditingClient(null)}
          onSaved={() => { setEditingClient(null); loadData(); }}
        />
      )}
    </div>
  );
}

// Vista Saldi (pagina intera per logista)
function ClientSaldiView({ user, config }) {
  const [clients, setClients] = useStateApp([]);
  const [selectedClient, setSelectedClient] = useStateApp("all"); // "all" o client object
  const [saldi, setSaldi] = useStateApp([]);
  const [loading, setLoading] = useStateApp(true);
  const [loadingData, setLoadingData] = useStateApp(false);
  const [filters, setFilters] = useStateApp({ articolo: "", lotto: "" });
  const [total, setTotal] = useStateApp(0);
  const [totalArticoli, setTotalArticoli] = useStateApp(0);
  const [totaliPerUM, setTotaliPerUM] = useStateApp({});
  const [topArticoli, setTopArticoli] = useStateApp([]);
  const [excludeZero, setExcludeZero] = useStateApp(true);
  const [colConfig, setColConfig] = useStateApp(null);
  const [page, setPage] = useStateApp(1);
  const pageSize = 100;

  // Carica lista clienti con permesso saldi
  useEffectApp(() => {
    const loadClients = async () => {
      const token = localStorage.getItem("token");
      const res = await fetch(`${API_BASE}/clients`, {
        headers: { Authorization: `Bearer ${token}` }
      }).then(r => r.json());

      if (res.success) {
        const saldiClients = res.clients.filter(c => c.gestionale_code);
        setClients(saldiClients);
      }
      setLoading(false);
    };
    loadClients();
  }, []);

  // Carica saldi quando cambia cliente o filtro exclude_zero
  useEffectApp(() => {
    setPage(1); // Reset pagina quando cambia cliente o filtro
    loadSaldi(1);
  }, [selectedClient, excludeZero]);

  // Carica quando cambia pagina
  useEffectApp(() => {
    if (page > 1) loadSaldi(page);
  }, [page]);

  const loadSaldi = async (currentPage = 1) => {
    setLoadingData(true);
    const token = localStorage.getItem("token");
    const isAll = selectedClient === "all";

    const params = new URLSearchParams({
      limit: pageSize,
      offset: (currentPage - 1) * pageSize,
      exclude_zero: excludeZero ? '1' : '0'
    });

    if (isAll) {
      params.append("all", "1");
    } else if (selectedClient?.gestionale_code) {
      params.append("gestionale_code", selectedClient.gestionale_code);
      const showPaletta = selectedClient.saldi_col_paletta !== false;
      params.append("aggregate", showPaletta ? '0' : '1');
    }

    if (filters.articolo) params.append("articolo", filters.articolo);
    if (filters.lotto) params.append("lotto", filters.lotto);

    const res = await fetch(`${API_BASE}/saldi?${params}`, {
      headers: { Authorization: `Bearer ${token}` }
    }).then(r => r.json());

    if (res.success) {
      setSaldi(res.saldi);
      setTotal(res.total);
      setTotalArticoli(res.totalArticoli || 0);
      setTotaliPerUM(res.totaliPerUM || {});
      setTopArticoli(res.topArticoli || []);
      setColConfig(isAll ? null : (res.config || selectedClient));
    }
    setLoadingData(false);
  };

  const handleSearch = () => {
    setPage(1);
    loadSaldi(1);
  };

  const handleFilterChange = (field, value) => {
    setFilters(prev => ({ ...prev, [field]: value }));
  };

  const resetFilters = () => {
    setFilters({ articolo: "", lotto: "" });
  };

  const exportExcel = async () => {
    if (total === 0) return;
    const isAllExp = selectedClient === "all";
    const token = localStorage.getItem("token");

    // Scarica TUTTI i dati per l'export (senza limit)
    const params = new URLSearchParams({
      limit: 100000,
      exclude_zero: excludeZero ? '1' : '0'
    });
    if (isAllExp) {
      params.append("all", "1");
    } else if (selectedClient?.gestionale_code) {
      params.append("gestionale_code", selectedClient.gestionale_code);
      const showPaletta = selectedClient.saldi_col_paletta !== false;
      params.append("aggregate", showPaletta ? '0' : '1');
    }
    if (filters.articolo) params.append("articolo", filters.articolo);
    if (filters.lotto) params.append("lotto", filters.lotto);

    const res = await fetch(`${API_BASE}/saldi?${params}`, {
      headers: { Authorization: `Bearer ${token}` }
    }).then(r => r.json());

    if (!res.success || !res.saldi.length) return;
    const allSaldi = res.saldi;

    const clientExpCols = colConfig || { saldi_col_articolo: true, saldi_col_descrizione: true, saldi_col_quantita: true, saldi_col_um: true, saldi_col_lotto: true, saldi_col_ubicazione: true, saldi_col_paletta: true };
    const expCols = {
      saldi_col_articolo: config?.vis_saldi_col_articolo !== false && clientExpCols.saldi_col_articolo !== false,
      saldi_col_descrizione: config?.vis_saldi_col_descrizione !== false && clientExpCols.saldi_col_descrizione !== false,
      saldi_col_quantita: config?.vis_saldi_col_quantita !== false && clientExpCols.saldi_col_quantita !== false,
      saldi_col_um: config?.vis_saldi_col_um !== false && clientExpCols.saldi_col_um !== false,
      saldi_col_lotto: config?.vis_saldi_col_lotto !== false && clientExpCols.saldi_col_lotto !== false,
      saldi_col_ubicazione: config?.vis_saldi_col_ubicazione !== false && clientExpCols.saldi_col_ubicazione !== false,
      saldi_col_paletta: config?.vis_saldi_col_paletta !== false && clientExpCols.saldi_col_paletta !== false
    };
    const headers = isAllExp ? ['Cliente'] : [];
    if (expCols.saldi_col_articolo) headers.push('Articolo');
    if (expCols.saldi_col_descrizione) headers.push('Descrizione');
    if (expCols.saldi_col_quantita) headers.push('Quantità');
    if (expCols.saldi_col_um) headers.push('UM');
    if (expCols.saldi_col_lotto) headers.push('Lotto');
    if (expCols.saldi_col_ubicazione) headers.push('Ubicazione');
    if (expCols.saldi_col_paletta) headers.push('Paletta');

    const rows = allSaldi.map(s => {
      const row = isAllExp ? [clients.find(c => c.gestionale_code === s.gestionale_code)?.name || s.gestionale_code] : [];
      if (expCols.saldi_col_articolo) row.push(s.articolo);
      if (expCols.saldi_col_descrizione) row.push(s.descrizione || '');
      if (expCols.saldi_col_quantita) row.push(parseFloat(s.quantita));
      if (expCols.saldi_col_um) row.push(s.um || '');
      if (expCols.saldi_col_lotto) row.push(s.lotto || '');
      if (expCols.saldi_col_ubicazione) row.push([s.ubi1, s.ubi2, s.ubi3, s.ubi4].filter(Boolean).join('-') || '');
      if (expCols.saldi_col_paletta) row.push(s.paletta || '');
      return row;
    });

    const csv = [headers.join(';'), ...rows.map(r => r.map(c => typeof c === 'string' ? `"${c}"` : c).join(';'))].join('\n');
    const blob = new Blob(['﻿' + csv], { type: 'text/csv;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `saldi_${isAllExp ? 'tutti' : selectedClient.code}_${new Date().toISOString().slice(0,10)}.csv`;
    a.click();
    URL.revokeObjectURL(url);
  };

  if (loading) {
    return <div className="panel"><div className="panel-body">Caricamento...</div></div>;
  }

  const isAll = selectedClient === "all";
  const clientCols = colConfig || { saldi_col_articolo: true, saldi_col_descrizione: true, saldi_col_quantita: true, saldi_col_um: true, saldi_col_lotto: true, saldi_col_ubicazione: true, saldi_col_paletta: true };
  // Combina config admin (vis_*) con config cliente - colonna visibile solo se entrambe true
  const cols = {
    saldi_col_articolo: config?.vis_saldi_col_articolo !== false && clientCols.saldi_col_articolo !== false,
    saldi_col_descrizione: config?.vis_saldi_col_descrizione !== false && clientCols.saldi_col_descrizione !== false,
    saldi_col_quantita: config?.vis_saldi_col_quantita !== false && clientCols.saldi_col_quantita !== false,
    saldi_col_um: config?.vis_saldi_col_um !== false && clientCols.saldi_col_um !== false,
    saldi_col_lotto: config?.vis_saldi_col_lotto !== false && clientCols.saldi_col_lotto !== false,
    saldi_col_ubicazione: config?.vis_saldi_col_ubicazione !== false && clientCols.saldi_col_ubicazione !== false,
    saldi_col_paletta: config?.vis_saldi_col_paletta !== false && clientCols.saldi_col_paletta !== false
  };

  return (
    <div>
      <SectionH>{t('saldi_title')}</SectionH>

      <div className="filter-panel mb-16">
        <div className="filter-panel-header">
          <span className="filter-panel-icon">{Icon.filter}</span>
          <span>{t('filters_title')}</span>
        </div>
        <div className="filter-panel-body">
          <div className="filter-grid">
            <div className="field">
              <label>{t('client')}</label>
              <select
                value={isAll ? "all" : (selectedClient?.id || "")}
                onChange={(e) => {
                  if (e.target.value === "all") {
                    setSelectedClient("all");
                  } else {
                    const c = clients.find(c => c.id === parseInt(e.target.value));
                    setSelectedClient(c);
                  }
                }}
              >
                <option value="all">— {t('all_clients')} —</option>
                {clients.map(c => (
                  <option key={c.id} value={c.id}>{c.name} ({c.code})</option>
                ))}
              </select>
            </div>

            {cols.saldi_col_articolo && (
              <div className="field">
                <label>{t('article')}</label>
                <input
                  type="text"
                  placeholder={t('search_article')}
                  value={filters.articolo}
                  onChange={(e) => handleFilterChange("articolo", e.target.value)}
                  onKeyDown={(e) => e.key === "Enter" && handleSearch()}
                />
              </div>
            )}

            {cols.saldi_col_lotto && (
              <div className="field">
                <label>{t('lotto')}</label>
                <input
                  type="text"
                  placeholder={t('search_lotto')}
                  value={filters.lotto}
                  onChange={(e) => handleFilterChange("lotto", e.target.value)}
                  onKeyDown={(e) => e.key === "Enter" && handleSearch()}
                />
              </div>
            )}

            <div className="field">
              <label>&nbsp;</label>
              <Checkbox checked={excludeZero} onChange={setExcludeZero} label={t('hide_zero_saldi')}/>
            </div>

            <div className="field filter-actions-inline">
              <label>&nbsp;</label>
              <div style={{display: "flex", gap: 8}}>
                <button className="btn btn-ghost" onClick={resetFilters}>
                  {Icon.refresh} {t('reset')}
                </button>
                <button className="btn btn-primary" onClick={handleSearch}>
                  {Icon.search} {t('search')}
                </button>
                <button className="btn btn-export" onClick={exportExcel} disabled={total === 0}>
                  <span className="btn-export-icon">{Icon.download}</span>
                  {t('export_excel')}
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>

      {/* Card riassuntive - usa dati aggregati dal backend */}
      {!loadingData && totalArticoli > 0 && (
        <div className="stats-cards mb-16">
          <div className="stat-card">
            <div className="stat-card-icon" style={{background: "var(--info-soft)", color: "var(--ti-blue)"}}>
              {Icon.box}
            </div>
            <div className="stat-card-content">
              <div className="stat-card-label">{t('card_articles')}</div>
              <div className="stat-card-value">{totalArticoli.toLocaleString('it-CH')}</div>
              <div className="stat-card-sub">{t('card_distinct_articles')}</div>
            </div>
          </div>

          <div className="stat-card">
            <div className="stat-card-icon" style={{background: "var(--info-soft)", color: "var(--ti-blue)"}}>
              {Icon.box}
            </div>
            <div className="stat-card-content">
              <div className="stat-card-label">{t('card_total_um')}</div>
              <div className="stat-card-list">
                {Object.entries(totaliPerUM).map(([um, tot]) => (
                  <div key={um} className="stat-card-list-item">
                    <span className="stat-card-list-label">{um}</span>
                    <span className="stat-card-list-value">{Math.round(tot).toLocaleString('it-CH')}</span>
                  </div>
                ))}
              </div>
            </div>
            <div className="stat-card-bar"></div>
          </div>

          <div className="stat-card">
            <div className="stat-card-icon" style={{background: "var(--ok-soft)", color: "var(--ok)"}}>
              {Icon.trend}
            </div>
            <div className="stat-card-content">
              <div className="stat-card-label">{t('card_top_articles')}</div>
              <div className="stat-card-list">
                {topArticoli.map((art, i) => (
                  <div key={i} className="stat-card-list-item">
                    <span className="stat-card-list-label mono" style={{fontSize: 11}}>{art.articolo}</span>
                    <span className="stat-card-list-value">{Math.round(art.quantita).toLocaleString('it-CH')} <small>{art.um}</small></span>
                  </div>
                ))}
              </div>
            </div>
          </div>
        </div>
      )}

      <div style={{fontSize: 13, color: "var(--text-3)", marginBottom: 12}}>
        {total} {t('rows')} {excludeZero ? `(${t('exclude_zero')})` : ""} {filters.articolo && `· ${t('article').toLowerCase()} "${filters.articolo}"`} {filters.lotto && `· ${t('lotto').toLowerCase()} "${filters.lotto}"`}
      </div>

      <div className="panel">
        {loadingData ? (
          <div className="panel-body"><div style={{padding: 20, textAlign: "center"}}>{t('loading_saldi')}</div></div>
        ) : saldi.length === 0 ? (
          <div className="panel-body empty">
            <div style={{padding: "40px 20px", textAlign: "center", color: "var(--text-3)"}}>
              {t('no_saldi')}
            </div>
          </div>
        ) : (
          <table className="data">
            <thead>
              <tr>
                {isAll && <th>{t('client')}</th>}
                {cols.saldi_col_articolo !== false && <th>{t('article')}</th>}
                {cols.saldi_col_descrizione !== false && <th>{t('description')}</th>}
                {cols.saldi_col_quantita !== false && <th style={{textAlign: "right"}}>{t('quantity')}</th>}
                {cols.saldi_col_um !== false && <th>{t('um')}</th>}
                {cols.saldi_col_lotto !== false && <th>{t('lotto')}</th>}
                {cols.saldi_col_ubicazione !== false && <th>{t('location')}</th>}
                {cols.saldi_col_paletta !== false && <th>{t('pallet')}</th>}
              </tr>
            </thead>
            <tbody>
              {saldi.map((s, i) => (
                <tr key={i}>
                  {isAll && <td>{clients.find(c => c.gestionale_code === s.gestionale_code)?.name || s.gestionale_code}</td>}
                  {cols.saldi_col_articolo !== false && <td className="mono"><strong>{s.articolo}</strong></td>}
                  {cols.saldi_col_descrizione !== false && <td>{s.descrizione || "-"}</td>}
                  {cols.saldi_col_quantita !== false && <td style={{textAlign: "right"}}>{parseFloat(s.quantita).toLocaleString('it-CH')}</td>}
                  {cols.saldi_col_um !== false && <td>{s.um || "-"}</td>}
                  {cols.saldi_col_lotto !== false && <td>{s.lotto || "-"}</td>}
                  {cols.saldi_col_ubicazione !== false && <td className="mono" style={{fontSize: 11}}>{[s.ubi1, s.ubi2, s.ubi3, s.ubi4].filter(Boolean).join("-") || "-"}</td>}
                  {cols.saldi_col_paletta !== false && <td>{s.paletta || "-"}</td>}
                </tr>
              ))}
            </tbody>
          </table>
        )}
        {/* Paginazione */}
        {total > pageSize && (
          <div className="pagination">
            <button
              className="btn btn-sm btn-secondary"
              disabled={page === 1}
              onClick={() => setPage(1)}
            >
              ««
            </button>
            <button
              className="btn btn-sm btn-secondary"
              disabled={page === 1}
              onClick={() => setPage(p => p - 1)}
            >
              «
            </button>
            <span className="pagination-info">
              Pagina {page} di {Math.ceil(total / pageSize)} · Righe {((page - 1) * pageSize) + 1}-{Math.min(page * pageSize, total)} di {total}
            </span>
            <button
              className="btn btn-sm btn-secondary"
              disabled={page >= Math.ceil(total / pageSize)}
              onClick={() => setPage(p => p + 1)}
            >
              »
            </button>
            <button
              className="btn btn-sm btn-secondary"
              disabled={page >= Math.ceil(total / pageSize)}
              onClick={() => setPage(Math.ceil(total / pageSize))}
            >
              »»
            </button>
          </div>
        )}
      </div>
    </div>
  );
}

// Vista Movimenti (pagina intera per logista)
function ClientMovimentiView({ user, config }) {
  const [clients, setClients] = useStateApp([]);
  const [selectedClient, setSelectedClient] = useStateApp("all");
  const [movimenti, setMovimenti] = useStateApp([]);
  const [loading, setLoading] = useStateApp(true);
  const [loadingData, setLoadingData] = useStateApp(false);
  const [filters, setFilters] = useStateApp({
    articolo: "",
    dataDa: getMonthStartDate(),
    dataA: getMonthEndDate(),
    segno: "",
    causale: "",
    lotto: ""
  });
  const [total, setTotal] = useStateApp(0);
  const [totaleEntrate, setTotaleEntrate] = useStateApp(0);
  const [totaleUscite, setTotaleUscite] = useStateApp(0);
  const [colConfig, setColConfig] = useStateApp(null);
  const [page, setPage] = useStateApp(1);
  const pageSize = 100;

  // Carica lista clienti con permesso movimenti
  useEffectApp(() => {
    const loadClients = async () => {
      const token = localStorage.getItem("token");
      const res = await fetch(`${API_BASE}/clients`, {
        headers: { Authorization: `Bearer ${token}` }
      }).then(r => r.json());

      if (res.success) {
        const movClients = res.clients.filter(c => c.gestionale_code);
        setClients(movClients);
      }
      setLoading(false);
    };
    loadClients();
  }, []);

  // Carica movimenti quando cambia cliente
  useEffectApp(() => {
    setPage(1);
    loadMovimenti(1);
  }, [selectedClient]);

  // Carica quando cambia pagina
  useEffectApp(() => {
    if (page > 1) loadMovimenti(page);
  }, [page]);

  const loadMovimenti = async (currentPage = 1) => {
    setLoadingData(true);
    const token = localStorage.getItem("token");
    const isAll = selectedClient === "all";

    const params = new URLSearchParams({
      limit: pageSize,
      offset: (currentPage - 1) * pageSize
    });

    if (isAll) {
      params.append("all", "1");
    } else if (selectedClient?.gestionale_code) {
      params.append("gestionale_code", selectedClient.gestionale_code);
    }

    if (filters.articolo) params.append("articolo", filters.articolo);
    if (filters.dataDa) params.append("data_da", filters.dataDa);
    if (filters.dataA) params.append("data_a", filters.dataA);
    if (filters.segno) params.append("segno", filters.segno);
    if (filters.causale) params.append("causale", filters.causale);
    if (filters.lotto) params.append("lotto", filters.lotto);

    const res = await fetch(`${API_BASE}/movimenti?${params}`, {
      headers: { Authorization: `Bearer ${token}` }
    }).then(r => r.json());

    if (res.success) {
      setMovimenti(res.movimenti);
      setTotal(res.total);
      setTotaleEntrate(res.totaleEntrate || 0);
      setTotaleUscite(res.totaleUscite || 0);
      if (res.config) setColConfig(res.config);
    }
    setLoadingData(false);
  };

  const handleSearch = () => {
    setPage(1);
    loadMovimenti(1);
  };

  const handleFilterChange = (field, value) => {
    setFilters(prev => ({ ...prev, [field]: value }));
  };

  const resetFilters = () => {
    setFilters({ articolo: "", dataDa: getMonthStartDate(), dataA: getMonthEndDate(), segno: "", causale: "", lotto: "" });
  };

  const formatDate = (d) => {
    if (!d) return "-";
    return new Date(d).toLocaleDateString('it-CH');
  };

  const exportExcel = async () => {
    if (total === 0) return;
    const isAllExp = selectedClient === "all";
    const token = localStorage.getItem("token");

    // Scarica TUTTI i dati per l'export (senza limit)
    const params = new URLSearchParams({ limit: 100000 });
    if (isAllExp) {
      params.append("all", "1");
    } else if (selectedClient?.gestionale_code) {
      params.append("gestionale_code", selectedClient.gestionale_code);
    }
    if (filters.articolo) params.append("articolo", filters.articolo);
    if (filters.dataDa) params.append("data_da", filters.dataDa);
    if (filters.dataA) params.append("data_a", filters.dataA);
    if (filters.segno) params.append("segno", filters.segno);
    if (filters.causale) params.append("causale", filters.causale);
    if (filters.lotto) params.append("lotto", filters.lotto);

    const res = await fetch(`${API_BASE}/movimenti?${params}`, {
      headers: { Authorization: `Bearer ${token}` }
    }).then(r => r.json());

    if (!res.success || !res.movimenti.length) return;
    const allMovimenti = res.movimenti;

    const clientExpCols = colConfig || { mov_col_articolo: true, mov_col_data: true, mov_col_segno: true, mov_col_causale: true, mov_col_descrizione: true, mov_col_quantita: true, mov_col_lotto: true };
    const expCols = {
      mov_col_articolo: config?.vis_mov_col_articolo !== false && clientExpCols.mov_col_articolo !== false,
      mov_col_data: config?.vis_mov_col_data !== false && clientExpCols.mov_col_data !== false,
      mov_col_segno: config?.vis_mov_col_segno !== false && clientExpCols.mov_col_segno !== false,
      mov_col_causale: config?.vis_mov_col_causale !== false && clientExpCols.mov_col_causale !== false,
      mov_col_descrizione: config?.vis_mov_col_descrizione !== false && clientExpCols.mov_col_descrizione !== false,
      mov_col_quantita: config?.vis_mov_col_quantita !== false && clientExpCols.mov_col_quantita !== false,
      mov_col_lotto: config?.vis_mov_col_lotto !== false && clientExpCols.mov_col_lotto !== false
    };

    const headers = isAllExp ? ['Cliente'] : [];
    if (expCols.mov_col_data) headers.push('Data');
    if (expCols.mov_col_segno) headers.push('Segno');
    if (expCols.mov_col_causale) headers.push('Causale');
    if (expCols.mov_col_articolo) headers.push('Articolo');
    if (expCols.mov_col_descrizione) headers.push('Descrizione');
    if (expCols.mov_col_quantita) headers.push('Quantità');
    if (expCols.mov_col_lotto) headers.push('Lotto');

    const rows = allMovimenti.map(m => {
      const row = isAllExp ? [clients.find(c => c.gestionale_code === m.gestionale_code)?.name || m.gestionale_code] : [];
      if (expCols.mov_col_data) row.push(formatDate(m.data_reg));
      if (expCols.mov_col_segno) row.push(m.segno || '');
      if (expCols.mov_col_causale) row.push(m.causale || '');
      if (expCols.mov_col_articolo) row.push(m.articolo);
      if (expCols.mov_col_descrizione) row.push(m.descrizione || '');
      if (expCols.mov_col_quantita) row.push(parseFloat(m.quantita));
      if (expCols.mov_col_lotto) row.push(m.lotto || '');
      return row;
    });

    const csv = [headers.join(';'), ...rows.map(r => r.map(c => typeof c === 'string' ? `"${c}"` : c).join(';'))].join('\n');
    const blob = new Blob(['﻿' + csv], { type: 'text/csv;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `movimenti_${new Date().toISOString().split('T')[0]}.csv`;
    a.click();
    URL.revokeObjectURL(url);
  };

  if (loading) {
    return <div className="panel"><div className="panel-body">Caricamento...</div></div>;
  }

  const isAll = selectedClient === "all";
  const clientCols = colConfig || { mov_col_articolo: true, mov_col_data: true, mov_col_segno: true, mov_col_causale: true, mov_col_descrizione: true, mov_col_quantita: true, mov_col_lotto: true };
  // Combina config admin (vis_*) con config cliente - colonna visibile solo se entrambe true
  const cols = {
    mov_col_articolo: config?.vis_mov_col_articolo !== false && clientCols.mov_col_articolo !== false,
    mov_col_data: config?.vis_mov_col_data !== false && clientCols.mov_col_data !== false,
    mov_col_segno: config?.vis_mov_col_segno !== false && clientCols.mov_col_segno !== false,
    mov_col_causale: config?.vis_mov_col_causale !== false && clientCols.mov_col_causale !== false,
    mov_col_descrizione: config?.vis_mov_col_descrizione !== false && clientCols.mov_col_descrizione !== false,
    mov_col_quantita: config?.vis_mov_col_quantita !== false && clientCols.mov_col_quantita !== false,
    mov_col_lotto: config?.vis_mov_col_lotto !== false && clientCols.mov_col_lotto !== false
  };

  return (
    <div>
      <SectionH>{t('movimenti_title')}</SectionH>

      <div className="filter-panel mb-16">
        <div className="filter-panel-header">
          <span className="filter-panel-icon">{Icon.filter}</span>
          <span>{t('filters_title')}</span>
        </div>
        <div className="filter-panel-body">
          <div className="filter-grid" style={{display: "flex", flexWrap: "wrap", gap: 12, marginBottom: 0}}>
            <div className="field" style={{flex: "0 0 150px"}}>
              <label>{t('client')}</label>
              <select
                value={isAll ? "all" : (selectedClient?.id || "")}
                onChange={(e) => {
                  if (e.target.value === "all") {
                    setSelectedClient("all");
                  } else {
                    const c = clients.find(c => c.id === parseInt(e.target.value));
                    setSelectedClient(c);
                  }
                }}
              >
                <option value="all">— {t('all_clients')} —</option>
                {clients.map(c => (
                  <option key={c.id} value={c.id}>{c.name} ({c.code})</option>
                ))}
              </select>
            </div>

            {cols.mov_col_articolo !== false && (
              <div className="field" style={{flex: 1}}>
                <label>{t('article')}</label>
                <input
                  type="text"
                  placeholder={t('search_article')}
                  value={filters.articolo}
                  onChange={(e) => handleFilterChange("articolo", e.target.value)}
                  onKeyDown={(e) => e.key === "Enter" && handleSearch()}
                />
              </div>
            )}

            <div className="field" style={{maxWidth: 130}}>
              <label>{t('date_from')}</label>
              <input
                type="date"
                value={filters.dataDa}
                onChange={(e) => handleFilterChange("dataDa", e.target.value)}
              />
            </div>

            <div className="field" style={{maxWidth: 130}}>
              <label>{t('date_to')}</label>
              <input
                type="date"
                value={filters.dataA}
                onChange={(e) => handleFilterChange("dataA", e.target.value)}
              />
            </div>

            <div className="field" style={{maxWidth: 80}}>
              <label>{t('sign')}</label>
              <select
                value={filters.segno}
                onChange={(e) => handleFilterChange("segno", e.target.value)}
              >
                <option value="">{t('all')}</option>
                <option value="+">{t('sign_in')}</option>
                <option value="-">{t('sign_out')}</option>
              </select>
            </div>

            <div className="field" style={{maxWidth: 80}}>
              <label>{t('causale')}</label>
              <input
                type="text"
                placeholder="es. E, U"
                value={filters.causale}
                onChange={(e) => handleFilterChange("causale", e.target.value.toUpperCase())}
                onKeyDown={(e) => e.key === "Enter" && handleSearch()}
              />
            </div>

            {cols.mov_col_lotto !== false && (
              <div className="field" style={{flex: 1}}>
                <label>{t('lotto')}</label>
                <input
                  type="text"
                  placeholder={t('search_lotto')}
                  value={filters.lotto}
                  onChange={(e) => handleFilterChange("lotto", e.target.value)}
                  onKeyDown={(e) => e.key === "Enter" && handleSearch()}
                />
              </div>
            )}

            <div className="field filter-actions-inline" style={{flex: "0 0 auto"}}>
              <label>&nbsp;</label>
              <div style={{display: "flex", gap: 8}}>
                <button className="btn btn-ghost" onClick={resetFilters}>
                  {Icon.refresh} {t('reset')}
                </button>
                <button className="btn btn-primary" onClick={handleSearch}>
                  {Icon.search} {t('search')}
                </button>
                <button className="btn btn-export" onClick={exportExcel} disabled={total === 0}>
                  <span className="btn-export-icon">{Icon.download}</span>
                  {t('export_excel')}
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>

      {/* Card riassuntive - usa dati aggregati dal backend */}
      {!loadingData && total > 0 && (() => {
        const saldo = totaleEntrate - totaleUscite;

        const formatDateIt = (d) => d ? d.split('-').reverse().join('/') : '';
        const formatDateRange = () => {
          if (filters.dataDa && filters.dataA) {
            return `tra ${formatDateIt(filters.dataDa)} e ${formatDateIt(filters.dataA)}`;
          } else if (filters.dataDa) {
            return `dal ${formatDateIt(filters.dataDa)}`;
          } else if (filters.dataA) {
            return `fino al ${formatDateIt(filters.dataA)}`;
          }
          return "nel periodo selezionato";
        };

        return (
          <div className="stats-cards stats-cards-4 mb-16">
            <div className="stat-card">
              <div className="stat-card-content">
                <div className="stat-card-label">{t('card_movements_period')}</div>
                <div className="stat-card-value">{total.toLocaleString('it-CH')}</div>
                <div className="stat-card-sub">{formatDateRange()}</div>
              </div>
            </div>

            <div className="stat-card">
              <div className="stat-card-content">
                <div className="stat-card-label">{t('card_pieces_in')}</div>
                <div className="stat-card-value" style={{color: "var(--ok)"}}>+{Math.round(totaleEntrate).toLocaleString('it-CH')}</div>
              </div>
              <div className="stat-card-sparkline green">
                <svg viewBox="0 0 100 30" preserveAspectRatio="none">
                  <polyline points="0,25 15,22 30,18 45,20 60,15 75,12 90,8 100,5" fill="none" stroke="currentColor" strokeWidth="2"/>
                </svg>
              </div>
            </div>

            <div className="stat-card">
              <div className="stat-card-content">
                <div className="stat-card-label">{t('card_pieces_out')}</div>
                <div className="stat-card-value" style={{color: "var(--err)"}}>−{Math.round(totaleUscite).toLocaleString('it-CH')}</div>
              </div>
              <div className="stat-card-sparkline red">
                <svg viewBox="0 0 100 30" preserveAspectRatio="none">
                  <polyline points="0,5 15,8 30,12 45,10 60,15 75,18 90,22 100,25" fill="none" stroke="currentColor" strokeWidth="2"/>
                </svg>
              </div>
            </div>

            <div className="stat-card">
              <div className="stat-card-content">
                <div className="stat-card-label">{t('card_period_balance')}</div>
                <div className="stat-card-value" style={{color: saldo >= 0 ? "var(--ok)" : "var(--err)"}}>
                  {saldo >= 0 ? '+' : '−'}{Math.abs(Math.round(saldo)).toLocaleString('it-CH')}
                </div>
                <div className="stat-card-sub">{t('in_out_diff')}</div>
              </div>
            </div>
          </div>
        );
      })()}

      <div style={{fontSize: 13, color: "var(--text-3)", marginBottom: 12}}>
        {total} {t('total_movimenti')}
      </div>

      <div className="panel">
        {loadingData ? (
          <div className="panel-body"><div style={{padding: 20, textAlign: "center"}}>{t('loading_movimenti')}</div></div>
        ) : movimenti.length === 0 ? (
          <div className="panel-body empty">
            <div style={{padding: "40px 20px", textAlign: "center", color: "var(--text-3)"}}>
              {t('no_movimenti')}
            </div>
          </div>
        ) : (
          <table className="data">
            <thead>
              <tr>
                {isAll && <th>{t('client')}</th>}
                {cols.mov_col_data !== false && <th style={{width: 75}}>{t('date')}</th>}
                {cols.mov_col_segno !== false && <th style={{textAlign: "center", width: 56}}></th>}
                {cols.mov_col_causale !== false && <th>{t('causale')}</th>}
                {cols.mov_col_articolo !== false && <th>{t('article')}</th>}
                {cols.mov_col_descrizione !== false && <th>{t('description')}</th>}
                {cols.mov_col_quantita !== false && <th style={{textAlign: "right"}}>{t('quantity')}</th>}
                {cols.mov_col_lotto !== false && <th>{t('lotto')}</th>}
              </tr>
            </thead>
            <tbody>
              {movimenti.map((m, i) => (
                <tr key={i}>
                  {isAll && <td>{clients.find(c => c.gestionale_code === m.gestionale_code)?.name || m.gestionale_code}</td>}
                  {cols.mov_col_data !== false && <td className="mono" style={{fontSize: 12}}>{formatDate(m.data_reg)}</td>}
                  {cols.mov_col_segno !== false && <td style={{textAlign: "center"}}>
                    {m.segno && <span className={m.segno === '+' ? 'segno-dot plus' : 'segno-dot minus'}></span>}
                  </td>}
                  {cols.mov_col_causale !== false && <td><Badge type={m.segno === '+' ? 'ok' : m.segno === '-' ? 'err' : 'info'}>{m.causale || "?"}</Badge></td>}
                  {cols.mov_col_articolo !== false && <td className="mono"><strong>{m.articolo}</strong></td>}
                  {cols.mov_col_descrizione !== false && <td>{m.descrizione || "-"}</td>}
                  {cols.mov_col_quantita !== false && <td style={{textAlign: "right"}}>{parseFloat(m.quantita).toLocaleString('it-CH')}</td>}
                  {cols.mov_col_lotto !== false && <td>{m.lotto || "-"}</td>}
                </tr>
              ))}
            </tbody>
          </table>
        )}
        {/* Paginazione */}
        {total > pageSize && (
          <div className="pagination">
            <button
              className="btn btn-sm btn-secondary"
              disabled={page === 1}
              onClick={() => setPage(1)}
            >
              ««
            </button>
            <button
              className="btn btn-sm btn-secondary"
              disabled={page === 1}
              onClick={() => setPage(p => p - 1)}
            >
              «
            </button>
            <span className="pagination-info">
              Pagina {page} di {Math.ceil(total / pageSize)} · Righe {((page - 1) * pageSize) + 1}-{Math.min(page * pageSize, total)} di {total}
            </span>
            <button
              className="btn btn-sm btn-secondary"
              disabled={page >= Math.ceil(total / pageSize)}
              onClick={() => setPage(p => p + 1)}
            >
              »
            </button>
            <button
              className="btn btn-sm btn-secondary"
              disabled={page >= Math.ceil(total / pageSize)}
              onClick={() => setPage(Math.ceil(total / pageSize))}
            >
              »»
            </button>
          </div>
        )}
      </div>
    </div>
  );
}

// Vista Saldi per utente finale (c2)
function C2SaldiView({ user, config }) {
  const [saldi, setSaldi] = useStateApp([]);
  const [loading, setLoading] = useStateApp(true);
  const [filter, setFilter] = useStateApp("");
  const [total, setTotal] = useStateApp(0);
  const [excludeZero, setExcludeZero] = useStateApp(true);
  const [colConfig, setColConfig] = useStateApp(null);

  const loadSaldi = async () => {
    setLoading(true);
    const token = localStorage.getItem("token");
    const showPaletta = colConfig?.saldi_col_paletta !== false;
    const params = new URLSearchParams({
      limit: 1000,
      exclude_zero: excludeZero ? '1' : '0',
      aggregate: (colConfig && !showPaletta) ? '1' : '0'
    });
    if (filter) params.append("articolo", filter);

    const res = await fetch(`${API_BASE}/saldi?${params}`, {
      headers: { Authorization: `Bearer ${token}` }
    }).then(r => r.json());

    if (res.success) {
      setSaldi(res.saldi);
      setTotal(res.total);
      if (res.config) setColConfig(res.config);
    }
    setLoading(false);
  };

  useEffectApp(() => {
    loadSaldi();
  }, [excludeZero]);

  // Ricarica quando cambia colConfig (per aggregazione)
  useEffectApp(() => {
    if (colConfig) loadSaldi();
  }, [colConfig?.saldi_col_paletta]);

  const handleSearch = () => loadSaldi();

  const exportExcel = () => {
    if (!saldi.length) return;
    const cols = colConfig || {};
    const headers = [];
    if (cols.saldi_col_articolo !== false) headers.push('Articolo');
    if (cols.saldi_col_descrizione !== false) headers.push('Descrizione');
    if (cols.saldi_col_quantita !== false) headers.push('Quantità');
    if (cols.saldi_col_um !== false) headers.push('UM');
    if (cols.saldi_col_lotto !== false) headers.push('Lotto');
    if (cols.saldi_col_ubicazione !== false) headers.push('Ubicazione');
    if (cols.saldi_col_paletta !== false) headers.push('Paletta');

    const rows = saldi.map(s => {
      const row = [];
      if (cols.saldi_col_articolo !== false) row.push(s.articolo);
      if (cols.saldi_col_descrizione !== false) row.push(s.descrizione || '');
      if (cols.saldi_col_quantita !== false) row.push(parseFloat(s.quantita));
      if (cols.saldi_col_um !== false) row.push(s.um || '');
      if (cols.saldi_col_lotto !== false) row.push(s.lotto || '');
      if (cols.saldi_col_ubicazione !== false) row.push([s.ubi1, s.ubi2, s.ubi3, s.ubi4].filter(Boolean).join('-') || '');
      if (cols.saldi_col_paletta !== false) row.push(s.paletta || '');
      return row;
    });

    const csv = [headers.join(';'), ...rows.map(r => r.map(c => typeof c === 'string' ? `"${c}"` : c).join(';'))].join('\n');
    const blob = new Blob(['﻿' + csv], { type: 'text/csv;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `saldi_${new Date().toISOString().slice(0,10)}.csv`;
    a.click();
    URL.revokeObjectURL(url);
  };

  const cols = colConfig || {};

  return (
    <div>
      <SectionH>{t('saldi_title')}</SectionH>

      <div className="panel mb-16">
        <div className="panel-body">
          <div style={{display: "flex", gap: 8, alignItems: "flex-end", flexWrap: "wrap"}}>
            {cols.saldi_col_articolo !== false && (
              <div className="field" style={{margin: 0, flex: 1, minWidth: 200}}>
                <label style={{marginBottom: 4, display: "block"}}>{t('article')}</label>
                <input
                  type="text"
                  placeholder={t('search_article')}
                  value={filter}
                  onChange={(e) => setFilter(e.target.value)}
                  onKeyDown={(e) => e.key === "Enter" && handleSearch()}
                />
              </div>
            )}
            <button className="btn btn-primary" onClick={handleSearch}>{t('search')}</button>
          </div>
          <div style={{display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: 12, flexWrap: "wrap", gap: 12}}>
            <Checkbox checked={excludeZero} onChange={setExcludeZero} label={t('exclude_zero')}/>
            <button className="btn btn-export" onClick={exportExcel} disabled={!saldi.length}>
              <span className="btn-export-icon">{Icon.download}</span>
              {t('export_excel')}
            </button>
          </div>
        </div>
      </div>

      {/* Card riassuntive */}
      {!loading && saldi.length > 0 && (() => {
        const articoliDistinti = new Set(saldi.map(s => s.articolo)).size;
        const totaliPerUM = {};
        saldi.forEach(s => {
          const um = s.um || 'N/D';
          totaliPerUM[um] = (totaliPerUM[um] || 0) + parseFloat(s.quantita || 0);
        });
        const umEntries = Object.entries(totaliPerUM).sort((a, b) => b[1] - a[1]).slice(0, 4);
        const articoliAggregati = {};
        saldi.forEach(s => {
          if (!articoliAggregati[s.articolo]) {
            articoliAggregati[s.articolo] = { articolo: s.articolo, quantita: 0, um: s.um };
          }
          articoliAggregati[s.articolo].quantita += parseFloat(s.quantita || 0);
        });
        const topArticoli = Object.values(articoliAggregati).sort((a, b) => b.quantita - a.quantita).slice(0, 3);

        return (
          <div className="stats-cards mb-16">
            <div className="stat-card">
              <div className="stat-card-icon" style={{background: "var(--info-soft)", color: "var(--ti-blue)"}}>
                {Icon.box}
              </div>
              <div className="stat-card-content">
                <div className="stat-card-label">{t('card_articles')}</div>
                <div className="stat-card-value">{articoliDistinti}</div>
                <div className="stat-card-sub">{t('card_distinct_articles')}</div>
              </div>
            </div>
            <div className="stat-card">
              <div className="stat-card-icon" style={{background: "var(--info-soft)", color: "var(--ti-blue)"}}>
                {Icon.box}
              </div>
              <div className="stat-card-content">
                <div className="stat-card-label">{t('card_total_um')}</div>
                <div className="stat-card-list">
                  {umEntries.map(([um, tot]) => (
                    <div key={um} className="stat-card-list-item">
                      <span className="stat-card-list-label">{um}</span>
                      <span className="stat-card-list-value">{Math.round(tot).toLocaleString('it-CH')}</span>
                    </div>
                  ))}
                </div>
              </div>
              <div className="stat-card-bar"></div>
            </div>
            <div className="stat-card">
              <div className="stat-card-icon" style={{background: "var(--ok-soft)", color: "var(--ok)"}}>
                {Icon.trend}
              </div>
              <div className="stat-card-content">
                <div className="stat-card-label">{t('card_top_articles')}</div>
                <div className="stat-card-list">
                  {topArticoli.map((art, i) => (
                    <div key={i} className="stat-card-list-item">
                      <span className="stat-card-list-label mono" style={{fontSize: 11}}>{art.articolo}</span>
                      <span className="stat-card-list-value">{Math.round(art.quantita).toLocaleString('it-CH')} <small>{art.um}</small></span>
                    </div>
                  ))}
                </div>
              </div>
            </div>
          </div>
        );
      })()}

      <div style={{fontSize: 13, color: "var(--text-3)", marginBottom: 12}}>
        {total} {t('rows')} {excludeZero ? `(${t('exclude_zero')})` : ""} {filter && `· ${t('filtered_by')} "${filter}"`}
      </div>

      <div className="panel">
        {loading ? (
          <div className="panel-body"><div style={{padding: 20, textAlign: "center"}}>{t('loading_saldi')}</div></div>
        ) : saldi.length === 0 ? (
          <div className="panel-body empty">
            <div style={{padding: "40px 20px", textAlign: "center", color: "var(--text-3)"}}>
              {t('no_saldi')}
            </div>
          </div>
        ) : (
          <table className="data">
            <thead>
              <tr>
                {cols.saldi_col_articolo !== false && <th>{t('article')}</th>}
                {cols.saldi_col_descrizione !== false && <th>{t('description')}</th>}
                {cols.saldi_col_quantita !== false && <th style={{textAlign: "right"}}>{t('quantity')}</th>}
                {cols.saldi_col_um !== false && <th>{t('um')}</th>}
                {cols.saldi_col_lotto !== false && <th>{t('lotto')}</th>}
                {cols.saldi_col_ubicazione !== false && <th>{t('location')}</th>}
                {cols.saldi_col_paletta !== false && <th>{t('pallet')}</th>}
              </tr>
            </thead>
            <tbody>
              {saldi.map((s, i) => (
                <tr key={i}>
                  {cols.saldi_col_articolo !== false && <td className="mono"><strong>{s.articolo}</strong></td>}
                  {cols.saldi_col_descrizione !== false && <td>{s.descrizione || "-"}</td>}
                  {cols.saldi_col_quantita !== false && <td style={{textAlign: "right"}}>{parseFloat(s.quantita).toLocaleString('it-CH')}</td>}
                  {cols.saldi_col_um !== false && <td>{s.um || "-"}</td>}
                  {cols.saldi_col_lotto !== false && <td>{s.lotto || "-"}</td>}
                  {cols.saldi_col_ubicazione !== false && <td className="mono" style={{fontSize: 11}}>{[s.ubi1, s.ubi2, s.ubi3, s.ubi4].filter(Boolean).join("-") || "-"}</td>}
                  {cols.saldi_col_paletta !== false && <td>{s.paletta || "-"}</td>}
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>
    </div>
  );
}

// Vista Movimenti per utente finale (c2)
function C2MovimentiView({ user, config }) {
  const [movimenti, setMovimenti] = useStateApp([]);
  const [loading, setLoading] = useStateApp(true);
  const [filters, setFilters] = useStateApp({
    articolo: "",
    dataDa: getMonthStartDate(),
    dataA: getMonthEndDate(),
    segno: "",
    causale: "",
    lotto: ""
  });
  const [total, setTotal] = useStateApp(0);
  const [colConfig, setColConfig] = useStateApp(null);

  const loadMovimenti = async () => {
    setLoading(true);
    const token = localStorage.getItem("token");
    const params = new URLSearchParams({ limit: 500 });

    if (filters.articolo) params.append("articolo", filters.articolo);
    if (filters.dataDa) params.append("data_da", filters.dataDa);
    if (filters.dataA) params.append("data_a", filters.dataA);
    if (filters.segno) params.append("segno", filters.segno);
    if (filters.causale) params.append("causale", filters.causale);
    if (filters.lotto) params.append("lotto", filters.lotto);

    const res = await fetch(`${API_BASE}/movimenti?${params}`, {
      headers: { Authorization: `Bearer ${token}` }
    }).then(r => r.json());

    if (res.success) {
      setMovimenti(res.movimenti);
      setTotal(res.total);
      if (res.config) setColConfig(res.config);
    }
    setLoading(false);
  };

  useEffectApp(() => {
    loadMovimenti();
  }, []);

  const handleSearch = () => loadMovimenti();

  const handleFilterChange = (field, value) => {
    setFilters(prev => ({ ...prev, [field]: value }));
  };

  const resetFilters = () => {
    setFilters({ articolo: "", dataDa: getMonthStartDate(), dataA: getMonthEndDate(), segno: "", causale: "", lotto: "" });
  };

  const formatDate = (d) => {
    if (!d) return "-";
    return new Date(d).toLocaleDateString('it-CH');
  };

  const exportExcel = () => {
    if (!movimenti.length) return;
    const expCols = colConfig || { mov_col_articolo: true, mov_col_data: true, mov_col_segno: true, mov_col_causale: true, mov_col_descrizione: true, mov_col_quantita: true, mov_col_lotto: true };

    const headers = [];
    if (expCols.mov_col_data !== false) headers.push('Data');
    if (expCols.mov_col_segno !== false) headers.push('Segno');
    if (expCols.mov_col_causale !== false) headers.push('Causale');
    if (expCols.mov_col_articolo !== false) headers.push('Articolo');
    if (expCols.mov_col_descrizione !== false) headers.push('Descrizione');
    if (expCols.mov_col_quantita !== false) headers.push('Quantità');
    if (expCols.mov_col_lotto !== false) headers.push('Lotto');

    const rows = movimenti.map(m => {
      const row = [];
      if (expCols.mov_col_data !== false) row.push(formatDate(m.data_reg));
      if (expCols.mov_col_segno !== false) row.push(m.segno || '');
      if (expCols.mov_col_causale !== false) row.push(m.causale || '');
      if (expCols.mov_col_articolo !== false) row.push(m.articolo);
      if (expCols.mov_col_descrizione !== false) row.push(m.descrizione || '');
      if (expCols.mov_col_quantita !== false) row.push(parseFloat(m.quantita));
      if (expCols.mov_col_lotto !== false) row.push(m.lotto || '');
      return row;
    });

    const csv = [headers.join(';'), ...rows.map(r => r.map(c => typeof c === 'string' ? `"${c}"` : c).join(';'))].join('\n');
    const blob = new Blob(['﻿' + csv], { type: 'text/csv;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `movimenti_${new Date().toISOString().split('T')[0]}.csv`;
    a.click();
    URL.revokeObjectURL(url);
  };

  const cols = colConfig || { mov_col_articolo: true, mov_col_data: true, mov_col_segno: true, mov_col_causale: true, mov_col_descrizione: true, mov_col_quantita: true, mov_col_lotto: true };

  return (
    <div>
      <SectionH>{t('movimenti_title')}</SectionH>

      <div className="filter-panel mb-16">
        <div className="filter-panel-header">
          <span className="filter-panel-icon">{Icon.filter}</span>
          <span>{t('filters_title')}</span>
        </div>
        <div className="filter-panel-body">
          <div className="filter-grid">
            {cols.mov_col_articolo !== false && (
              <div className="field" style={{flex: 1}}>
                <label>{t('article')}</label>
                <input
                  type="text"
                  placeholder={t('search_article')}
                  value={filters.articolo}
                  onChange={(e) => handleFilterChange("articolo", e.target.value)}
                  onKeyDown={(e) => e.key === "Enter" && handleSearch()}
                />
              </div>
            )}

            <div className="field" style={{maxWidth: 130}}>
              <label>{t('date_from')}</label>
              <input
                type="date"
                value={filters.dataDa}
                onChange={(e) => handleFilterChange("dataDa", e.target.value)}
              />
            </div>

            <div className="field" style={{maxWidth: 130}}>
              <label>{t('date_to')}</label>
              <input
                type="date"
                value={filters.dataA}
                onChange={(e) => handleFilterChange("dataA", e.target.value)}
              />
            </div>

            <div className="field" style={{maxWidth: 80}}>
              <label>{t('sign')}</label>
              <select
                value={filters.segno}
                onChange={(e) => handleFilterChange("segno", e.target.value)}
              >
                <option value="">{t('all')}</option>
                <option value="+">{t('sign_in')}</option>
                <option value="-">{t('sign_out')}</option>
              </select>
            </div>

            <div className="field" style={{maxWidth: 80}}>
              <label>{t('causale')}</label>
              <input
                type="text"
                placeholder="es. E, U"
                value={filters.causale}
                onChange={(e) => handleFilterChange("causale", e.target.value.toUpperCase())}
                onKeyDown={(e) => e.key === "Enter" && handleSearch()}
              />
            </div>

            {cols.mov_col_lotto !== false && (
              <div className="field" style={{flex: 1}}>
                <label>{t('lotto')}</label>
                <input
                  type="text"
                  placeholder={t('search_lotto')}
                  value={filters.lotto}
                  onChange={(e) => handleFilterChange("lotto", e.target.value)}
                  onKeyDown={(e) => e.key === "Enter" && handleSearch()}
                />
              </div>
            )}

            <div className="field filter-actions-inline" style={{flex: "0 0 auto"}}>
              <label>&nbsp;</label>
              <div style={{display: "flex", gap: 8}}>
                <button className="btn btn-ghost" onClick={resetFilters}>
                  {Icon.refresh} {t('reset')}
                </button>
                <button className="btn btn-primary" onClick={handleSearch}>
                  {Icon.search} {t('search')}
                </button>
                <button className="btn btn-export" onClick={exportExcel} disabled={!movimenti.length}>
                  <span className="btn-export-icon">{Icon.download}</span>
                  {t('export_excel')}
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>

      {/* Card riassuntive */}
      {!loading && movimenti.length > 0 && (() => {
        const totaleEntrate = movimenti.filter(m => m.segno === '+').reduce((sum, m) => sum + parseFloat(m.quantita || 0), 0);
        const totaleUscite = movimenti.filter(m => m.segno === '-').reduce((sum, m) => sum + parseFloat(m.quantita || 0), 0);
        const saldo = totaleEntrate - totaleUscite;

        const formatDateIt = (d) => d ? d.split('-').reverse().join('/') : '';
        const formatDateRange = () => {
          if (filters.dataDa && filters.dataA) {
            return `tra ${formatDateIt(filters.dataDa)} e ${formatDateIt(filters.dataA)}`;
          } else if (filters.dataDa) {
            return `dal ${formatDateIt(filters.dataDa)}`;
          } else if (filters.dataA) {
            return `fino al ${formatDateIt(filters.dataA)}`;
          }
          return "nel periodo selezionato";
        };

        return (
          <div className="stats-cards stats-cards-4 mb-16">
            <div className="stat-card">
              <div className="stat-card-content">
                <div className="stat-card-label">{t('card_movements_period')}</div>
                <div className="stat-card-value">{movimenti.length}</div>
                <div className="stat-card-sub">{formatDateRange()}</div>
              </div>
            </div>

            <div className="stat-card">
              <div className="stat-card-content">
                <div className="stat-card-label">{t('card_pieces_in')}</div>
                <div className="stat-card-value" style={{color: "var(--ok)"}}>+{Math.round(totaleEntrate).toLocaleString('it-CH')}</div>
              </div>
              <div className="stat-card-sparkline green">
                <svg viewBox="0 0 100 30" preserveAspectRatio="none">
                  <polyline points="0,25 15,22 30,18 45,20 60,15 75,12 90,8 100,5" fill="none" stroke="currentColor" strokeWidth="2"/>
                </svg>
              </div>
            </div>

            <div className="stat-card">
              <div className="stat-card-content">
                <div className="stat-card-label">{t('card_pieces_out')}</div>
                <div className="stat-card-value" style={{color: "var(--err)"}}>−{Math.round(totaleUscite).toLocaleString('it-CH')}</div>
              </div>
              <div className="stat-card-sparkline red">
                <svg viewBox="0 0 100 30" preserveAspectRatio="none">
                  <polyline points="0,5 15,8 30,12 45,10 60,15 75,18 90,22 100,25" fill="none" stroke="currentColor" strokeWidth="2"/>
                </svg>
              </div>
            </div>

            <div className="stat-card">
              <div className="stat-card-content">
                <div className="stat-card-label">{t('card_period_balance')}</div>
                <div className="stat-card-value" style={{color: saldo >= 0 ? "var(--ok)" : "var(--err)"}}>
                  {saldo >= 0 ? '+' : '−'}{Math.abs(Math.round(saldo)).toLocaleString('it-CH')}
                </div>
                <div className="stat-card-sub">{t('in_out_diff')}</div>
              </div>
            </div>
          </div>
        );
      })()}

      <div style={{fontSize: 13, color: "var(--text-3)", marginBottom: 12}}>
        {total} {t('total_movimenti')}
      </div>

      <div className="panel">
        {loading ? (
          <div className="panel-body"><div style={{padding: 20, textAlign: "center"}}>{t('loading_movimenti')}</div></div>
        ) : movimenti.length === 0 ? (
          <div className="panel-body empty">
            <div style={{padding: "40px 20px", textAlign: "center", color: "var(--text-3)"}}>
              {t('no_movimenti')}
            </div>
          </div>
        ) : (
          <table className="data">
            <thead>
              <tr>
                {cols.mov_col_data !== false && <th style={{width: 75}}>{t('date')}</th>}
                {cols.mov_col_segno !== false && <th style={{textAlign: "center", width: 56}}></th>}
                {cols.mov_col_causale !== false && <th>{t('causale')}</th>}
                {cols.mov_col_articolo !== false && <th>{t('article')}</th>}
                {cols.mov_col_descrizione !== false && <th>{t('description')}</th>}
                {cols.mov_col_quantita !== false && <th style={{textAlign: "right"}}>{t('quantity')}</th>}
                {cols.mov_col_lotto !== false && <th>{t('lotto')}</th>}
              </tr>
            </thead>
            <tbody>
              {movimenti.map((m, i) => (
                <tr key={i}>
                  {cols.mov_col_data !== false && <td className="mono" style={{fontSize: 12}}>{formatDate(m.data_reg)}</td>}
                  {cols.mov_col_segno !== false && <td style={{textAlign: "center"}}>
                    {m.segno && <span className={m.segno === '+' ? 'segno-dot plus' : 'segno-dot minus'}></span>}
                  </td>}
                  {cols.mov_col_causale !== false && <td><Badge type={m.segno === '+' ? 'ok' : m.segno === '-' ? 'err' : 'info'}>{m.causale || "?"}</Badge></td>}
                  {cols.mov_col_articolo !== false && <td className="mono"><strong>{m.articolo}</strong></td>}
                  {cols.mov_col_descrizione !== false && <td>{m.descrizione || "-"}</td>}
                  {cols.mov_col_quantita !== false && <td style={{textAlign: "right"}}>{parseFloat(m.quantita).toLocaleString('it-CH')}</td>}
                  {cols.mov_col_lotto !== false && <td>{m.lotto || "-"}</td>}
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>
    </div>
  );
}

// Modal Nuovo Cliente (per Logista)
function ClientNewClientModal({ config, onClose, onCreated }) {
  const [form, setForm] = useStateApp({
    code: "",
    name: "",
    enable_saldi: true,
    enable_movimenti: false,
    gestionale_code: "",
    saldi_col_articolo: true,
    saldi_col_descrizione: true,
    saldi_col_quantita: true,
    saldi_col_um: true,
    saldi_col_lotto: true,
    saldi_col_ubicazione: true,
    saldi_col_paletta: true,
    mov_col_articolo: true,
    mov_col_data: true,
    mov_col_segno: true,
    mov_col_causale: true,
    mov_col_descrizione: true,
    mov_col_quantita: true,
    mov_col_lotto: true
  });
  const [saving, setSaving] = useStateApp(false);
  const [error, setError] = useStateApp("");

  const handleChange = (field, value) => {
    setForm(prev => ({ ...prev, [field]: value }));
  };

  const handleSubmit = async () => {
    if (!form.code || !form.name || !form.gestionale_code) {
      setError("Codice, ragione sociale e codice gestionale sono obbligatori");
      return;
    }
    if (!/^\d{1,6}$/.test(form.gestionale_code)) {
      setError("Il codice gestionale deve essere numerico (da 1 a 999999)");
      return;
    }

    setSaving(true);
    setError("");

    const token = localStorage.getItem("token");
    const res = await fetch(`${API_BASE}/clients`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${token}`
      },
      body: JSON.stringify(form)
    });
    const data = await res.json();

    if (data.success) {
      onCreated();
    } else {
      setError(data.error || "Errore creazione cliente");
    }
    setSaving(false);
  };

  return (
    <Modal title={t('new_client')} size="md" onClose={onClose} footer={<>
      <button className="btn btn-secondary" onClick={onClose} disabled={saving}>{t('cancel')}</button>
      <button className="btn btn-primary" onClick={handleSubmit} disabled={saving}>
        {saving ? "Creazione..." : "Crea Cliente"}
      </button>
    </>}>
      {error && (
        <div style={{marginBottom: 16, padding: "10px 12px", background: "rgba(220,53,69,0.1)", border: "1px solid rgba(220,53,69,0.3)", borderRadius: 4, color: "#dc3545", fontSize: 13}}>
          {error}
        </div>
      )}

      <div className="field-grid">
        <div className="field">
          <label>{t('client_name')} *</label>
          <input type="text" value={form.name} onChange={(e) => handleChange("name", e.target.value)} placeholder="es. Pinco Pallo SA"/>
        </div>
        <div className="field">
          <label>{t('code')} *</label>
          <input type="text" value={form.code} onChange={(e) => handleChange("code", e.target.value.toUpperCase())} placeholder="es. PPSA" className="mono" maxLength={20}/>
        </div>
        <div className="field" style={{gridColumn: "1 / -1"}}>
          <label>{t('erp_client_code')} *</label>
          <input type="text" value={form.gestionale_code} onChange={(e) => handleChange("gestionale_code", e.target.value.replace(/\D/g, "").slice(0, 6))} placeholder="000000" className="mono" maxLength={6}/>
        </div>
      </div>

      <h3 style={{margin: "22px 0 8px", fontSize: 13, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: "0.06em"}}>Permessi</h3>
      <div style={{display: "grid", gap: 10}}>
        <Checkbox checked={form.enable_saldi} onChange={(v) => handleChange("enable_saldi", v)} label="Visualizzazione Saldi"/>
        {form.enable_saldi && (
          <div style={{marginLeft: 24, padding: "8px 12px", background: "var(--bg-2)", borderRadius: 6, display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8}}>
            {config?.vis_saldi_col_articolo !== false && <Checkbox checked={form.saldi_col_articolo} onChange={(v) => handleChange("saldi_col_articolo", v)} label="Articolo"/>}
            {config?.vis_saldi_col_descrizione !== false && <Checkbox checked={form.saldi_col_descrizione} onChange={(v) => handleChange("saldi_col_descrizione", v)} label="Descrizione"/>}
            {config?.vis_saldi_col_quantita !== false && <Checkbox checked={form.saldi_col_quantita} onChange={(v) => handleChange("saldi_col_quantita", v)} label="Quantità"/>}
            {config?.vis_saldi_col_um !== false && <Checkbox checked={form.saldi_col_um} onChange={(v) => handleChange("saldi_col_um", v)} label="Unità misura"/>}
            {config?.vis_saldi_col_lotto !== false && <Checkbox checked={form.saldi_col_lotto} onChange={(v) => handleChange("saldi_col_lotto", v)} label="Lotto"/>}
            {config?.vis_saldi_col_ubicazione !== false && <Checkbox checked={form.saldi_col_ubicazione} onChange={(v) => handleChange("saldi_col_ubicazione", v)} label="Ubicazione"/>}
            {config?.vis_saldi_col_paletta !== false && <Checkbox checked={form.saldi_col_paletta} onChange={(v) => handleChange("saldi_col_paletta", v)} label="Paletta"/>}
          </div>
        )}
        <Checkbox checked={form.enable_movimenti} onChange={(v) => handleChange("enable_movimenti", v)} label="Visualizzazione Movimenti"/>
        {form.enable_movimenti && (
          <div style={{marginLeft: 24, padding: "8px 12px", background: "var(--bg-2)", borderRadius: 6, display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8}}>
            {config?.vis_mov_col_articolo !== false && <Checkbox checked={form.mov_col_articolo} onChange={(v) => handleChange("mov_col_articolo", v)} label="Articolo"/>}
            {config?.vis_mov_col_data !== false && <Checkbox checked={form.mov_col_data} onChange={(v) => handleChange("mov_col_data", v)} label="Data"/>}
            {config?.vis_mov_col_segno !== false && <Checkbox checked={form.mov_col_segno} onChange={(v) => handleChange("mov_col_segno", v)} label="Segno (+/-)"/>}
            {config?.vis_mov_col_causale !== false && <Checkbox checked={form.mov_col_causale} onChange={(v) => handleChange("mov_col_causale", v)} label="Causale"/>}
            {config?.vis_mov_col_descrizione !== false && <Checkbox checked={form.mov_col_descrizione} onChange={(v) => handleChange("mov_col_descrizione", v)} label="Descrizione"/>}
            {config?.vis_mov_col_quantita !== false && <Checkbox checked={form.mov_col_quantita} onChange={(v) => handleChange("mov_col_quantita", v)} label="Quantità"/>}
            {config?.vis_mov_col_lotto !== false && <Checkbox checked={form.mov_col_lotto} onChange={(v) => handleChange("mov_col_lotto", v)} label="Lotto"/>}
          </div>
        )}
      </div>
    </Modal>
  );
}

// Modal Modifica Cliente (per Logista)
function ClientEditClientModal({ client, config, onClose, onSaved }) {
  const [form, setForm] = useStateApp({
    name: client.name,
    enable_saldi: client.enable_saldi,
    enable_movimenti: client.enable_movimenti,
    gestionale_code: client.gestionale_code || "",
    active: client.active,
    saldi_col_articolo: client.saldi_col_articolo !== false,
    saldi_col_descrizione: client.saldi_col_descrizione !== false,
    saldi_col_quantita: client.saldi_col_quantita !== false,
    saldi_col_um: client.saldi_col_um !== false,
    saldi_col_lotto: client.saldi_col_lotto !== false,
    saldi_col_ubicazione: client.saldi_col_ubicazione !== false,
    saldi_col_paletta: client.saldi_col_paletta !== false,
    mov_col_articolo: client.mov_col_articolo !== false,
    mov_col_data: client.mov_col_data !== false,
    mov_col_segno: client.mov_col_segno !== false,
    mov_col_causale: client.mov_col_causale !== false,
    mov_col_descrizione: client.mov_col_descrizione !== false,
    mov_col_quantita: client.mov_col_quantita !== false,
    mov_col_lotto: client.mov_col_lotto !== false
  });
  const [saving, setSaving] = useStateApp(false);
  const [error, setError] = useStateApp("");

  const handleChange = (field, value) => {
    setForm(prev => ({ ...prev, [field]: value }));
  };

  const handleSubmit = async () => {
    if (!form.gestionale_code) {
      setError("Il codice cliente su gestionale è obbligatorio");
      return;
    }
    if (!/^\d{1,6}$/.test(form.gestionale_code)) {
      setError("Il codice gestionale deve essere numerico (da 1 a 999999)");
      return;
    }

    setSaving(true);
    setError("");

    const token = localStorage.getItem("token");
    const res = await fetch(`${API_BASE}/clients/${client.id}`, {
      method: "PUT",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${token}`
      },
      body: JSON.stringify(form)
    });
    const data = await res.json();

    if (data.success) {
      onSaved();
    } else {
      setError(data.error || "Errore salvataggio");
    }
    setSaving(false);
  };

  return (
    <Modal title={t('edit_client')} size="md" onClose={onClose} footer={<>
      <button className="btn btn-secondary" onClick={onClose} disabled={saving}>{t('cancel')}</button>
      <button className="btn btn-primary" onClick={handleSubmit} disabled={saving}>
        {saving ? t('saving') : t('save')}
      </button>
    </>}>
      {error && (
        <div style={{marginBottom: 16, padding: "10px 12px", background: "rgba(220,53,69,0.1)", border: "1px solid rgba(220,53,69,0.3)", borderRadius: 4, color: "#dc3545", fontSize: 13}}>
          {error}
        </div>
      )}

      <div className="field" style={{marginBottom: 14}}>
        <label>{t('code')}</label>
        <input type="text" value={client.code} disabled className="mono"/>
      </div>

      <div className="field" style={{marginBottom: 14}}>
        <label>{t('client_name')}</label>
        <input type="text" value={form.name} onChange={(e) => handleChange("name", e.target.value)}/>
      </div>

      <div className="field" style={{marginBottom: 14}}>
        <label>{t('erp_client_code')} *</label>
        <input type="text" value={form.gestionale_code} onChange={(e) => handleChange("gestionale_code", e.target.value.replace(/\D/g, "").slice(0, 6))} placeholder="000000" className="mono" maxLength={6}/>
      </div>

      <h3 style={{margin: "22px 0 8px", fontSize: 13, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: "0.06em"}}>Permessi</h3>
      <div style={{display: "grid", gap: 10}}>
        <Checkbox checked={form.enable_saldi} onChange={(v) => handleChange("enable_saldi", v)} label="Visualizzazione Saldi"/>
        {form.enable_saldi && (
          <div style={{marginLeft: 24, padding: "8px 12px", background: "var(--bg-2)", borderRadius: 6, display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8}}>
            {config?.vis_saldi_col_articolo !== false && <Checkbox checked={form.saldi_col_articolo} onChange={(v) => handleChange("saldi_col_articolo", v)} label="Articolo"/>}
            {config?.vis_saldi_col_descrizione !== false && <Checkbox checked={form.saldi_col_descrizione} onChange={(v) => handleChange("saldi_col_descrizione", v)} label="Descrizione"/>}
            {config?.vis_saldi_col_quantita !== false && <Checkbox checked={form.saldi_col_quantita} onChange={(v) => handleChange("saldi_col_quantita", v)} label="Quantità"/>}
            {config?.vis_saldi_col_um !== false && <Checkbox checked={form.saldi_col_um} onChange={(v) => handleChange("saldi_col_um", v)} label="Unità misura"/>}
            {config?.vis_saldi_col_lotto !== false && <Checkbox checked={form.saldi_col_lotto} onChange={(v) => handleChange("saldi_col_lotto", v)} label="Lotto"/>}
            {config?.vis_saldi_col_ubicazione !== false && <Checkbox checked={form.saldi_col_ubicazione} onChange={(v) => handleChange("saldi_col_ubicazione", v)} label="Ubicazione"/>}
            {config?.vis_saldi_col_paletta !== false && <Checkbox checked={form.saldi_col_paletta} onChange={(v) => handleChange("saldi_col_paletta", v)} label="Paletta"/>}
          </div>
        )}
        <Checkbox checked={form.enable_movimenti} onChange={(v) => handleChange("enable_movimenti", v)} label="Visualizzazione Movimenti"/>
        {form.enable_movimenti && (
          <div style={{marginLeft: 24, padding: "8px 12px", background: "var(--bg-2)", borderRadius: 6, display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8}}>
            {config?.vis_mov_col_articolo !== false && <Checkbox checked={form.mov_col_articolo} onChange={(v) => handleChange("mov_col_articolo", v)} label="Articolo"/>}
            {config?.vis_mov_col_data !== false && <Checkbox checked={form.mov_col_data} onChange={(v) => handleChange("mov_col_data", v)} label="Data"/>}
            {config?.vis_mov_col_segno !== false && <Checkbox checked={form.mov_col_segno} onChange={(v) => handleChange("mov_col_segno", v)} label="Segno (+/-)"/>}
            {config?.vis_mov_col_causale !== false && <Checkbox checked={form.mov_col_causale} onChange={(v) => handleChange("mov_col_causale", v)} label="Causale"/>}
            {config?.vis_mov_col_descrizione !== false && <Checkbox checked={form.mov_col_descrizione} onChange={(v) => handleChange("mov_col_descrizione", v)} label="Descrizione"/>}
            {config?.vis_mov_col_quantita !== false && <Checkbox checked={form.mov_col_quantita} onChange={(v) => handleChange("mov_col_quantita", v)} label="Quantità"/>}
            {config?.vis_mov_col_lotto !== false && <Checkbox checked={form.mov_col_lotto} onChange={(v) => handleChange("mov_col_lotto", v)} label="Lotto"/>}
          </div>
        )}
      </div>

      <div style={{marginTop: 16}}>
        <Checkbox checked={form.active} onChange={(v) => handleChange("active", v)} label="Cliente attivo"/>
      </div>
    </Modal>
  );
}

// Vista Import Log (per logista)
function ClientImportLog({ user, config }) {
  return (
    <div>
      <SectionH>Import log</SectionH>
      <div className="panel">
        <div className="panel-body empty">
          <div style={{padding: "40px 20px", textAlign: "center", color: "var(--text-3)"}}>
            <div style={{marginBottom: 8, fontSize: 14, fontWeight: 600}}>Funzionalità in sviluppo</div>
            Qui verranno visualizzati i log delle importazioni dati.
          </div>
        </div>
      </div>
    </div>
  );
}

// Vista tutti gli utenti (per logista)
function ClientAllUsers({ user, config, initialClient }) {
  const [users, setUsers] = useStateApp([]);
  const [clients, setClients] = useStateApp([]);
  const [selectedClient, setSelectedClient] = useStateApp(initialClient || "all");
  const [loading, setLoading] = useStateApp(true);
  const [newUserOpen, setNewUserOpen] = useStateApp(false);
  const [editingUser, setEditingUser] = useStateApp(null);

  const loadData = async () => {
    setLoading(true);
    const token = localStorage.getItem("token");

    const [usersRes, clientsRes] = await Promise.all([
      fetch(`${API_BASE}/users`, { headers: { Authorization: `Bearer ${token}` } }).then(r => r.json()),
      fetch(`${API_BASE}/clients`, { headers: { Authorization: `Bearer ${token}` } }).then(r => r.json())
    ]);

    if (usersRes.success) setUsers(usersRes.users);
    if (clientsRes.success) setClients(clientsRes.clients);
    setLoading(false);
  };

  useEffectApp(() => {
    loadData();
  }, []);

  useEffectApp(() => {
    if (initialClient) setSelectedClient(initialClient);
  }, [initialClient]);

  if (loading) {
    return <div className="panel"><div className="panel-body">Caricamento...</div></div>;
  }

  const isAll = selectedClient === "all";
  const filteredUsers = isAll ? users : users.filter(u => u.client_id === selectedClient?.id);

  return (
    <div>
      <SectionH>{t('nav_users')}</SectionH>

      <div className="panel mb-16">
        <div className="panel-body">
          <div style={{display: "flex", gap: 16, alignItems: "center", flexWrap: "wrap"}}>
            <div className="field" style={{margin: 0, minWidth: 250}}>
              <label style={{marginBottom: 4, display: "block"}}>Cliente</label>
              <select
                value={isAll ? "all" : (selectedClient?.id || "")}
                onChange={(e) => {
                  if (e.target.value === "all") {
                    setSelectedClient("all");
                  } else {
                    const c = clients.find(c => c.id === parseInt(e.target.value));
                    setSelectedClient(c);
                  }
                }}
              >
                <option value="all">— {t('all_clients')} —</option>
                {clients.map(c => (
                  <option key={c.id} value={c.id}>{c.name} ({c.code})</option>
                ))}
              </select>
            </div>
            <div style={{flex: 1}}></div>
            {clients.length > 0 && (
              <button className="btn btn-primary" onClick={() => setNewUserOpen(true)}>
                <span className="icon">{Icon.plus}</span>Nuovo Utente
              </button>
            )}
          </div>
        </div>
      </div>

      <div style={{fontSize: 13, color: "var(--text-3)", marginBottom: 12}}>
        {filteredUsers.length} utenti {!isAll && selectedClient && `per ${selectedClient.name}`}
      </div>

      <div className="panel">
        {filteredUsers.length === 0 ? (
          <div className="panel-body empty">
            <div style={{padding: "40px 20px", textAlign: "center", color: "var(--text-3)"}}>
              {clients.length === 0
                ? "Crea prima un cliente per poter aggiungere utenti."
                : "Nessun utente. Clicca \"Nuovo Utente\" per crearne uno."}
            </div>
          </div>
        ) : (
          <table className="data">
            <thead>
              <tr>
                <th>{t('username')}</th>
                <th>{t('full_name')}</th>
                {isAll && <th>{t('client')}</th>}
                <th>{t('email')}</th>
                <th>{t('status')}</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {filteredUsers.map(u => (
                <tr key={u.id}>
                  <td className="mono"><strong>{u.username}</strong></td>
                  <td>{u.full_name || "-"}</td>
                  {isAll && <td><Badge type="info">{u.client_name || "-"}</Badge></td>}
                  <td>{u.email || "-"}</td>
                  <td>{u.active ? <Badge type="ok" dot>attivo</Badge> : <Badge type="warn" dot>disattivo</Badge>}</td>
                  <td>
                    <button className="btn btn-secondary btn-sm" onClick={() => setEditingUser(u)}>{t('edit')}</button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>

      {newUserOpen && (
        <ClientNewUserWithClientModal
          clients={clients}
          onClose={() => setNewUserOpen(false)}
          onCreated={() => { setNewUserOpen(false); loadData(); }}
        />
      )}

      {editingUser && (
        <ClientEditUserModal
          user={editingUser}
          onClose={() => setEditingUser(null)}
          onSaved={() => { setEditingUser(null); loadData(); }}
        />
      )}
    </div>
  );
}

// Modal Nuovo Utente con selezione cliente
function ClientNewUserWithClientModal({ clients, onClose, onCreated }) {
  const [form, setForm] = useStateApp({
    username: "",
    password: "",
    full_name: "",
    email: "",
    client_id: clients[0]?.id || ""
  });
  const [saving, setSaving] = useStateApp(false);
  const [error, setError] = useStateApp("");

  const handleChange = (field, value) => {
    setForm(prev => ({ ...prev, [field]: value }));
  };

  const handleSubmit = async () => {
    if (!form.username || !form.password) {
      setError(t('username_password_required'));
      return;
    }
    if (!form.client_id) {
      setError("Seleziona un cliente");
      return;
    }

    setSaving(true);
    setError("");

    const token = localStorage.getItem("token");
    const res = await fetch(`${API_BASE}/users`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${token}`
      },
      body: JSON.stringify({
        ...form,
        role: "c2"
      })
    });
    const data = await res.json();

    if (data.success) {
      onCreated();
    } else {
      setError(data.error || "Errore creazione utente");
    }
    setSaving(false);
  };

  return (
    <Modal title="Nuovo Utente" size="md" onClose={onClose} footer={<>
      <button className="btn btn-secondary" onClick={onClose} disabled={saving}>{t('cancel')}</button>
      <button className="btn btn-primary" onClick={handleSubmit} disabled={saving}>
        {saving ? "Creazione..." : "Crea Utente"}
      </button>
    </>}>
      {error && (
        <div style={{marginBottom: 16, padding: "10px 12px", background: "rgba(220,53,69,0.1)", border: "1px solid rgba(220,53,69,0.3)", borderRadius: 4, color: "#dc3545", fontSize: 13}}>
          {error}
        </div>
      )}

      <div className="field" style={{marginBottom: 14}}>
        <label>Cliente *</label>
        <select value={form.client_id} onChange={(e) => handleChange("client_id", e.target.value)}>
          {clients.map(c => (
            <option key={c.id} value={c.id}>{c.name} ({c.code})</option>
          ))}
        </select>
      </div>

      <div className="field-grid">
        <div className="field">
          <label>Username *</label>
          <input type="text" value={form.username} onChange={(e) => handleChange("username", e.target.value)} placeholder="es. mario.rossi"/>
        </div>
        <div className="field">
          <label>Password *</label>
          <input type="password" value={form.password} onChange={(e) => handleChange("password", e.target.value)}/>
        </div>
        <div className="field">
          <label>Nome completo</label>
          <input type="text" value={form.full_name} onChange={(e) => handleChange("full_name", e.target.value)} placeholder="es. Mario Rossi"/>
        </div>
        <div className="field">
          <label>Email</label>
          <input type="email" value={form.email} onChange={(e) => handleChange("email", e.target.value)}/>
        </div>
      </div>
    </Modal>
  );
}

// Modal Gestione Utenti Cliente
function ClientUsersModal({ client, onClose }) {
  const [users, setUsers] = useStateApp([]);
  const [loading, setLoading] = useStateApp(true);
  const [newUserOpen, setNewUserOpen] = useStateApp(false);
  const [editingUser, setEditingUser] = useStateApp(null);

  const loadUsers = async () => {
    setLoading(true);
    const token = localStorage.getItem("token");
    const res = await fetch(`${API_BASE}/clients/${client.id}`, {
      headers: { Authorization: `Bearer ${token}` }
    }).then(r => r.json());

    if (res.success && res.users) {
      setUsers(res.users);
    }
    setLoading(false);
  };

  useEffectApp(() => {
    loadUsers();
  }, [client.id]);

  return (
    <Modal title={`Utenti di ${client.name}`} size="lg" onClose={onClose} footer={
      <button className="btn btn-secondary" onClick={onClose}>Chiudi</button>
    }>
      <div style={{marginBottom: 16, padding: 12, background: "var(--bg-2)", borderRadius: 6}}>
        <div style={{display: "flex", gap: 16, alignItems: "center"}}>
          <div><strong>Cliente:</strong> {client.name}</div>
          <div className="mono" style={{color: "var(--text-3)"}}>{client.code}</div>
        </div>
      </div>

      <div style={{display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 12}}>
        <h3 style={{margin: 0, fontSize: 14}}>Utenti ({users.length})</h3>
        <button className="btn btn-primary btn-sm" onClick={() => setNewUserOpen(true)}>
          <span className="icon">{Icon.plus}</span>Nuovo Utente
        </button>
      </div>

      {loading ? (
        <div style={{padding: 20, textAlign: "center", color: "var(--text-3)"}}>Caricamento...</div>
      ) : users.length === 0 ? (
        <div style={{padding: 30, textAlign: "center", color: "var(--text-3)", background: "var(--bg-2)", borderRadius: 6}}>
          Nessun utente per questo cliente.<br/>
          Clicca "Nuovo Utente" per crearne uno.
        </div>
      ) : (
        <table className="data">
          <thead>
            <tr>
              <th>{t('username')}</th>
              <th>{t('full_name')}</th>
              <th>{t('email')}</th>
              <th>{t('status')}</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {users.map(u => (
              <tr key={u.id}>
                <td className="mono"><strong>{u.username}</strong></td>
                <td>{u.full_name || "-"}</td>
                <td>{u.email || "-"}</td>
                <td>{u.active ? <Badge type="ok" dot>attivo</Badge> : <Badge type="warn" dot>disattivo</Badge>}</td>
                <td>
                  <button className="btn btn-secondary btn-sm" onClick={() => setEditingUser(u)}>{t('edit')}</button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      )}

      {newUserOpen && (
        <ClientNewUserModal
          clientId={client.id}
          onClose={() => setNewUserOpen(false)}
          onCreated={() => { setNewUserOpen(false); loadUsers(); }}
        />
      )}

      {editingUser && (
        <ClientEditUserModal
          user={editingUser}
          onClose={() => setEditingUser(null)}
          onSaved={() => { setEditingUser(null); loadUsers(); }}
        />
      )}
    </Modal>
  );
}

// Modal Nuovo Utente per Cliente
function ClientNewUserModal({ clientId, onClose, onCreated }) {
  const [form, setForm] = useStateApp({
    username: "",
    password: "",
    full_name: "",
    email: ""
  });
  const [saving, setSaving] = useStateApp(false);
  const [error, setError] = useStateApp("");

  const handleChange = (field, value) => {
    setForm(prev => ({ ...prev, [field]: value }));
  };

  const handleSubmit = async () => {
    if (!form.username || !form.password) {
      setError(t('username_password_required'));
      return;
    }

    setSaving(true);
    setError("");

    const token = localStorage.getItem("token");
    const res = await fetch(`${API_BASE}/users`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${token}`
      },
      body: JSON.stringify({
        ...form,
        client_id: clientId,
        role: "c2"
      })
    });
    const data = await res.json();

    if (data.success) {
      onCreated();
    } else {
      setError(data.error || "Errore creazione utente");
    }
    setSaving(false);
  };

  return (
    <Modal title="Nuovo Utente" size="md" onClose={onClose} footer={<>
      <button className="btn btn-secondary" onClick={onClose} disabled={saving}>{t('cancel')}</button>
      <button className="btn btn-primary" onClick={handleSubmit} disabled={saving}>
        {saving ? "Creazione..." : "Crea Utente"}
      </button>
    </>}>
      {error && (
        <div style={{marginBottom: 16, padding: "10px 12px", background: "rgba(220,53,69,0.1)", border: "1px solid rgba(220,53,69,0.3)", borderRadius: 4, color: "#dc3545", fontSize: 13}}>
          {error}
        </div>
      )}

      <div className="field-grid">
        <div className="field">
          <label>Username *</label>
          <input type="text" value={form.username} onChange={(e) => handleChange("username", e.target.value)} placeholder="es. mario.rossi"/>
        </div>
        <div className="field">
          <label>Password *</label>
          <input type="password" value={form.password} onChange={(e) => handleChange("password", e.target.value)}/>
        </div>
        <div className="field">
          <label>Nome completo</label>
          <input type="text" value={form.full_name} onChange={(e) => handleChange("full_name", e.target.value)} placeholder="es. Mario Rossi"/>
        </div>
        <div className="field">
          <label>Email</label>
          <input type="email" value={form.email} onChange={(e) => handleChange("email", e.target.value)}/>
        </div>
      </div>
    </Modal>
  );
}

// Modal Modifica Utente Cliente
function ClientEditUserModal({ user, onClose, onSaved }) {
  const [form, setForm] = useStateApp({
    full_name: user.full_name || "",
    email: user.email || "",
    password: "",
    active: user.active
  });
  const [saving, setSaving] = useStateApp(false);
  const [error, setError] = useStateApp("");

  const handleChange = (field, value) => {
    setForm(prev => ({ ...prev, [field]: value }));
  };

  const handleSubmit = async () => {
    setSaving(true);
    setError("");

    const token = localStorage.getItem("token");
    const body = { ...form };
    if (!body.password) delete body.password;

    const res = await fetch(`${API_BASE}/users/${user.id}`, {
      method: "PUT",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${token}`
      },
      body: JSON.stringify(body)
    });
    const data = await res.json();

    if (data.success) {
      onSaved();
    } else {
      setError(data.error || "Errore salvataggio");
    }
    setSaving(false);
  };

  return (
    <Modal title={t('edit_user')} size="md" onClose={onClose} footer={<>
      <button className="btn btn-secondary" onClick={onClose} disabled={saving}>{t('cancel')}</button>
      <button className="btn btn-primary" onClick={handleSubmit} disabled={saving}>
        {saving ? t('saving') : t('save')}
      </button>
    </>}>
      {error && (
        <div style={{marginBottom: 16, padding: "10px 12px", background: "rgba(220,53,69,0.1)", border: "1px solid rgba(220,53,69,0.3)", borderRadius: 4, color: "#dc3545", fontSize: 13}}>
          {error}
        </div>
      )}

      <div className="field-grid" style={{marginBottom: 14}}>
        <div className="field">
          <label>Username</label>
          <input type="text" value={user.username} disabled className="mono"/>
        </div>
        <div className="field">
          <label>{t('client')}</label>
          <input type="text" value={user.client_name || "-"} disabled/>
        </div>
      </div>

      <div className="field-grid">
        <div className="field">
          <label>Nome completo</label>
          <input type="text" value={form.full_name} onChange={(e) => handleChange("full_name", e.target.value)}/>
        </div>
        <div className="field">
          <label>Email</label>
          <input type="email" value={form.email} onChange={(e) => handleChange("email", e.target.value)}/>
        </div>
      </div>

      <div className="field" style={{marginTop: 14}}>
        <label>Nuova password (lascia vuoto per non modificare)</label>
        <input type="password" value={form.password} onChange={(e) => handleChange("password", e.target.value)} placeholder="••••••"/>
      </div>

      <div style={{marginTop: 16}}>
        <Checkbox checked={form.active} onChange={(v) => handleChange("active", v)} label="Utente attivo"/>
      </div>
    </Modal>
  );
}

Object.assign(window, { App, DisabledModule, AdminAllTenants, AdminAudit, AdminConfig, ClientClienti });
ReactDOM.createRoot(document.getElementById("root")).render(<App/>);
