// ListItemDetailModal — opens when you tap any item in a v2 list.
//
// Handles both catalog items (where node.productId resolves to a real
// product) AND custom items (the ad-hoc blob carrying name/brand/price/
// image/sourceUrl). Surfaces the rich detail the user expects when they
// click on something they care about: the picture at full size, the
// product info, source-URL link, editable notes, pick toggle if it's
// under a slot, vote widget, and a delete action.
//
// Edit mode (custom items only) lets the user rename, change brand, edit
// price, replace the image, and edit description inline. Catalog items
// expose a "View full product" button that hands off to the existing
// ProductCard panel for retailer-search + comparison.

const { useState: _lds, useEffect: _lde, useRef: _ldr } = React;

// One canonical set of status icons + metadata, matching the heart/cart/check
// icons in the topbar. Use this map everywhere status is shown so we stay
// consistent. The DB enum is the legacy `want`/`need`/`have`; the labels are
// the user-facing Loved/Getting/Have vocabulary.
const STATUS_META = {
  want: { value: 'want', label: 'Loved',   tone: 'loved',   ariaLabel: 'Loved' },
  need: { value: 'need', label: 'Getting', tone: 'getting', ariaLabel: 'Getting' },
  have: { value: 'have', label: 'Have',    tone: 'have',    ariaLabel: 'Have' },
};
const STATUS_ORDER = ['want', 'need', 'have'];

// Single-source-of-truth icon paths — identical to the topbar SVGs so a
// user learns the visual vocabulary once. `size` controls width+height.
function StatusIcon({ status, size = 14, filled = true, className = '' }) {
  const s = status || 'want';
  if (s === 'want') {
    return (
      <svg className={className} width={size} height={size} viewBox="0 0 24 24" fill={filled ? 'currentColor' : 'none'} stroke="currentColor" strokeWidth={filled ? 1.6 : 1.8} strokeLinejoin="round" strokeLinecap="round" aria-hidden="true">
        <path d="M12 21.3 C 12 21.3, 3.5 15.5, 3.5 9.5 C 3.5 6.2, 6 4, 8.6 4 C 10.5 4, 11.5 5.4, 12 6.5 C 12.5 5.4, 13.5 4, 15.4 4 C 18 4, 20.5 6.2, 20.5 9.5 C 20.5 15.5, 12 21.3, 12 21.3 Z"/>
      </svg>
    );
  }
  if (s === 'need') {
    return (
      <svg className={className} width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinejoin="round" strokeLinecap="round" aria-hidden="true">
        <path d="M7 10V8a5 5 0 0110 0v2"/>
        <path d="M5 10h14l-1.2 9.5a2 2 0 01-2 1.5H8.2a2 2 0 01-2-1.5z"/>
        <path d="M9 14l2 2 4-4" strokeWidth="2"/>
      </svg>
    );
  }
  // 'have'
  return (
    <svg className={className} width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinejoin="round" strokeLinecap="round" aria-hidden="true">
      <rect x="3" y="3" width="18" height="18" rx="5.5"/>
      <path d="M7.5 12.4 L10.6 15.5 L16.8 8.8" strokeWidth="2.4"/>
    </svg>
  );
}

window.StatusIcon = StatusIcon;
window.STATUS_META = STATUS_META;
window.STATUS_ORDER = STATUS_ORDER;

