// Kundväljaren i Steg 1.
//
// Tidigare var det ett vanligt <input list="..."> med en <datalist>. Den
// listan ritas av webbläsaren och går varken att styla eller fylla med något
// mer än namnet: man såg inte org.nr, inte hur många offerter kunden har, och
// det fanns ingen väg att säga "det här är en ny kund". Dessutom såg den olika
// ut i Chrome, Edge och Firefox, och gick inte att bläddra i med tangentbordet
// på ett förutsägbart sätt.
//
// Den här väljaren ritar listan själv: träffar på namn, org.nr och ort, med
// kundens historik på raden, och ett tydligt alternativ för att lägga upp ett
// nytt företag. Piltangenter, Enter och Esc fungerar som man förväntar sig.

function CustomerPicker({ value, customers = [], onPick, onChange, placeholder, autofokus = false }) {
  const [text, setText] = React.useState(value || '');
  const [open, setOpen] = React.useState(false);
  const [aktiv, setAktiv] = React.useState(0);
  const senasteExterna = React.useRef(value);
  const vardRef = React.useRef(null);
  const faltRef = React.useRef(null);
  const listRef = React.useRef(null);

  // Byter man offert ska fältet följa med — men inte medan man skriver i det.
  React.useEffect(() => {
    if (value !== senasteExterna.current) {
      setText(value || '');
      senasteExterna.current = value;
    }
  }, [value]);

  React.useEffect(() => { if (autofokus && faltRef.current) faltRef.current.focus(); }, [autofokus]);

  // Klick utanför stänger listan.
  React.useEffect(() => {
    if (!open) return;
    const ut = (e) => { if (vardRef.current && !vardRef.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', ut);
    return () => document.removeEventListener('mousedown', ut);
  }, [open]);

  const norm = (s) => String(s || '').toLowerCase().replace(/\s+/g, ' ').trim();
  const siffror = (s) => String(s || '').replace(/[^0-9]/g, '');

  const sokt = norm(text);
  const traffar = React.useMemo(() => {
    // Arkiverade kunder är med — märkta, och sist. Doldes de helt skapade
    // autosparet ändå kopplingen till dem i bakgrunden, och kunden låg kvar
    // arkiverad med en ny offert som ingen hittade. Nu syns det i listan, och
    // väljer man en arkiverad kund tas den tillbaka när offerten sparas.
    const lista = customers;
    if (!sokt) {
      // Utan söktext: de kunder som varit aktuella senast ligger överst.
      return lista.filter(c => !c.archived_at).slice().sort((a, b) =>
        String(b.senaste_offert || '').localeCompare(String(a.senaste_offert || ''))).slice(0, 8);
    }
    const bara = siffror(sokt);
    return lista
      .map(c => {
        const namn = norm(c.name);
        let poang = -1;
        if (namn.startsWith(sokt)) poang = 0;
        else if (namn.includes(sokt)) poang = 1;
        else if (bara.length >= 4 && siffror(c.org_nr).includes(bara)) poang = 2;
        else if (norm(c.contact).includes(sokt)) poang = 3;
        return { c, poang };
      })
      .filter(x => x.poang >= 0)
      .sort((a, b) => (a.c.archived_at ? 1 : 0) - (b.c.archived_at ? 1 : 0) || a.poang - b.poang || norm(a.c.name).localeCompare(norm(b.c.name)))
      .slice(0, 8)
      .map(x => x.c);
  }, [customers, sokt]);

  const exaktTraff = customers.some(c => norm(c.name) === sokt);
  const visaNy = sokt.length > 1 && !exaktTraff;
  const rader = traffar.length + (visaNy ? 1 : 0);

  React.useEffect(() => { setAktiv(0); }, [sokt]);

  // Håll den markerade raden synlig när man bläddrar med piltangenterna.
  React.useEffect(() => {
    if (!open || !listRef.current) return;
    const cpRad = listRef.current.querySelector('[data-aktiv="true"]');
    if (cpRad && cpRad.scrollIntoView) cpRad.scrollIntoView({ block: 'nearest' });
  }, [aktiv, open]);

  const skriv = (s) => {
    setText(s);
    senasteExterna.current = s;
    setOpen(true);
    onChange(s);
  };

  const valj = (c) => {
    setText(c.name);
    senasteExterna.current = c.name;
    setOpen(false);
    onChange(c.name);
    if (onPick) onPick(c);
    if (faltRef.current) faltRef.current.focus();
  };

  const nyKund = () => {
    const namn = text.trim();
    setOpen(false);
    onChange(namn);
    // Namnet skickas med: föräldern har inte hunnit få det nya värdet via
    // onChange än när det här körs.
    if (onPick) onPick(null, namn);
    if (faltRef.current) faltRef.current.focus();
  };

  const tangent = (e) => {
    if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
      e.preventDefault();
      if (!open) { setOpen(true); return; }
      if (!rader) return;
      setAktiv(n => (e.key === 'ArrowDown' ? (n + 1) % rader : (n - 1 + rader) % rader));
    } else if (e.key === 'Enter') {
      if (!open || !rader) return;
      e.preventDefault();
      if (aktiv < traffar.length) valj(traffar[aktiv]); else nyKund();
    } else if (e.key === 'Escape') {
      if (open) { e.preventDefault(); e.stopPropagation(); setOpen(false); }
    } else if (e.key === 'Tab') {
      setOpen(false);
    }
  };

  const sammanfatta = (c) => {
    const bitar = [];
    if (c.org_nr) bitar.push(c.org_nr);
    const n = Number(c.antal_offerter) || 0;
    if (n) bitar.push(n + (n === 1 ? ' offert' : ' offerter'));
    if (Number(c.antal_vantar)) bitar.push(Number(c.antal_vantar) + ' väntar på svar');
    else if (c.senaste_offert) bitar.push('senast ' + c.senaste_offert);
    if (!n) bitar.push('ingen offert än');
    return bitar.join(' · ');
  };

  const initialer = (namn) => String(namn || '?').split(/\s+/)
    .filter(o => o && !/^(ab|hb|kb|&|och|i)$/i.test(o))
    .slice(0, 2).map(o => o[0].toUpperCase()).join('');

  return (
    <div ref={vardRef} style={{ position: 'relative' }}>
      {/* Ikonen och cpRensa-krysset ligger i en egen ruta runt själva fältet.
          Låg de i ytterrutan skulle "top:50%" räknas mot hela väljaren med
          den öppna listan — och då hamnar de mitt i träfflistan. */}
      <div style={{ position: 'relative' }}>
      <input
        ref={faltRef}
        value={text}
        placeholder={placeholder}
        role="combobox"
        aria-expanded={open}
        aria-autocomplete="list"
        aria-controls="kundvaljare-lista"
        aria-activedescendant={open && rader ? 'kundrad-' + aktiv : undefined}
        autoComplete="off"
        onChange={e => skriv(e.target.value)}
        onFocus={() => setOpen(true)}
        onKeyDown={tangent}
        style={{ ...cpFalt, borderColor: open ? 'var(--ulab-blue)' : 'var(--border-strong)',
                 boxShadow: open ? '0 0 0 3px rgba(0,117,189,.16)' : 'none' }}
      />
      <span aria-hidden="true" style={cpIkon}>
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
          <circle cx="11" cy="11" r="7"/><path d="m20 20-3.2-3.2"/>
        </svg>
      </span>
      {text ? (
        <button type="button" aria-label="Rensa företagsnamnet" style={cpRensa}
          onClick={() => { skriv(''); if (faltRef.current) faltRef.current.focus(); }}>×</button>
      ) : null}
      </div>

      {open ? (
        <div style={cpPanel}>
          <div style={cpPanelHuvud}>
            <span>{sokt ? (traffar.length ? 'Träffar i kundregistret' : 'Ingen träff i registret') : 'Senast använda'}</span>
            <span style={{ color: 'var(--fg-muted)' }}>
              {traffar.length ? traffar.length + (traffar.length === 1 ? ' kund' : ' kunder') : ''}
            </span>
          </div>
          <div id="kundvaljare-lista" ref={listRef} role="listbox" aria-label="Kunder" style={{ maxHeight: 'min(316px, 34vh)', overflowY: 'auto' }}>
            {traffar.map((c, n) => (
              <button
                key={c.id}
                id={'kundrad-' + n}
                type="button"
                role="option"
                aria-selected={n === aktiv}
                data-aktiv={n === aktiv}
                onMouseEnter={() => setAktiv(n)}
                onMouseDown={e => e.preventDefault()}
                onClick={() => valj(c)}
                style={{ ...cpRad, background: n === aktiv ? 'var(--ulab-cream)' : 'transparent' }}
              >
                <span style={cpAvatar}>{initialer(c.name)}</span>
                <span style={{ flex: 1, minWidth: 0 }}>
                  <span style={cpRadNamn}>{c.name}</span>
                  <span style={cpRadMeta}>{sammanfatta(c)}</span>
                </span>
                {c.archived_at ? (
                  <span style={{ ...cpFlagga, color: 'var(--fg-muted)', background: 'var(--ulab-cool-grey)', borderColor: 'var(--border-strong)' }}
                    title="Kunden är arkiverad. Väljer du den tas den tillbaka i kundlistan när offerten sparas.">Arkiverad — tas tillbaka</span>
                ) : Number(c.antal_forsenade) ? (
                  <span style={cpFlagga}>Bevakning förfallen</span>
                ) : null}
              </button>
            ))}

            {!traffar.length && !sokt ? (
              <div style={cpTomText}>Kundregistret är tomt än. Skriv företagets namn så läggs det upp.</div>
            ) : null}

            {visaNy ? (
              <button
                id={'kundrad-' + traffar.length}
                type="button"
                role="option"
                aria-selected={aktiv === traffar.length}
                data-aktiv={aktiv === traffar.length}
                onMouseEnter={() => setAktiv(traffar.length)}
                onMouseDown={e => e.preventDefault()}
                onClick={nyKund}
                style={{ ...cpRad, borderTop: traffar.length ? '1px solid var(--border)' : 'none',
                         background: aktiv === traffar.length ? 'var(--ulab-cream)' : 'transparent' }}
              >
                <span style={{ ...cpAvatar, background: '#fdf0ee', color: 'var(--ulab-coral)', fontSize: 17 }}>+</span>
                <span style={{ flex: 1, minWidth: 0 }}>
                  <span style={{ ...cpRadNamn, color: 'var(--ulab-coral)' }}>Lägg upp ”{text.trim()}” som ny kund</span>
                  <span style={cpRadMeta}>Fyll i org.nr och kontaktuppgifter under Fler uppgifter</span>
                </span>
              </button>
            ) : null}
          </div>
          <div style={cpPanelFot}>
            <kbd style={cpTangentStil}>↑</kbd><kbd style={cpTangentStil}>↓</kbd> bläddra
            <kbd style={{ ...cpTangentStil, marginLeft: 10 }}>Enter</kbd> välj
            <kbd style={{ ...cpTangentStil, marginLeft: 10 }}>Esc</kbd> stäng
          </div>
        </div>
      ) : null}
    </div>
  );
}

const cpFalt = {
  fontFamily: 'var(--font-sans)', fontSize: 14, padding: '10px 34px 10px 36px',
  border: '1px solid var(--border-strong)', borderRadius: 'var(--radius-button)',
  background: '#fff', color: 'var(--ulab-navy)', width: '100%', boxSizing: 'border-box', outline: 'none',
  transition: 'border-color .12s, box-shadow .12s',
};
const cpIkon = {
  position: 'absolute', left: 12, top: '50%', transform: 'translateY(-50%)',
  color: 'var(--fg-subtle)', display: 'flex', pointerEvents: 'none',
};
const cpRensa = {
  position: 'absolute', right: 6, top: '50%', transform: 'translateY(-50%)',
  width: 26, height: 26, border: 'none', background: 'transparent', cursor: 'pointer',
  color: 'var(--fg-muted)', fontSize: 17, lineHeight: 1, borderRadius: 'var(--radius-button)',
};
const cpPanel = {
  position: 'absolute', top: 'calc(100% + 6px)', left: 0, right: 0, zIndex: 60,
  background: '#fff', border: '1px solid var(--border-strong)',
  borderRadius: 'var(--radius-card)', boxShadow: 'var(--shadow-modal)', overflow: 'hidden',
};
const cpPanelHuvud = {
  display: 'flex', justifyContent: 'space-between', gap: 12,
  padding: '9px 14px', background: 'var(--ulab-cool-grey)',
  borderBottom: '1px solid var(--border)', fontSize: 11, fontWeight: 700,
  letterSpacing: '.12em', textTransform: 'uppercase', color: 'var(--fg-muted)',
};
const cpRad = {
  display: 'flex', alignItems: 'center', gap: 12, width: '100%', textAlign: 'left',
  border: 'none', padding: '10px 14px', cursor: 'pointer', fontFamily: 'var(--font-sans)',
};
const cpAvatar = {
  flex: 'none', width: 32, height: 32, borderRadius: 'var(--radius-button)',
  background: '#e8f1f8', color: 'var(--ulab-navy)', display: 'flex',
  alignItems: 'center', justifyContent: 'center', fontSize: 12, fontWeight: 700,
};
const cpRadNamn = {
  display: 'block', fontSize: 14, fontWeight: 600, color: 'var(--ulab-navy)',
  whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
};
const cpRadMeta = {
  display: 'block', fontSize: 12, color: 'var(--fg-muted)', marginTop: 2,
  whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
};
const cpFlagga = {
  flex: 'none', fontSize: 11, fontWeight: 600, color: '#8a5a12',
  background: '#fff7ed', border: '1px solid #f0b866', borderRadius: 'var(--radius-pill)',
  padding: '3px 9px', whiteSpace: 'nowrap',
};
const cpTomText = { padding: '16px 14px', fontSize: 13, color: 'var(--fg-muted)' };
const cpPanelFot = {
  display: 'flex', alignItems: 'center', gap: 4, padding: '8px 14px',
  borderTop: '1px solid var(--border)', background: 'var(--ulab-cool-grey)',
  fontSize: 11, color: 'var(--fg-subtle)',
};
const cpTangentStil = {
  fontFamily: 'var(--font-sans)', fontSize: 10, border: '1px solid var(--border-strong)',
  borderRadius: 3, padding: '1px 5px', marginRight: 3, background: '#fff', color: 'var(--fg-muted)',
};

window.CustomerPicker = CustomerPicker;
