// ─────────────────────────────────────────────
// DO_Fields_Rating.jsx
// Interactive emoji rating widget for the APP runtime
//
// Loaded in: do-app/index.html  (before DO_DetailView.jsx)
// Used by:   RenderObject in DO_DetailView.jsx as:
//   case "rating": return <RatingField obj={obj} record={record} onChange={onChange} onForceSave={onForceSave} />;
//
// obj config properties:
//   ratingEmoji  — emoji character            (default '⭐')
//   ratingScale  — max steps 3–10             (default 5)
//   field        — DB field name to read/write
//   label        — display label text
//   labelpos     — 'top' | 'left' | 'none'    (default 'top')
//   labelalign   — 'left' | 'center' | 'right'(default 'left')
//
// Value stored in DB: numeric string e.g. "3"
// Clicking same value again deselects (stores "")
//
// Save strategy:
//   onForceSave(field, value) is called with the new values directly.
//   This bypasses the React setState async timing issue — recordRef.current
//   would still hold the old value if we called onForceSave() with no args.
// ─────────────────────────────────────────────

function RatingField({ obj, record, onChange, onForceSave }) {
  const emoji = obj.ratingEmoji || '⭐';
  const scale = Number(obj.ratingScale || 5);

  // Resolve stored numeric value
  const raw     = record?.[obj.field];
  const current = raw ? Number(raw) : 0;

  const [hover, setHover] = React.useState(0);

  function handleClick(idx) {
    if (!onChange) return;
    // Clicking current value deselects
    const newVal    = idx === current ? 0 : idx;
    const stored    = newVal === 0 ? '' : String(newVal);
    // 1. Update React state (async)
    onChange(obj.field, stored);
    // 2. Force immediate DB save — pass field+value directly so
    //    handleForceSave doesn't need to wait for recordRef to update
    if (onForceSave) onForceSave(obj.field, stored);
  }

  // ── Label ──
  const labelpos   = obj.labelpos   || 'top';
  const labelalign = obj.labelalign || 'left';
  const showLabel  = labelpos !== 'none' && obj.label;

  const labelEl = showLabel ? (
    <span style={{
      display:       'block',
      fontSize:      10,
      fontWeight:    700,
      textTransform: 'uppercase',
      letterSpacing: '0.07em',
      color:         '#94a3b8',
      textAlign:     labelalign,
      marginBottom:  labelpos === 'top' ? 5 : 0,
      marginRight:   labelpos === 'left' ? 8 : 0,
      whiteSpace:    'nowrap',
    }}>
      {obj.label}
    </span>
  ) : null;

  // ── Rating items ──
  const ratingEl = (
    <div style={{ display:'flex', alignItems:'center', gap:2, flexWrap:'wrap' }}>
      {Array.from({ length: scale }, (_, i) => {
        const idx    = i + 1;
        const active = hover ? idx <= hover : idx <= current;
        const isHov  = hover === idx;

        return (
          <span
            key={idx}
            title={String(idx)}
            onMouseEnter={() => setHover(idx)}
            onMouseLeave={() => setHover(0)}
            onClick={() => handleClick(idx)}
            style={{
              fontSize:   24,
              cursor:     'pointer',
              userSelect: 'none',
              display:    'inline-block',
              transition: 'transform 0.1s ease, opacity 0.1s ease',
              transform:  isHov ? 'scale(1.25)' : 'scale(1)',
              opacity:    active ? 1 : 0.25,
            }}
          >
            {emoji}
          </span>
        );
      })}

      {/* Numeric readout when value is set and not hovering */}
      {current > 0 && !hover && (
        <span style={{ fontSize:11, color:'#94a3b8', marginLeft:6, fontStyle:'italic' }}>
          {current} / {scale}
        </span>
      )}

      {/* Hover preview readout */}
      {hover > 0 && (
        <span style={{ fontSize:11, color:'#2563eb', marginLeft:6, fontStyle:'italic' }}>
          {hover} / {scale}
        </span>
      )}
    </div>
  );

  // Top label (default)
  if (labelpos !== 'left') {
    return (
      <div style={{ marginBottom:2 }}>
        {labelEl}
        {ratingEl}
      </div>
    );
  }

  // Left / inline label
  return (
    <div style={{ display:'flex', alignItems:'center', marginBottom:2 }}>
      {labelEl}
      {ratingEl}
    </div>
  );
}