function ListItemDetailModal({
  node,
  productMap,
  votes,
  comments,                    // [{ id, author_id, body, created_at }] for this node
  nameFor,                     // (userId) → 'You' | displayName | 'someone'
  myUserId,
  isUnderSlot,
  rootKind,
  claim,                       // existing registry claim if any
  onClose,
  onUpdate,                    // (patch) → persist node edits
  onDelete,                    // () → delete node
  onVote,                      // (vote: 'up'|'down'|null) → toggle vote
  onAddComment,                // (body) → post comment
  onDeleteComment,             // (commentId) → delete comment
  onOpenFullProduct,           // (product) → switch to the catalog ProductCard
}) {
  if (!node) return null;

  // Resolve the display fields from either catalog or custom shape.
  const product = node.productId && productMap ? productMap[node.productId] : null;
  const isCatalog = !!product;
  const isCustom = !product && !!node.custom;

  const name     = product ? product.name      : (node.custom && node.custom.name)      || node.name || 'Item';
  const brand    = product ? product.brand     : (node.custom && node.custom.brand)     || '';
  const image    = product ? product.img       : (node.custom && node.custom.image)     || '';
  // Gallery: catalog items have product.gallery; custom items get the
  // list collected at paste-link time (read from localStorage by
  // nodeFromRow). Falls back to [image] so we always render something.
  const galleryRaw = product
    ? (product.gallery && product.gallery.length ? product.gallery : (image ? [image] : []))
    : ((node.custom && Array.isArray(node.custom.gallery) && node.custom.gallery.length)
        ? node.custom.gallery
        : (image ? [image] : []));
  // De-dupe so the same URL doesn't show up twice (catalog + custom can
  // both list the primary).
  const gallery = Array.from(new Set(galleryRaw)).slice(0, 12);
  const [galIdx, setGalIdx] = _lds(0);
  _lde(() => { setGalIdx(0); }, [node.id]);
  const hasMultiImages = gallery.length > 1;
  const activeImage = gallery[Math.min(galIdx, gallery.length - 1)] || image;
  const price    = product ? product.price     : (node.custom && node.custom.price);
  const currency = product ? (product.currency || 'AUD') : (node.custom && node.custom.currency) || 'AUD';
  const description = product
    ? (product.why || product.description || '')
    : (node.custom && node.custom.description) || '';
  const sourceUrl   = product ? null : ((node.custom && node.custom.sourceUrl) || '');

  // Edit mode — drafts mirror the live values until commit/cancel.
  const [editing, setEditing] = _lds(false);
  const [draftName,  setDraftName ] = _lds(name);
  const [draftBrand, setDraftBrand] = _lds(brand || '');
  const [draftPrice, setDraftPrice] = _lds(price != null ? String(price) : '');
  const [draftDesc,  setDraftDesc ] = _lds(description || '');
  const [imgUploading, setImgUploading] = _lds(false);
  const fileRef = _ldr(null);

  _lde(() => {
    setDraftName(name);
    setDraftBrand(brand || '');
    setDraftPrice(price != null ? String(price) : '');
    setDraftDesc(description || '');
  }, [node.id]);

  // Notes — separate from edit mode, always inline-editable.
  const [notesDraft, setNotesDraft] = _lds(node.notes || '');
  _lde(() => { setNotesDraft(node.notes || ''); }, [node.id, node.notes]);
  const commitNotes = () => {
    const v = (notesDraft || '').trim();
    if (v === (node.notes || '')) return;
    onUpdate({ notes: v });
  };

  // Esc to close
  _lde(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);

  const commitEdits = () => {
    const patch = {};
    const newName = (draftName || '').trim();
    if (newName && newName !== name) patch.name = newName;
    // For custom items, also write into the custom blob.
    if (isCustom) {
      const customPatch = {};
      if (newName && newName !== (node.custom.name || ''))  customPatch.name = newName;
      const trimmedBrand = draftBrand.trim();
      if (trimmedBrand !== (node.custom.brand || ''))       customPatch.brand = trimmedBrand;
      const priceNum = draftPrice.trim() ? Number(draftPrice) : null;
      if (priceNum !== node.custom.price)                   customPatch.price = priceNum;
      const trimmedDesc = draftDesc.trim();
      if (trimmedDesc !== (node.custom.description || ''))  customPatch.description = trimmedDesc;
      if (Object.keys(customPatch).length > 0) patch.custom = customPatch;
    }
    if (Object.keys(patch).length > 0) onUpdate(patch);
    setEditing(false);
  };

  const handleImageReplace = async (file) => {
    if (!file) return;
    setImgUploading(true);
    try {
      // uploadOrEncodeImage is a global helper (defined in tweaks-panel.jsx?).
      const res = typeof uploadOrEncodeImage === 'function'
        ? await uploadOrEncodeImage(file)
        : null;
      if (res && res.url) {
        const customPatch = { ...(node.custom || {}), image: res.url };
        onUpdate({ custom: customPatch });
      }
    } finally {
      setImgUploading(false);
    }
  };

  // Vote state for the in-modal widget — also resolve voter names so
  // partners know who voted what (hover the count to see).
  const nodeVotes = (votes || []).filter(v => v.node_id === node.id);
  const upCount   = nodeVotes.filter(v => v.vote === 'up').length;
  const downCount = nodeVotes.filter(v => v.vote === 'down').length;
  const myVote    = nodeVotes.find(v => v.voter_id === myUserId)?.vote || null;
  const upNames   = nodeVotes.filter(v => v.vote === 'up')
    .map(v => (nameFor ? nameFor(v.voter_id) : 'someone')).join(', ');
  const downNames = nodeVotes.filter(v => v.vote === 'down')
    .map(v => (nameFor ? nameFor(v.voter_id) : 'someone')).join(', ');

  return (
    <>
      <div className="lid-scrim" onClick={onClose} />
      <div className="lid-modal" role="dialog" aria-modal="true" aria-label={name}>
        <button type="button" className="lid-close" aria-label="Close" onClick={onClose}>
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M6 6l12 12M6 18L18 6"/></svg>
        </button>
        <div className="lid-body">
          {/* Big image — fills the left half on desktop, full width on phones.
              When there are multiple images (from a richer og-fetch result or
              catalog gallery), show prev/next arrows + a counter + a thumbnail
              strip below. */}
          <div className="lid-imagewrap">
            {activeImage
              ? <SmartImage src={activeImage} alt={name} fallbackLabel={brand || name} />
              : <div className="lid-image-empty">No image</div>}
            {hasMultiImages && (
              <>
                <button
                  type="button"
                  className="lid-gallery-arrow lid-gallery-arrow--prev"
                  onClick={() => setGalIdx(i => (i - 1 + gallery.length) % gallery.length)}
                  aria-label="Previous image"
                >
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M15 18l-6-6 6-6"/></svg>
                </button>
                <button
                  type="button"
                  className="lid-gallery-arrow lid-gallery-arrow--next"
                  onClick={() => setGalIdx(i => (i + 1) % gallery.length)}
                  aria-label="Next image"
                >
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M9 18l6-6-6-6"/></svg>
                </button>
                <div className="lid-gallery-counter">{galIdx + 1} / {gallery.length}</div>
              </>
            )}
            {isCustom && editing && (
              <>
                <button
                  type="button"
                  className="lid-image-replace"
                  onClick={() => fileRef.current && fileRef.current.click()}
                  disabled={imgUploading}
                >
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M3 7 h4 l2 -2 h6 l2 2 h4 v12 H3z"/><circle cx="12" cy="13" r="3.5"/></svg>
                  <span>{imgUploading ? 'Uploading…' : 'Replace photo'}</span>
                </button>
                <input
                  ref={fileRef}
                  type="file"
                  accept="image/*"
                  capture="environment"
                  style={{ display: 'none' }}
                  onChange={(e) => { const f = e.target.files && e.target.files[0]; if (f) { handleImageReplace(f); e.target.value = ''; } }}
                />
              </>
            )}
            {claim && (
              <div className="lid-claim-chip">
                <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round"><path d="M5 12l5 5L20 7"/></svg>
                Claimed by {claim.buyer_name || 'someone'}
              </div>
            )}
            {/* Thumbnail strip — visible whenever there are 2+ images.
                Clicking a thumb jumps the main image to it. */}
            {hasMultiImages && (
              <div className="lid-gallery-thumbs">
                {gallery.map((src, i) => (
                  <button
                    key={i}
                    type="button"
                    className={`lid-gallery-thumb${i === galIdx ? ' is-active' : ''}`}
                    onClick={() => setGalIdx(i)}
                    aria-label={`Image ${i + 1}`}
                  >
                    <SmartImage src={src} alt="" fallbackLabel="" />
                  </button>
                ))}
              </div>
            )}
          </div>

          {/* Right column — info + actions */}
          <div className="lid-content">
            {editing ? (
              <>
                <label className="lid-field">
                  <span>Brand</span>
                  <input type="text" value={draftBrand} onChange={(e) => setDraftBrand(e.target.value)} placeholder="Optional" />
                </label>
                <label className="lid-field">
                  <span>Name</span>
                  <input type="text" autoFocus value={draftName} onChange={(e) => setDraftName(e.target.value)} />
                </label>
                <label className="lid-field">
                  <span>Price</span>
                  <input type="number" inputMode="decimal" value={draftPrice} onChange={(e) => setDraftPrice(e.target.value)} placeholder="—" min="0" step="0.01" />
                </label>
                <label className="lid-field">
                  <span>Description</span>
                  <textarea rows={4} value={draftDesc} onChange={(e) => setDraftDesc(e.target.value)} />
                </label>
                <div className="lid-edit-actions">
                  <button type="button" className="btn btn-ghost" onClick={() => { setEditing(false); }} style={{ width: 'auto', padding: '10px 16px' }}>
                    <span>Cancel</span>
                  </button>
                  <button type="button" className="btn" onClick={commitEdits} style={{ width: 'auto', padding: '10px 18px' }}>
                    <span>Save changes</span><span className="arrow">→</span>
                  </button>
                </div>
              </>
            ) : (
              <>
                {brand && <div className="lid-brand">{brand}</div>}
                <h2 className="lid-name">{name}</h2>
                {price != null && (
                  <div className="lid-price">{currency === 'AUD' ? 'A$' : '$'}{Number(price).toLocaleString()}</div>
                )}

                {/* Loved / Getting / Have — the canonical status for any
                    saved item. Uses the same SVG icons as the topbar so the
                    visual vocabulary is consistent across the whole site. */}
                <div className="lid-statuspills" role="radiogroup" aria-label="Item status">
                  {STATUS_ORDER.map(value => {
                    const s = STATUS_META[value];
                    const isOn = (node.status || 'want') === value;
                    return (
                      <button
                        key={value}
                        type="button"
                        role="radio"
                        aria-checked={isOn}
                        className={`lid-statuspill lid-statuspill--${s.tone}${isOn ? ' is-on' : ''}`}
                        onClick={() => onUpdate({ status: value })}
                      >
                        <StatusIcon status={value} size={15} />
                        <span>{s.label}</span>
                      </button>
                    );
                  })}
                </div>

                {/* Status row — vote widget + pick toggle + registry chip */}
                <div className="lid-status">
                  {onVote && myUserId && (
                    <div className="lid-vote" role="group" aria-label="Vote on this item">
                      <button
                        type="button"
                        className={`lid-vote-btn lid-vote-btn--up${myVote === 'up' ? ' is-on' : ''}`}
                        onClick={() => onVote(myVote === 'up' ? null : 'up')}
                        title={upNames ? `Yes: ${upNames}` : 'Vote yes'}
                        aria-label={upNames ? `Vote yes — ${upNames}` : 'Vote yes'}
                      >
                        <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M7 22V11h3l4-9c.8 0 1.5.4 2 1 .5.7.5 1.5.3 2.3L15 11h6c1.1 0 2 .9 2 2v3c0 .3-.1.6-.2.9l-3.3 5.4c-.4.6-1 1-1.7 1H7z"/></svg>
                        {upNames && <span className="lid-vote-names">{upNames}</span>}
                      </button>
                      <button
                        type="button"
                        className={`lid-vote-btn lid-vote-btn--down${myVote === 'down' ? ' is-on' : ''}`}
                        onClick={() => onVote(myVote === 'down' ? null : 'down')}
                        title={downNames ? `No: ${downNames}` : 'Vote no'}
                        aria-label={downNames ? `Vote no — ${downNames}` : 'Vote no'}
                      >
                        <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" style={{ transform: 'rotate(180deg)' }}><path d="M7 22V11h3l4-9c.8 0 1.5.4 2 1 .5.7.5 1.5.3 2.3L15 11h6c1.1 0 2 .9 2 2v3c0 .3-.1.6-.2.9l-3.3 5.4c-.4.6-1 1-1.7 1H7z"/></svg>
                        {downNames && <span className="lid-vote-names">{downNames}</span>}
                      </button>
                    </div>
                  )}
                  {isUnderSlot && (
                    <button
                      type="button"
                      className={`lid-pick${node.picked ? ' is-on' : ''}`}
                      onClick={() => onUpdate({ picked: !node.picked })}
                    >
                      <span className="lid-pick-box">
                        {node.picked && <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12l5 5L20 7"/></svg>}
                      </span>
                      <span>{node.picked ? 'Picked' : 'Pick this one'}</span>
                    </button>
                  )}
                  {rootKind === 'registry' && (
                    <button
                      type="button"
                      className={`lid-reg${node.inRegistry ? ' is-on' : ''}`}
                      onClick={() => onUpdate({ inRegistry: !node.inRegistry })}
                    >
                      <span>{node.inRegistry ? '✓ On registry' : '+ Add to registry'}</span>
                    </button>
                  )}
                </div>

                {description && (
                  <div className="lid-section">
                    <div className="lid-section-h">{isCatalog ? 'About this product' : 'Description'}</div>
                    <p className="lid-desc">{description}</p>
                  </div>
                )}

                {(() => {
                  // Sanitise sourceUrl against javascript:/data:/etc. schemes.
                  // If unsafe, show the raw text rather than a clickable link.
                  const safeSrc = window.MR && window.MR.safeUrl ? window.MR.safeUrl(sourceUrl) : null;
                  if (!sourceUrl) return null;
                  if (!safeSrc) {
                    return (
                      <div className="lid-section">
                        <div className="lid-section-h">Source</div>
                        <span style={{ fontSize: 12, color: 'var(--ink-3)' }}>{sourceUrl}</span>
                      </div>
                    );
                  }
                  return (
                    <div className="lid-section">
                      <div className="lid-section-h">Source</div>
                      <a className="lid-source" href={safeSrc} target="_blank" rel="noopener noreferrer">
                        <span>{(() => { try { return new URL(safeSrc).hostname; } catch { return safeSrc; } })()}</span>
                        <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M10 14L21 3M21 3h-7M21 3v7"/></svg>
                      </a>
                    </div>
                  );
                })()}

                {/* Comments thread — anyone with access to this list can
                    post. Each comment shows author + time. Author can delete
                    their own (RLS enforces). */}
                <CommentsThread
                  comments={comments || []}
                  nameFor={nameFor}
                  myUserId={myUserId}
                  onAdd={onAddComment}
                  onDelete={onDeleteComment}
                />

                <div className="lid-actions">
                  {isCustom && (
                    <button type="button" className="btn btn-ghost" onClick={() => setEditing(true)} style={{ width: 'auto', padding: '11px 18px' }}>
                      <span>Edit details</span><span className="arrow">✎</span>
                    </button>
                  )}
                  {isCatalog && onOpenFullProduct && (
                    <button type="button" className="btn btn-ghost" onClick={() => onOpenFullProduct(product)} style={{ width: 'auto', padding: '11px 18px' }}>
                      <span>View full product</span><span className="arrow">↗</span>
                    </button>
                  )}
                  <button type="button" className="btn lid-delete" onClick={() => {
                    if (window.confirm(`Remove "${name}" from this list?`)) { onDelete(); onClose(); }
                  }} style={{ width: 'auto', padding: '11px 18px' }}>
                    <span>Remove from list</span><span className="arrow">×</span>
                  </button>
                </div>
              </>
            )}
          </div>
        </div>
      </div>
    </>
  );
}

// CommentsThread — a small chat-style thread on a single node. Each row
// shows author, relative time, body, and a delete button on your own
// comments. The composer at the bottom is a single textarea with cmd-Enter
// to send.
function CommentsThread({ comments, nameFor, myUserId, onAdd, onDelete }) {
  const [draft, setDraft] = _lds('');
  const [busy, setBusy] = _lds(false);
  const [err, setErr] = _lds('');
  const sorted = (comments || []).slice().sort((a, b) => new Date(a.created_at) - new Date(b.created_at));
  const submit = async (e) => {
    if (e) e.preventDefault();
    const v = (draft || '').trim();
    if (!v || busy) return;
    setBusy(true); setErr('');
    const res = await onAdd(v);
    setBusy(false);
    if (res && res.ok) { setDraft(''); return; }
    // Surface a readable message. Most common cause: the comments table
    // doesn't exist yet (the user hasn't run the SQL migration).
    let msg = res && res.reason ? res.reason : 'Could not post — try again?';
    if (/list_node_comments/.test(msg) || /relation .* does not exist/i.test(msg)) {
      msg = "Comments table isn't set up yet. Run the comments SQL migration in Supabase (see admin/migrations/2026-06-list-node-comments.sql).";
    }
    setErr(msg);
  };
  // Pretty relative time — "just now", "5m", "2h", "3d", or short date.
  const relTime = (iso) => {
    if (!iso) return '';
    const ms = Date.now() - new Date(iso).getTime();
    const s = Math.floor(ms / 1000);
    if (s < 60) return 'just now';
    if (s < 3600) return `${Math.floor(s / 60)}m`;
    if (s < 86400) return `${Math.floor(s / 3600)}h`;
    if (s < 604800) return `${Math.floor(s / 86400)}d`;
    try { return new Date(iso).toLocaleDateString(undefined, { month: 'short', day: 'numeric' }); }
    catch { return ''; }
  };
  // Avatar initial — first letter of the resolved name.
  const initial = (uid) => {
    const n = nameFor ? nameFor(uid) : '?';
    return (n || '?').trim().charAt(0).toUpperCase();
  };
  return (
    <div className="lid-section lid-section--comments">
      {sorted.length > 0 && (
        <div className="lid-comments">
          {sorted.map(c => (
            <div key={c.id} className={`lid-comment${c.author_id === myUserId ? ' is-mine' : ''}`}>
              <div className="lid-comment-avatar" aria-hidden="true">{initial(c.author_id)}</div>
              <div className="lid-comment-body">
                <div className="lid-comment-head">
                  <span className="lid-comment-author">{nameFor ? nameFor(c.author_id) : 'someone'}</span>
                  <span className="lid-comment-time">{relTime(c.created_at)}</span>
                  {c.author_id === myUserId && onDelete && (
                    <button
                      type="button"
                      className="lid-comment-delete"
                      onClick={() => {
                        if (window.confirm('Delete this comment?')) onDelete(c.id);
                      }}
                      aria-label="Delete comment"
                      title="Delete"
                    >×</button>
                  )}
                </div>
                <div className="lid-comment-text">{c.body}</div>
              </div>
            </div>
          ))}
        </div>
      )}
      <form className="lid-comment-composer" onSubmit={submit}>
        <textarea
          rows={2}
          placeholder="Add a comment…"
          value={draft}
          onChange={(e) => { setDraft(e.target.value); if (err) setErr(''); }}
          onKeyDown={(e) => { if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') { e.preventDefault(); submit(); } }}
        />
        <button
          type="submit"
          className="btn"
          disabled={!draft.trim() || busy}
          style={{ width: 'auto', padding: '8px 14px' }}
        >
          <span>{busy ? 'Posting…' : 'Post'}</span>
        </button>
      </form>
      {err && (
        <div className="lid-comment-err" role="alert">
          ⚠ {err}
        </div>
      )}
    </div>
  );
}

window.ListItemDetailModal = ListItemDetailModal;
window.CommentsThread = CommentsThread;
