/* ============================================================
   ANAGRAFICA CLIENTI — Lista + ricerca fuzzy + CRUD
   ============================================================ */

/* ---- Normalizzazione + ricerca fuzzy ---------------------- */

// Pronunce delle lettere italiane → lettera singola
// "dierre" → "dr", "piemme" → "pm", "kappa" → "k", ecc.
const LETTER_PRONUNCIATIONS = [
  // ordine importante: prima le più lunghe per evitare match parziali
  ['cappa', 'k'],
  ['kappa', 'k'],
  ['acca', 'h'],
  ['ipsilon', 'y'],
  ['ypsilon', 'y'],
  ['doppiavu', 'w'],
  ['effe', 'f'],
  ['elle', 'l'],
  ['emme', 'm'],
  ['enne', 'n'],
  ['erre', 'r'],
  ['esse', 's'],
  ['gamma', 'g'],
  ['ics', 'x'],
  ['esce', 'x'],
  ['bi', 'b'],
  ['ci', 'c'],
  ['di', 'd'],
  ['gi', 'g'],
  ['pi', 'p'],
  ['ti', 't'],
  ['vi', 'v'],
  ['vu', 'v'],
  ['zeta', 'z'],
];

// Equivalenze comuni (forme societarie, brand)
const COMMON_REPLACEMENTS = [
  ['societaperazioni', 'spa'],
  ['societaresponsabilitalimitata', 'srl'],
  ['societanomecollettivo', 'snc'],
  ['societaaccomanditasemplice', 'sas'],
  ['tetrapak', 'tetrapack'],
];

// Sostituzioni di errori ortografici comuni
const SPELLING_VARIANTS = [
  ['ch', 'k'],
  ['cch', 'k'],
  ['cc', 'k'],
  ['qu', 'k'],
];

function applyReplacements(s, list) {
  let out = s;
  list.forEach(([a, b]) => {
    out = out.split(a).join(b);
  });
  return out;
}

function normalizeClient(s) {
  if (!s) return '';
  let n = s.toLowerCase()
    .normalize('NFD').replace(/[\u0300-\u036f]/g, '') // rimuove accenti
    .replace(/[^a-z0-9]/g, ''); // solo alfanumerici
  // Applica nell'ordine: pronunce lettere → forme societarie → varianti ortografiche
  n = applyReplacements(n, LETTER_PRONUNCIATIONS);
  n = applyReplacements(n, COMMON_REPLACEMENTS);
  n = applyReplacements(n, SPELLING_VARIANTS);
  return n;
}

// Distanza di Levenshtein
function levenshtein(a, b) {
  if (a === b) return 0;
  if (!a.length) return b.length;
  if (!b.length) return a.length;
  const m = [];
  for (let i = 0; i <= b.length; i++) m[i] = [i];
  for (let j = 0; j <= a.length; j++) m[0][j] = j;
  for (let i = 1; i <= b.length; i++) {
    for (let j = 1; j <= a.length; j++) {
      m[i][j] = b[i-1] === a[j-1]
        ? m[i-1][j-1]
        : Math.min(m[i-1][j-1]+1, m[i][j-1]+1, m[i-1][j]+1);
    }
  }
  return m[b.length][a.length];
}

// Ricerca fuzzy clienti
function fuzzySearchClienti(clienti, query) {
  const q = normalizeClient(query);
  if (!q || q.length < 2) return [];

  const results = [];
  for (const c of clienti) {
    // Normalizza al volo applicando anche le pronunce delle lettere
    const norm = normalizeClient(c.ragione_sociale);
    // Match diretto (substring)
    if (norm.includes(q)) {
      results.push({ ...c, score: 0 });
      continue;
    }
    // Match con Levenshtein (per typo)
    if (Math.abs(norm.length - q.length) <= 3) {
      const dist = levenshtein(norm, q);
      if (dist <= 2) {
        results.push({ ...c, score: dist + 1 });
        continue;
      }
    }
    // Match parziale per parole lunghe
    if (q.length >= 2 && norm.length >= q.length) {
      for (let i = 0; i <= norm.length - q.length; i++) {
        const sub = norm.slice(i, i + q.length);
        const dist = levenshtein(sub, q);
        if (dist <= 1) {
          results.push({ ...c, score: dist + 2 });
          break;
        }
      }
    }
  }
  return results.sort((a, b) => a.score - b.score).slice(0, 20);
}

