// Primitives — Card, Btn, Chip, Input, Dot, Bar, plus filigree decorations.

const { useState, useEffect, useRef, useCallback, useMemo, useContext, createContext } = React;

const Card = ({ title, eyebrow, tag, action, children, className = '', headClass = '', bodyClass = '', style, soft, bare }) => {
  const cls = ['card'];
  if (soft) cls[0] = 'card-soft';
  if (bare) cls[0] = 'card-bare';
  return (
    <div className={`${cls.join(' ')} ${className}`} style={style}>
      {(title || tag || action) && (
        <div className={`card-head ${headClass}`}>
          <div className="card-title">
            {eyebrow}
            <span>{title}</span>
          </div>
          <div className="flex ica ig-8">
            {tag && <span className="card-tag">{tag}</span>}
            {action}
          </div>
        </div>
      )}
      <div className={`card-body ${bodyClass}`}>{children}</div>
    </div>
  );
};

const Btn = ({ children, primary, ghost, danger, heal, sm, lg, onClick, disabled, className = '', style, iconOnly, title }) => {
  const cls = ['btn'];
  if (primary) cls.push('primary');
  if (ghost) cls.push('ghost');
  if (danger) cls.push('danger');
  if (heal) cls.push('heal');
  if (sm) cls.push('sm');
  if (lg) cls.push('lg');
  if (iconOnly) cls.push('icon-only');
  return (
    <button className={`${cls.join(' ')} ${className}`} onClick={onClick} disabled={disabled} style={style} title={title}>
      {children}
    </button>
  );
};

const IconBtn = ({ name, onClick, danger, title, size = 14 }) => (
  <button className={`btn-icon ${danger ? 'danger' : ''}`} onClick={onClick} title={title}>
    <Icon name={name} size={size} />
  </button>
);

const Chip = ({ children, active, fill, muted, sm, lg, color, onClick, style, className = '' }) => {
  const cls = ['chip'];
  if (active) cls.push('active');
  if (fill) cls.push('fill');
  if (muted) cls.push('muted');
  if (sm) cls.push('sm');
  if (lg) cls.push('lg');
  if (color) cls.push(color);
  return (
    <span className={`${cls.join(' ')} ${className}`} onClick={onClick} style={style}>
      {children}
    </span>
  );
};

const Dot = ({ on, expert, color, lg, sm, onClick, title, style }) => {
  const cls = ['dot'];
  if (on) cls.push('on');
  if (expert) cls.push('expert');
  if (color) cls.push(color);
  if (lg) cls.push('lg');
  if (sm) cls.push('sm');
  return <span className={cls.join(' ')} onClick={onClick} title={title} style={style}/>;
};

const Slot = ({ full, used, onClick, title }) => {
  const cls = ['slot'];
  if (full) cls.push('full');
  if (used) cls.push('used');
  return <span className={cls.join(' ')} onClick={onClick} title={title}/>;
};

const Bar = ({ pct = 0, color, lg, thin, style }) => {
  const cls = ['bar'];
  if (color) cls.push(color);
  if (lg) cls.push('lg');
  if (thin) cls.push('thin');
  return (
    <div className={cls.join(' ')} style={style}>
      <div className="bar-fill" style={{ width: `${Math.max(0, Math.min(100, pct))}%` }}/>
    </div>
  );
};

const Field = ({ label, children, style }) => (
  <div className="field" style={style}>
    <div className="field-label">{label}</div>
    {children}
  </div>
);

const Divider = ({ gold, style }) => <div className={`divider ${gold ? 'gold' : ''}`} style={style}/>;

const SectionHeader = ({ title, eyebrow, action }) => (
  <div className="section-h">
    <h2>{title}</h2>
    {eyebrow && <span className="section-eyebrow">— {eyebrow}</span>}
    <div className="igrow"/>
    {action}
  </div>
);

