// Shared UI primitives: Field, Select, MultiSelect (chip input), Modal, Toast.

const Field = ({ label, required, optional, hint, error, children }) => (
  <div className="field">
    <div className="field-label">
      {label}
      {required && <span className="req">*</span>}
      {optional && <span className="opt">(optional)</span>}
    </div>
    {children}
    {error ? <div className="field-error"><Icon name="alert" size={11} /> {error}</div>
      : hint ? <div className="field-hint">{hint}</div> : null}
  </div>
);

const TextInput = React.forwardRef(({ error, ...props }, ref) => (
  <input ref={ref} className={"input" + (error ? " error" : "")} {...props} />
));

const Select = ({ value, onChange, options, placeholder = "Select…", error, ...rest }) => (
  <select className={"select" + (error ? " error" : "")} value={value || ""}
          onChange={e => onChange(e.target.value)} {...rest}>
    <option value="" disabled>{placeholder}</option>
    {options.map(o => {
      const v = typeof o === "string" ? o : o.value;
      const l = typeof o === "string" ? o : o.label;
      return <option key={v} value={v}>{l}</option>;
    })}
  </select>
);

// Multi-select chip input with type-ahead suggestions
const MultiSelect = ({ values = [], onChange, options = [], placeholder = "Type to add…", allowCustom = false }) => {
  const [text, setText] = React.useState("");
  const [open, setOpen] = React.useState(false);
  const [activeIdx, setActiveIdx] = React.useState(0);
  const inputRef = React.useRef(null);

  const remaining = options.filter(o => !values.includes(o));
  const filtered = text.trim()
    ? remaining.filter(o => o.toLowerCase().includes(text.toLowerCase()))
    : remaining;

  const add = (v) => {
    if (!v) return;
    if (!values.includes(v)) onChange([...values, v]);
    setText("");
    setActiveIdx(0);
    inputRef.current?.focus();
  };
  const remove = (v) => onChange(values.filter(x => x !== v));

  const onKey = (e) => {
    if (e.key === "Backspace" && !text && values.length) {
      remove(values[values.length - 1]);
    } else if (e.key === "Enter") {
      e.preventDefault();
      if (filtered[activeIdx]) add(filtered[activeIdx]);
      else if (allowCustom && text.trim()) add(text.trim());
    } else if (e.key === "ArrowDown") {
      e.preventDefault();
      setActiveIdx(i => Math.min(i + 1, filtered.length - 1));
    } else if (e.key === "ArrowUp") {
      e.preventDefault();
      setActiveIdx(i => Math.max(i - 1, 0));
    } else if (e.key === "Escape") {
      setOpen(false);
    }
  };

  return (
    <div className="chip-suggest">
      <div className="chips-input" onClick={() => inputRef.current?.focus()}>
        {values.map(v => (
          <span key={v} className="chip">
            {v}
            <button onClick={(e) => { e.stopPropagation(); remove(v); }} aria-label={`Remove ${v}`}>
              <Icon name="x" size={10} />
            </button>
          </span>
        ))}
        <input
          ref={inputRef}
          className="chip-add-input"
          value={text}
          placeholder={values.length ? "" : placeholder}
          onChange={e => { setText(e.target.value); setOpen(true); setActiveIdx(0); }}
          onFocus={() => setOpen(true)}
          onBlur={() => setTimeout(() => setOpen(false), 120)}
          onKeyDown={onKey}
        />
      </div>
      {open && filtered.length > 0 && (
        <div className="chip-suggest-list">
          {filtered.slice(0, 8).map((o, i) => (
            <button
              key={o}
              data-active={i === activeIdx ? "true" : "false"}
              onMouseDown={(e) => { e.preventDefault(); add(o); }}
            >
              {o}
            </button>
          ))}
        </div>
      )}
    </div>
  );
};

const Modal = ({ open, onClose, title, sub, children, footer, size = "md" }) => {
  React.useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === "Escape") onClose?.(); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div className="modal-backdrop" onMouseDown={(e) => { if (e.target.classList.contains("modal-backdrop")) onClose?.(); }}>
      <div className={"modal" + (size === "lg" ? " lg" : "")}>
        <div className="modal-head">
          <div>
            <h3 className="modal-title">{title}</h3>
            {sub && <div className="modal-sub">{sub}</div>}
          </div>
          <button className="icon-btn" onClick={onClose}><Icon name="x" size={16} /></button>
        </div>
        {children}
        {footer && <div className="modal-foot">{footer}</div>}
      </div>
    </div>
  );
};

const Toast = ({ msg, onDone }) => {
  React.useEffect(() => {
    if (!msg) return;
    const t = setTimeout(onDone, 2400);
    return () => clearTimeout(t);
  }, [msg, onDone]);
  if (!msg) return null;
  return (
    <div className="toast">
      <span className="check"><Icon name="check" size={10} /></span>
      {msg}
    </div>
  );
};

const Avatar = ({ name, size = 30 }) => {
  const initials = name.split(" ").map(s => s[0]).join("").slice(0, 2).toUpperCase();
  return <div className="avatar" style={{ width: size, height: size, fontSize: size * 0.42 }}>{initials}</div>;
};

const ConfDot = ({ level }) => {
  const map = { public: "Public", internal: "Internal", restricted: "Restricted", confidential: "Confidential", "client confidential": "Confidential" };
  const dataLvl = level === "client confidential" ? "confidential" : level;
  return <span className="conf-dot" data-level={dataLvl}>{map[level] || level}</span>;
};

Object.assign(window, { Field, TextInput, Select, MultiSelect, Modal, Toast, Avatar, ConfDot });