/* ---- Pannello principale Anagrafica ----------------------- */
function AnagraficaClienti({ clienti, setClienti, zone, clienteCat, toast, role, setBookings, setArchive }) {
  const vp = useViewport();
  const [q, setQ] = useState('');
  const [editing, setEditing] = useState(undefined); // undefined=closed, null=new, obj=edit
  const [confirm, setConfirm] = useState(null);
  const [hover, setHover] = useState(null);

  // Rubrica: lettera attiva + risultati caricati on-demand dal DB
  const [letter, setLetter] = useState('A');
  const [pageClients, setPageClients] = useState([]);
  const [pageLoading, setPageLoading] = useState(false);
  const [searchResults, setSearchResults] = useState(null); // null = non in ricerca
  const [searching, setSearching] = useState(false);

  const LETTERS = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','#'];

  // Carica i clienti della lettera attiva (quando cambia lettera e non si sta cercando)
  useEffect(() => {
    if (q.trim()) return; // in ricerca: non caricare per lettera
    let cancelled = false;
    setPageLoading(true);
    (async () => {
      try {
        const data = await window.DataAPI.listClientiByLetter(letter);
        if (!cancelled) setPageClients(data);
      } catch (e) { console.error('listClientiByLetter', e); if(!cancelled) setPageClients([]); }
      finally { if (!cancelled) setPageLoading(false); }
    })();
    return () => { cancelled = true; };
  }, [letter, q]);

  // Ricerca globale sul DB (debounced)
  useEffect(() => {
    const term = q.trim();
    if (!term) { setSearchResults(null); return; }
    let cancelled = false;
    setSearching(true);
    const timer = setTimeout(async () => {
      try {
        const data = await window.DataAPI.searchClienti(term);
        if (!cancelled) setSearchResults(data);
      } catch (e) { console.error('searchClienti', e); if(!cancelled) setSearchResults([]); }
      finally { if (!cancelled) setSearching(false); }
    }, 300);
    return () => { cancelled = true; clearTimeout(timer); };
  }, [q]);

  // Lista da mostrare: risultati ricerca se in ricerca, altrimenti la pagina della lettera
  const list = q.trim()
    ? (searchResults || [])
    : pageClients.slice().sort((a, b) => a.ragione_sociale.localeCompare(b.ragione_sociale));

  // Ricarica la pagina/lettera corrente (dopo save/delete)
  const reloadPage = async () => {
    if (q.trim()) {
      const data = await window.DataAPI.searchClienti(q.trim()).catch(()=>[]);
      setSearchResults(data);
    } else {
      const data = await window.DataAPI.listClientiByLetter(letter).catch(()=>[]);
      setPageClients(data);
    }
  };

  const save = async (c) => {
    const isNew = editing===null;
    if (window.SF_CONFIG.useSupabase) {
      try {
        const exists = !!c.id && (pageClients.some(x => x.id === c.id) || (searchResults||[]).some(x=>x.id===c.id));
        if (exists) {
          await window.DataAPI.update('clienti', c.id, {
            ragione_sociale: c.ragione_sociale,
            zona_id: c.zona_id || null,
            client_category_id: c.client_category_id || null,
          });
          // FIX: propaga il nuovo nome alle prenotazioni collegate (bookings + archivio)
          try {
            const cli = window.DataAPI.client();
            if (cli && c.id) {
              await cli.from('bookings').update({ cliente: c.ragione_sociale }).eq('cliente_id', c.id);
              await cli.from('bookings_archive').update({ cliente: c.ragione_sociale }).eq('cliente_id', c.id);
            }
          } catch (pe) { console.error('propaga nome cliente', pe); }
          setBookings?.(prev => prev.map(b => b.cliente_id === c.id ? { ...b, cliente: c.ragione_sociale } : b));
          setArchive?.(prev => prev.map(b => b.cliente_id === c.id ? { ...b, cliente: c.ragione_sociale } : b));
        } else {
          const row = await window.DataAPI.insert('clienti', {
            ragione_sociale: c.ragione_sociale,
            zona_id: c.zona_id || null,
            client_category_id: c.client_category_id || null,
          });
          c = { ...c, id: row.id, ragione_sociale_norm: row.ragione_sociale_norm };
          // Se il nuovo cliente inizia con una lettera diversa, spostati su quella
          const firstChar = (c.ragione_sociale||'').trim().charAt(0).toUpperCase();
          if (/[A-Z]/.test(firstChar) && firstChar !== letter && !q.trim()) setLetter(firstChar);
        }
      } catch(e) { toast('Errore salvataggio cliente'); console.error(e); return; }
    }
    // aggiorna anche la cache globale (per prenotazioni)
    setClienti(prev => prev.some(x=>x.id===c.id) ? prev.map(x=>x.id===c.id?c:x) : [...prev, c]);
    setEditing(undefined);
    toast(isNew ? 'Cliente creato' : 'Cliente aggiornato');
    reloadPage();
    window.LogAPI?.logEvent(isNew ? 'client.created' : 'client.updated', {
      entity_type: 'client', entity_id: c.id,
      title: isNew ? 'Nuovo cliente in anagrafica' : 'Cliente modificato',
      description: c.ragione_sociale,
      metadata: { ragione_sociale: c.ragione_sociale, zona_id: c.zona_id, client_category_id: c.client_category_id },
    });
  };

  const remove = async (c) => {
    if (window.SF_CONFIG.useSupabase) {
      try { await window.DataAPI.remove('clienti', c.id); }
      catch(e) { toast('Errore eliminazione'); console.error(e); return; }
    }
    setClienti(prev => prev.filter(x => x.id !== c.id));
    setPageClients(prev => prev.filter(x => x.id !== c.id));
    setSearchResults(prev => prev ? prev.filter(x => x.id !== c.id) : prev);
    setConfirm(null);
    toast(`Cliente "${c.ragione_sociale}" eliminato`);
    window.LogAPI?.logEvent('client.deleted', {
      entity_type: 'client', entity_id: c.id,
      title: 'Cliente rimosso dall\'anagrafica',
      description: c.ragione_sociale,
      metadata: { ragione_sociale: c.ragione_sociale },
    });
  };

  const PG = 'minmax(0,2fr) minmax(0,1.3fr) minmax(0,1.3fr) 92px';

  return (
    <div className="scroll" style={{ flex:1, minWidth:0, overflowY:'auto', overflowX:'hidden', padding: vp.isMobile?'16px 12px 30px':'24px 30px 40px' }}>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:14, gap:14, flexWrap:'wrap' }}>
        <div style={{ minWidth:0, flex:1 }}>
          <h2 style={{ margin:0, fontFamily:'var(--font-display)', fontSize: vp.isMobile?17:19, fontWeight:800 }}>Anagrafica clienti</h2>
          <div style={{ fontSize:12.5, color:'var(--ink-3)', marginTop:2 }}>
            Rubrica per iniziale {!vp.isMobile && '· cerca per trovare in tutto il database'}
          </div>
        </div>
        {!vp.isMobile && <Btn icon="plus" onClick={()=>setEditing(null)}>Nuovo cliente</Btn>}
      </div>

      <div style={{ position:'relative', marginBottom:14, maxWidth: vp.isMobile?'none':480 }}>
        <Icon name="search" size={18} style={{ position:'absolute', left:13, top:'50%', transform:'translateY(-50%)', color:'var(--ink-4)' }} />
        <input value={q} onChange={e=>setQ(e.target.value)} placeholder="Cerca cliente…"
          style={{ width:'100%', padding:'11px 14px 11px 40px', fontSize:14, borderRadius:'var(--r-md)', border:'1.5px solid var(--line)', background:'var(--surface-2)', outline:'none' }}
          onFocus={e=>e.target.style.borderColor='var(--red)'} onBlur={e=>e.target.style.borderColor='var(--line)'} />
        {q && (
          <button onClick={()=>setQ('')} style={{ position:'absolute', right:10, top:'50%', transform:'translateY(-50%)', padding:6, color:'var(--ink-4)' }}>
            <Icon name="x" size={16} />
          </button>
        )}
      </div>

      {/* Rubrica: barra lettere (nascosta durante la ricerca) */}
      {!q.trim() && (
        <div style={{ display:'flex', flexWrap:'wrap', gap:4, marginBottom:14 }}>
          {LETTERS.map(L => {
            const active = L === letter;
            return (
              <button key={L} onClick={()=>setLetter(L)}
                style={{ minWidth: vp.isMobile?28:32, height: vp.isMobile?28:32, padding:0, borderRadius:8,
                  fontSize:12.5, fontWeight:800, cursor:'pointer', transition:'.12s',
                  border:'1.5px solid '+(active?'var(--red)':'var(--line)'),
                  background: active?'var(--red)':'var(--surface)',
                  color: active?'#fff':'var(--ink-3)' }}>
                {L}
              </button>
            );
          })}
        </div>
      )}

      {/* Indicatore stato caricamento */}
      {(pageLoading || searching) && (
        <div style={{ fontSize:12.5, color:'var(--ink-3)', fontWeight:600, marginBottom:10 }}>
          {searching ? 'Ricerca in corso…' : 'Caricamento…'}
        </div>
      )}
      {!pageLoading && !searching && (
        <div style={{ fontSize:12.5, color:'var(--ink-4)', fontWeight:600, marginBottom:10 }}>
          {q.trim()
            ? `${list.length} ${list.length===1?'risultato':'risultati'} in tutto il database`
            : `${list.length} clienti con iniziale "${letter}"`}
        </div>
      )}

      {vp.isMobile ? (
        /* MOBILE: card list */
        <div style={{ display:'flex', flexDirection:'column', gap:10, paddingBottom:80 }}>
          {list.length === 0 ? (
            <div style={{ padding:'50px 0', textAlign:'center', color:'var(--ink-3)', fontWeight:600 }}>
              {q ? 'Nessun cliente trovato' : 'Nessun cliente in anagrafica'}
            </div>
          ) : list.map(c => {
            const zona = zone.find(z => z.id === c.zona_id);
            const cat = clienteCat.find(cc => cc.id === c.client_category_id);
            return (
              <button key={c.id} onClick={()=>setEditing(c)}
                style={{ textAlign:'left', background:'var(--surface)', border:'1px solid var(--line)', borderRadius:'var(--r-lg)',
                  padding:'14px 15px', display:'flex', flexDirection:'column', gap:6, boxShadow:'var(--sh-1)' }}>
                <div style={{ fontSize:14, fontWeight:800, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>
                  {c.ragione_sociale}
                </div>
                <div style={{ display:'flex', gap:12, fontSize:12, color:'var(--ink-3)', fontWeight:600, flexWrap:'wrap' }}>
                  <span><Icon name="pin" size={11} style={{ marginRight:3, verticalAlign:'-1px' }} />
                    {zona ? zona.nome : '—'}
                  </span>
                  <span><Icon name="tag" size={11} style={{ marginRight:3, verticalAlign:'-1px' }} />
                    {cat ? cat.nome : '—'}
                  </span>
                </div>
              </button>
            );
          })}

          {/* FAB Nuovo cliente */}
          <button onClick={()=>setEditing(null)}
            style={{ position:'fixed', right:16, bottom:'calc(90px + env(safe-area-inset-bottom, 0))', zIndex:20,
              width:56, height:56, borderRadius:'50%', background:'var(--red)', color:'#fff',
              boxShadow:'0 8px 22px -6px rgba(200,16,46,.55)',
              display:'flex', alignItems:'center', justifyContent:'center' }}>
            <Icon name="plus" size={22} stroke={2.2} />
          </button>
        </div>
      ) : (
        <div style={{ background:'var(--surface)', border:'1px solid var(--line)', borderRadius:'var(--r-lg)', overflow:'hidden', boxShadow:'var(--sh-1)' }}>
          <div style={{ display:'grid', gridTemplateColumns:PG, gap:14, padding:'13px 22px', background:'var(--surface-2)',
            borderBottom:'1px solid var(--line)', fontSize:11, fontWeight:800, color:'var(--ink-3)', textTransform:'uppercase', letterSpacing:'.04em' }}>
            <span>Ragione sociale</span><span>Zona</span><span>Categoria</span><span style={{ textAlign:'right' }}>Azioni</span>
          </div>
          {list.length === 0 ? (
            <div style={{ padding:'50px 0', textAlign:'center', color:'var(--ink-3)', fontWeight:600 }}>
              {q ? 'Nessun cliente trovato' : 'Nessun cliente in anagrafica'}
            </div>
          ) : list.map((c, i) => {
            const zona = zone.find(z => z.id === c.zona_id);
            const cat = clienteCat.find(cc => cc.id === c.client_category_id);
            return (
              <div key={c.id} onMouseEnter={()=>setHover(c.id)} onMouseLeave={()=>setHover(null)}
                style={{ display:'grid', gridTemplateColumns:PG, gap:14, padding:'13px 22px',
                  borderBottom: i<list.length-1?'1px solid var(--line-2)':'none', alignItems:'center',
                  background: hover===c.id?'var(--surface-2)':'transparent' }}>
                <div style={{ fontSize:14, fontWeight:700, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>
                  {c.ragione_sociale}
                </div>
                <span style={{ fontSize:13, color: zona?'var(--ink-2)':'var(--ink-4)', fontWeight:600 }}>
                  {zona ? zona.nome : '— non impostata'}
                </span>
                <span style={{ fontSize:13, color: cat?'var(--ink-2)':'var(--ink-4)', fontWeight:600 }}>
                  {cat ? cat.nome : '— non impostata'}
                </span>
                <div style={{ display:'flex', gap:6, justifySelf:'end', opacity: hover===c.id?1:0, transition:'opacity .12s' }}>
                  <button onClick={()=>setEditing(c)} title="Modifica" style={iconBtn}><Icon name="edit" size={15} /></button>
                  {role==='admin' && (
                    <button onClick={()=>setConfirm(c)} title="Elimina" style={{ ...iconBtn, color:'var(--red)', borderColor:'var(--red-tint-2)' }}><Icon name="x" size={15} /></button>
                  )}
                </div>
              </div>
            );
          })}
        </div>
      )}

      {editing !== undefined && (
        <ClienteEditModal cliente={editing} zone={zone} clienteCat={clienteCat}
          onClose={()=>setEditing(undefined)} onSave={save} />
      )}
      {confirm && (
        <ConfirmDialog title="Eliminare il cliente?"
          message={<>Stai per eliminare <b>{confirm.ragione_sociale}</b> dall'anagrafica.</>}
          confirmLabel="Elimina cliente"
          onConfirm={()=>remove(confirm)} onClose={()=>setConfirm(null)} />
      )}
    </div>
  );
}

/* ---- Modal create/edit cliente ---------------------------- */
function ClienteEditModal({ cliente, zone, clienteCat, onClose, onSave, prefillName }) {
  const isNew = !cliente;
  const [ragione, setRagione] = useState(cliente?.ragione_sociale || prefillName || '');
  const [zonaId, setZonaId] = useState(cliente?.zona_id || '');
  const [catId, setCatId] = useState(cliente?.client_category_id || '');
  const valid = ragione.trim().length >= 2;

  const submit = () => {
    if (!valid) return;
    onSave({
      id: cliente?.id || 'tmp-'+Date.now(),
      ragione_sociale: ragione.trim(),
      zona_id: zonaId || null,
      client_category_id: catId || null,
    });
  };

  const zonaList = (zone || []).slice().sort((a, b) => a.nome.localeCompare(b.nome));

  return (
    <ModalShell onClose={onClose} width={480}
      title={isNew?'Nuovo cliente':'Modifica cliente'}
      subtitle={isNew?'Solo 3 campi — semplice e veloce':cliente.ragione_sociale}>
      <div style={{ display:'flex', flexDirection:'column', gap:16 }}>
        <Field label="Ragione sociale" required>
          <input value={ragione} onChange={e=>setRagione(e.target.value)}
            placeholder="es. Tetrapak Italia S.r.l." style={inputStyle} autoFocus />
        </Field>
        <Field label="Zona di consegna">
          <div style={{ position:'relative' }}>
            <select value={zonaId} onChange={e=>setZonaId(e.target.value)}
              style={{ ...inputStyle, appearance:'none', paddingRight:34 }}>
              <option value="">— Nessuna zona —</option>
              {zonaList.map(z => <option key={z.id} value={z.id}>{z.nome}</option>)}
            </select>
            <Icon name="chevDown" size={16} style={{ position:'absolute', right:12, top:'50%', transform:'translateY(-50%)', color:'var(--ink-3)', pointerEvents:'none' }} />
          </div>
        </Field>
        <Field label="Categoria cliente">
          <div style={{ position:'relative' }}>
            <select value={catId} onChange={e=>setCatId(e.target.value)}
              style={{ ...inputStyle, appearance:'none', paddingRight:34 }}>
              <option value="">— Nessuna categoria —</option>
              {(clienteCat || []).map(c => <option key={c.id} value={c.id}>{c.nome}</option>)}
            </select>
            <Icon name="chevDown" size={16} style={{ position:'absolute', right:12, top:'50%', transform:'translateY(-50%)', color:'var(--ink-3)', pointerEvents:'none' }} />
          </div>
        </Field>
      </div>
      <div style={{ display:'flex', gap:12, marginTop:22 }}>
        <Btn variant="ghost" full onClick={onClose}>Annulla</Btn>
        <Btn full icon="check" onClick={submit} disabled={!valid}>{isNew?'Crea cliente':'Salva modifiche'}</Btn>
      </div>
    </ModalShell>
  );
}

Object.assign(window, { AnagraficaClienti, ClienteEditModal, fuzzySearchClienti, normalizeClient });