// Shield-shaped stat (for AC and similar in combat panel)
const ShieldStat = ({ value, label, color = 'var(--gold-0)' }) => (
  <div className="shield-stat" title={label}>
    <svg className="shield-bg" viewBox="0 0 80 92" fill="none">
      <path d="M40 4 L74 14 L74 48 C 74 64 60 80 40 88 C 20 80 6 64 6 48 V14 Z"
        fill="var(--bg-2)" stroke={color} strokeWidth="1.5"/>
      <path d="M40 9 L70 17 L70 48 C 70 62 58 76 40 83 C 22 76 10 62 10 48 V17 Z"
        fill="none" stroke={color} strokeWidth="0.6" opacity="0.5"/>
    </svg>
    <div className="ss-v">{value}</div>
    <div className="ss-k">{label}</div>
  </div>
);

// Numeric input with +/- stepper
const Stepper = ({ value, onChange, min = 0, max = 999, step = 1, w = 60 }) => (
  <div className="flex ica" style={{
    background: 'var(--bg-2)',
    border: '1px solid var(--line-1)',
    borderRadius: 'var(--radius)',
    height: 30,
    overflow: 'hidden',
  }}>
    <button className="btn-icon" style={{ height: 28, width: 28, borderRadius: 0 }}
      onClick={() => onChange(Math.max(min, value - step))}>
      <Icon name="minus" size={12}/>
    </button>
    <input
      type="number" value={value}
      onChange={(e) => {
        const v = parseInt(e.target.value, 10);
        if (!isNaN(v)) onChange(Math.max(min, Math.min(max, v)));
      }}
      style={{
        width: w, background: 'transparent', border: 'none', textAlign: 'center',
        color: 'var(--ink-0)', fontFamily: 'var(--font-display)', fontSize: 14, fontWeight: 600, outline: 'none',
      }}
    />
    <button className="btn-icon" style={{ height: 28, width: 28, borderRadius: 0 }}
      onClick={() => onChange(Math.min(max, value + step))}>
      <Icon name="plus" size={12}/>
    </button>
  </div>
);

// Decorative ornamental flourish (used in card headers, between sections)
const Flourish = ({ width = 80, color = 'var(--gold-0)' }) => (
  <svg viewBox="0 0 80 12" width={width} height="12" fill="none" stroke={color} strokeWidth="0.9" aria-hidden="true">
    <path d="M2 6 H30 M50 6 H78"/>
    <path d="M40 6 L36 2 M40 6 L36 10 M40 6 L44 2 M40 6 L44 10"/>
    <circle cx="40" cy="6" r="1.5" fill={color}/>
    <circle cx="30" cy="6" r="0.8" fill={color}/>
    <circle cx="50" cy="6" r="0.8" fill={color}/>
  </svg>
);

// Illuminated manuscript-style corner ornament.
// Render 4× at each corner of a frame to box content with filigree.
const CornerOrnament = ({ size = 36, color = 'var(--gold-0)', rotate = 0 }) => (
  <svg width={size} height={size} viewBox="0 0 40 40" fill="none"
    stroke={color} strokeWidth="1.1" strokeLinecap="round" strokeLinejoin="round"
    style={{ transform: `rotate(${rotate}deg)`, display: 'block' }} aria-hidden="true">
    {/* Main outer arc */}
    <path d="M0 4 L18 4 M4 0 L4 18"/>
    {/* Inner curl that hooks into a spiral */}
    <path d="M4 18 C 4 12 8 10 12 10 C 16 10 18 14 18 18"/>
    <path d="M18 4 C 12 4 10 8 10 12 C 10 16 14 18 18 18"/>
    {/* Tiny ornament dots */}
    <circle cx="4" cy="4" r="2.2" fill={color}/>
    <circle cx="18" cy="18" r="1.4" fill={color} opacity="0.6"/>
    <circle cx="12" cy="12" r="0.9" fill={color} opacity="0.5"/>
    {/* Decorative leaf */}
    <path d="M18 4 C 22 4 24 6 24 10" strokeWidth="0.8" opacity="0.8"/>
    <path d="M4 18 C 4 22 6 24 10 24" strokeWidth="0.8" opacity="0.8"/>
    {/* Small star/flourish */}
    <path d="M22 22 L23 24 L25 25 L23 26 L22 28 L21 26 L19 25 L21 24 Z" fill={color} opacity="0.7" stroke="none"/>
  </svg>
);

