// =========================================
// DXA Admin · shared UI atoms + icons
// =========================================

const { useRef: _useRef, useState: _useState } = React;
const useRef = _useRef;
const useState = _useState;

const cls = (...a) => a.filter(Boolean).join(' ');

// Inline SVG icon set (24x24 viewBox, currentColor strokes)
const sv = (d, opts={}) => (
  <svg width={opts.size||18} height={opts.size||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">{d}</svg>
);

const I = {
  dashboard: sv(<><rect x="3" y="3" width="7" height="9"/><rect x="14" y="3" width="7" height="5"/><rect x="14" y="12" width="7" height="9"/><rect x="3" y="16" width="7" height="5"/></>),
  inbox: sv(<><path d="M22 12h-6l-2 3h-4l-2-3H2"/><path d="M5.45 5.11L2 12v6a2 2 0 002 2h16a2 2 0 002-2v-6l-3.45-6.89A2 2 0 0016.76 4H7.24a2 2 0 00-1.79 1.11z"/></>),
  hero: sv(<><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18M9 21V9"/></>),
  about: sv(<><circle cx="12" cy="12" r="10"/><path d="M12 16v-4M12 8h.01"/></>),
  services: sv(<><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 11-2.83 2.83l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 11-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 11-2.83-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 110-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 112.83-2.83l.06.06a1.65 1.65 0 001.82.33H9a1.65 1.65 0 001-1.51V3a2 2 0 114 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 112.83 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H21a2 2 0 110 4h-.09a1.65 1.65 0 00-1.51 1z"/></>),
  stats: sv(<><line x1="12" y1="20" x2="12" y2="10"/><line x1="18" y1="20" x2="18" y2="4"/><line x1="6" y1="20" x2="6" y2="16"/></>),
  portfolio: sv(<><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="M21 15l-5-5L5 21"/></>),
  clients: sv(<><path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 00-3-3.87M16 3.13a4 4 0 010 7.75"/></>),
  contact: sv(<><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></>),
  footer: sv(<><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="3" y1="16" x2="21" y2="16"/></>),
  settings: sv(<><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 11-2.83 2.83l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 11-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 11-2.83-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 110-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 112.83-2.83l.06.06a1.65 1.65 0 001.82.33H9a1.65 1.65 0 001-1.51V3a2 2 0 114 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 112.83 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H21a2 2 0 110 4h-.09a1.65 1.65 0 00-1.51 1z"/></>),
  theme: sv(<><circle cx="13.5" cy="6.5" r="2.5"/><circle cx="17.5" cy="10.5" r="2.5"/><circle cx="8.5" cy="7.5" r="2.5"/><circle cx="6.5" cy="12.5" r="2.5"/><path d="M12 2a10 10 0 00-10 10c0 5.5 4.5 10 10 10a2 2 0 002-2v-3a2 2 0 012-2h3a2 2 0 002-2c0-5.5-4.5-10-10-10z"/></>),
  history: sv(<><path d="M3 12a9 9 0 109-9 9.7 9.7 0 00-6.74 2.74L3 8"/><path d="M3 3v5h5"/><path d="M12 7v5l4 2"/></>),
  backup: sv(<><path d="M21 16v3a2 2 0 01-2 2H5a2 2 0 01-2-2v-3"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></>),
  plus: sv(<><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></>),
  edit: sv(<><path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z"/></>),
  trash: sv(<><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6"/><path d="M10 11v6M14 11v6"/></>),
  drag: sv(<><circle cx="9" cy="6" r="1.2" fill="currentColor"/><circle cx="9" cy="12" r="1.2" fill="currentColor"/><circle cx="9" cy="18" r="1.2" fill="currentColor"/><circle cx="15" cy="6" r="1.2" fill="currentColor"/><circle cx="15" cy="12" r="1.2" fill="currentColor"/><circle cx="15" cy="18" r="1.2" fill="currentColor"/></>),
  check: sv(<polyline points="20 6 9 17 4 12"/>),
  x: sv(<><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></>),
  external: sv(<><path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></>),
  eye: sv(<><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></>),
  reply: sv(<><polyline points="9 17 4 12 9 7"/><path d="M20 18v-2a4 4 0 00-4-4H4"/></>),
  star: sv(<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" fill="currentColor"/>),
  image: sv(<><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></>),
  video: sv(<><polygon points="23 7 16 12 23 17 23 7"/><rect x="1" y="5" width="15" height="14" rx="2"/></>),
  upload: sv(<><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></>),
};

// === Pill ===
const Pill = ({ tone='muted', children }) => (
  <span className={`pill pill-${tone}`}>{children}</span>
);

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

// === Bilingual text field (AR + EN stacked) ===
const Bilingual = ({ labelAr, labelEn, valueAr, valueEn, onChangeAr, onChangeEn, multiline=false, rows=2 }) => (
  <div className="bilingual">
    <div className="bi-head">
      <span>{labelAr}</span>
      <span style={{fontSize:10,opacity:.7,fontFamily:'JetBrains Mono, monospace'}}>{labelEn}</span>
    </div>
    <div className="bi-row">
      <div className="bi-lang">AR</div>
      {multiline
        ? <textarea rows={rows} value={valueAr||''} onChange={e=>onChangeAr(e.target.value)}/>
        : <input type="text" value={valueAr||''} onChange={e=>onChangeAr(e.target.value)}/>}
    </div>
    <div className="bi-row en">
      <div className="bi-lang">EN</div>
      {multiline
        ? <textarea rows={rows} value={valueEn||''} onChange={e=>onChangeEn(e.target.value)}/>
        : <input type="text" value={valueEn||''} onChange={e=>onChangeEn(e.target.value)}/>}
    </div>
  </div>
);

// =========================================
// Media upload system (high-quality images + videos)
// =========================================

// Format file size as human-readable
const fmtSize = (b) => {
  if (!b && b !== 0) return '';
  if (b < 1024) return b + ' B';
  if (b < 1024*1024) return (b/1024).toFixed(1) + ' KB';
  if (b < 1024*1024*1024) return (b/1024/1024).toFixed(1) + ' MB';
  return (b/1024/1024/1024).toFixed(2) + ' GB';
};
const fmtDuration = (s) => {
  if (!s && s !== 0) return '';
  const m = Math.floor(s/60), sec = Math.floor(s%60);
  return `${m}:${String(sec).padStart(2,'0')}`;
};
// Resolution quality badge
const qualityBadge = (w, h, isVideo) => {
  const max = Math.max(w||0, h||0);
  if (isVideo) {
    if (max >= 3840) return { label:'4K · UHD', tone:'accent' };
    if (max >= 2560) return { label:'2.5K · QHD', tone:'green' };
    if (max >= 1920) return { label:'Full HD', tone:'green' };
    if (max >= 1280) return { label:'HD', tone:'blue' };
    return { label:'SD', tone:'amber' };
  }
  const mp = (w*h)/1_000_000;
  if (mp >= 30) return { label:'فائق الدقة · ' + Math.round(mp) + 'MP', tone:'accent' };
  if (mp >= 12) return { label:Math.round(mp) + 'MP · عالي', tone:'green' };
  if (mp >= 4)  return { label:Math.round(mp) + 'MP', tone:'blue' };
  return { label:'منخفض · ' + mp.toFixed(1) + 'MP', tone:'amber' };
};

// Probe a File to get dimensions/duration before storing
const probeMedia = (file) => new Promise((resolve) => {
  const isVideo = file.type.startsWith('video/');
  const url = URL.createObjectURL(file);
  if (isVideo) {
    const v = document.createElement('video');
    v.preload = 'metadata';
    v.muted = true;
    v.src = url;
    v.onloadedmetadata = () => {
      resolve({ src:url, name:file.name, size:file.size, type:file.type, width:v.videoWidth, height:v.videoHeight, duration:v.duration, isVideo:true });
    };
    v.onerror = () => resolve({ src:url, name:file.name, size:file.size, type:file.type, isVideo:true });
  } else {
    const img = new Image();
    img.onload = () => {
      resolve({ src:url, name:file.name, size:file.size, type:file.type, width:img.naturalWidth, height:img.naturalHeight, isVideo:false });
    };
    img.onerror = () => resolve({ src:url, name:file.name, size:file.size, type:file.type, isVideo:false });
    img.src = url;
  }
});

// === MediaSlot: a full upload + preview slot ===
const MediaSlot = ({ value, onChange, kind='photo', aspect, label, hint }) => {
  const fileInputRef = useRef(null);
  const [over, setOver] = useState(false);
  const [busy, setBusy] = useState(false);
  const accept = kind === 'video'
    ? 'video/mp4,video/quicktime,video/webm,video/x-matroska'
    : kind === 'any'
      ? 'image/*,video/*'
      : 'image/jpeg,image/png,image/webp,image/avif';

  const handleFiles = async (files) => {
    const file = files && files[0];
    if (!file) return;
    setBusy(true);
    const meta = await probeMedia(file);
    onChange(meta);
    setBusy(false);
  };
  const onDrop = (e) => {
    e.preventDefault(); setOver(false);
    handleFiles(e.dataTransfer.files);
  };
  const onPick = (e) => handleFiles(e.target.files);

  const ar = aspect || (kind==='video' ? '16 / 9' : '4 / 3');
  const hasMedia = !!(value && value.src);
  const isVid = hasMedia && value.isVideo;
  const qb = hasMedia && value.width ? qualityBadge(value.width, value.height, isVid) : null;

  return (
    <div className="mslot">
      <div
        className={cls('mslot-frame', over && 'over', hasMedia && 'has')}
        style={{ aspectRatio: ar }}
        onDragOver={e=>{e.preventDefault(); setOver(true);}}
        onDragLeave={()=>setOver(false)}
        onDrop={onDrop}
        onClick={()=>!hasMedia && fileInputRef.current?.click()}
      >
        {hasMedia ? (
          isVid ? (
            <video src={value.src} muted loop playsInline autoPlay className="mslot-media"/>
          ) : (
            <img src={value.src} alt="" className="mslot-media"/>
          )
        ) : (
          <div className="mslot-empty">
            <div className="ph-mark">{kind==='video' ? '▷' : '⌘'}</div>
            <div className="mslot-cta">
              <strong>{kind==='video' ? 'اسحب الفيديو هنا' : 'اسحب الصورة هنا'}</strong>
              <span>أو انقر للاختيار من الجهاز</span>
            </div>
            {hint && <div className="mslot-hint">{hint}</div>}
          </div>
        )}
        {busy && <div className="mslot-busy"><div className="spinner"/></div>}
        {hasMedia && (
          <div className="mslot-overlay">
            <button className="ibtn-light" title="استبدال" onClick={e=>{e.stopPropagation(); fileInputRef.current?.click();}}>{I.upload}</button>
            <button className="ibtn-light danger" title="إزالة" onClick={e=>{e.stopPropagation(); onChange(null);}}>{I.trash}</button>
          </div>
        )}
        {qb && <div className={`mslot-quality pill pill-${qb.tone}`}>{qb.label}</div>}
        {hasMedia && isVid && value.duration && <div className="mslot-dur">{fmtDuration(value.duration)}</div>}
      </div>

      {hasMedia ? (
        <div className="mslot-meta">
          <div className="mslot-meta-row">
            <span className="mslot-name" title={value.name}>{value.name}</span>
            <span className="mslot-size mono">{fmtSize(value.size)}</span>
          </div>
          <div className="mslot-meta-row">
            {value.width && <span className="mslot-dim mono">{value.width} × {value.height}</span>}
            <span className="mslot-type mono">{(value.type||'').split('/')[1]?.toUpperCase()}</span>
          </div>
        </div>
      ) : (
        <div className="mslot-formats">
          {kind==='video'
            ? 'MP4 · MOV · WebM — حتى 500MB · يدعم 4K'
            : 'JPG · PNG · WebP · AVIF — حتى 20MB · جودة أصلية'}
        </div>
      )}

      <input ref={fileInputRef} type="file" accept={accept} onChange={onPick} style={{display:'none'}}/>
    </div>
  );
};

// Backwards-compatible aliases
const ImgPreview = ({ kind='photo', label, value, onChange }) => (
  <MediaSlot kind={kind} value={value} onChange={onChange||(()=>{})} label={label}/>
);
const Dropzone = ({ value, onChange, kind='photo' }) => (
  <MediaSlot kind={kind} value={value} onChange={onChange||(()=>{})} />
);

// === Empty state ===
const EmptyState = ({ icon, title, hint, action }) => (
  <div className="empty">
    <div className="e-icon">{icon}</div>
    <h4>{title}</h4>
    <p>{hint}</p>
    {action}
  </div>
);

Object.assign(window, { cls, I, Pill, Field, Bilingual, MediaSlot, ImgPreview, Dropzone, EmptyState, fmtSize, fmtDuration, probeMedia });