// Ornament frame wrapping content — 4 filigree corners + top/bottom flourish.
// Honors data-ornaments="off" by collapsing to plain.
const Ornamented = ({ children, size = 32, color = 'var(--gold-0)', className = '', style }) => (
  <div className={`ornamented ${className}`} style={style}>
    <span className="orn orn-tl"><CornerOrnament size={size} color={color}/></span>
    <span className="orn orn-tr"><CornerOrnament size={size} color={color} rotate={90}/></span>
    <span className="orn orn-br"><CornerOrnament size={size} color={color} rotate={180}/></span>
    <span className="orn orn-bl"><CornerOrnament size={size} color={color} rotate={270}/></span>
    {children}
  </div>
);

// Portrait upload component — accepts dragged/picked image, returns base64.
const PortraitDrop = ({ value, onChange, name = '', size = 120, monogramFn }) => {
  const inputRef = useRef(null);
  const [drag, setDrag] = useState(false);

  const onFile = (file) => {
    if (!file) return;
    if (!/^image\//.test(file.type)) return;
    if (file.size > 4 * 1024 * 1024) return; // мовчки ігноруємо >4 МБ
    const reader = new FileReader();
    reader.onload = (e) => onChange(e.target.result);
    reader.readAsDataURL(file);
  };

  const monogram = monogramFn ? monogramFn(name) : (name || '').split(' ').map(p => p[0]).slice(0, 2).join('');

  return (
    <div
      className={`portrait-drop ${drag ? 'drag' : ''} ${value ? 'has-image' : ''}`}
      style={{ width: size, height: size }}
      onDragOver={(e) => { e.preventDefault(); setDrag(true); }}
      onDragLeave={() => setDrag(false)}
      onDrop={(e) => { e.preventDefault(); setDrag(false); onFile(e.dataTransfer.files[0]); }}
      onClick={() => inputRef.current?.click()}
      title="Клік або перетягни фото"
    >
      <input ref={inputRef} type="file" accept="image/*"
        style={{ display: 'none' }}
        onChange={(e) => onFile(e.target.files[0])}/>
      {value
        ? <img src={value} alt={name}/>
        : <span className="portrait-monogram">{monogram}</span>
      }
      <div className="portrait-rim"/>
      <div className="portrait-overlay">
        <Icon name="upload" size={20}/>
        <span style={{ fontSize: 9, marginTop: 4 }}>фото</span>
      </div>
      {value && (
        <button className="portrait-clear" onClick={(e) => { e.stopPropagation(); onChange(null); }} title="Скинути">
          <Icon name="x" size={12}/>
        </button>
      )}
    </div>
  );
};

// Toast (managed via ToastContext)
const ToastContext = createContext({ push: () => {} });
const useToast = () => useContext(ToastContext);

const ToastHost = ({ toasts }) => (
  <div className="toast-wrap">
    {toasts.map(t => (
      <div key={t.id} className={`toast ${t.crit ? 'crit' : ''}`}>
        {t.icon && <Icon name={t.icon} size={16}/>}
        {t.label && <span>{t.label}</span>}
        {t.value !== undefined && <span className="toast-val">{t.value}</span>}
        {t.detail && <span className="mono" style={{ color: 'var(--ink-3)', fontSize: 11 }}>{t.detail}</span>}
      </div>
    ))}
  </div>
);

const ToastProvider = ({ children }) => {
  const [toasts, setToasts] = useState([]);
  const push = useCallback((t) => {
    const id = Math.random().toString(36).slice(2);
    setToasts(prev => [...prev, { id, ...t }].slice(-4));
    setTimeout(() => setToasts(prev => prev.filter(x => x.id !== id)), t.duration || 3200);
  }, []);
  return (
    <ToastContext.Provider value={{ push }}>
      {children}
      <ToastHost toasts={toasts}/>
    </ToastContext.Provider>
  );
};

Object.assign(window, {
  Card, Btn, IconBtn, Chip, Dot, Slot, Bar, Field, Divider,
  SectionHeader, ShieldStat, Stepper, Flourish, CornerOrnament, Ornamented, PortraitDrop,
  ToastContext, useToast, ToastProvider,
});
