/* ============================================================
   Umumiy UI komponentlar  →  window'ga eksport
   ============================================================ */
const { useState, useEffect, useRef, useMemo, useCallback, useLayoutEffect } = React;

/* ---------- Ikonkalar ---------- */
const ICONS = {
  board:   'M4 4h6v16H4zM14 4h6v9h-6z',
  grid:    'M3 3h7v7H3zM14 3h7v7h-7zM14 14h7v7h-7zM3 14h7v7H3z',
  chart:   'M3 3v18h18M7 14v4M12 9v9M17 5v13',
  gear:    'M12 15a3 3 0 100-6 3 3 0 000 6z|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',
  plus:    'M12 5v14M5 12h14',
  x:       'M18 6L6 18M6 6l12 12',
  chevD:   'M6 9l6 6 6-6',
  chevR:   'M9 6l6 6-6 6',
  chevL:   'M15 6l-6 6 6 6',
  logout:  'M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4M16 17l5-5-5-5M21 12H9',
  search:  'M11 19a8 8 0 100-16 8 8 0 000 16zM21 21l-4.35-4.35',
  clock:   'M12 22a10 10 0 100-20 10 10 0 000 20zM12 6v6l4 2',
  cal:     'M3 4h18v18H3zM3 10h18M8 2v4M16 2v4',
  trash:   'M3 6h18M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6',
  edit:    'M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7M18.5 2.5a2.12 2.12 0 013 3L12 15l-4 1 1-4z',
  check:   'M20 6L9 17l-5-5',
  truck:   'M1 3h15v13H1zM16 8h4l3 3v5h-7M5.5 19a2 2 0 100-4 2 2 0 000 4zM18.5 19a2 2 0 100-4 2 2 0 000 4z',
  box:     'M21 16V8a2 2 0 00-1-1.73l-7-4a2 2 0 00-2 0l-7 4A2 2 0 003 8v8a2 2 0 001 1.73l7 4a2 2 0 002 0l7-4A2 2 0 0021 16zM3.27 6.96L12 12l8.73-5.04M12 22V12',
  pin:     'M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z|M12 13a3 3 0 100-6 3 3 0 000 6z',
  user:    'M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2M12 11a4 4 0 100-8 4 4 0 000 8z',
  users:   'M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2M9 11a4 4 0 100-8 4 4 0 000 8z|M23 21v-2a4 4 0 00-3-3.87M16 3.13a4 4 0 010 7.75',
  layers:  'M12 2l9 5-9 5-9-5 9-5zM3 12l9 5 9-5M3 17l9 5 9-5',
  drag:    'M9 6a1 1 0 100-2 1 1 0 000 2zM9 13a1 1 0 100-2 1 1 0 000 2zM9 20a1 1 0 100-2 1 1 0 000 2zM15 6a1 1 0 100-2 1 1 0 000 2zM15 13a1 1 0 100-2 1 1 0 000 2zM15 20a1 1 0 100-2 1 1 0 000 2z',
  arrowR:  'M5 12h14M13 6l6 6-6 6',
  menu:    'M3 6h18M3 12h18M3 18h18',
  filter:  'M22 3H2l8 9.46V19l4 2v-8.54z',
  trendUp: 'M23 6l-9.5 9.5-5-5L1 18M17 6h6v6',
  lock:    'M5 11h14v10H5zM8 11V7a4 4 0 018 0v4',
  hash:    'M4 9h16M4 15h16M10 3L8 21M16 3l-2 18',
  coin:    'M12 22a10 10 0 100-20 10 10 0 000 20zM9.5 9a2.5 2 0 015 0c0 1.5-2.5 1.8-2.5 3M12 17h.01',
  info:    'M12 22a10 10 0 100-20 10 10 0 000 20zM12 16v-4M12 8h.01',
  alert:   'M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z|M12 9v4M12 17h.01',
  note:    'M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z',
  upload:  'M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M17 8l-5-5-5 5M12 3v12',
  download:'M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3',
  tasks:   'M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2|M9 5a2 2 0 002 2h2a2 2 0 002-2|M9 5a2 2 0 012-2h2a2 2 0 012 2|M9 14l2 2 4-4',
  shield:  'M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z|M9 12l2 2 4-4',
  copy:    'M9 9h10a2 2 0 012 2v8a2 2 0 01-2 2H9a2 2 0 01-2-2v-8a2 2 0 012-2z|M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1',
  refresh: 'M23 4v6h-6M1 20v-6h6|M3.51 9a9 9 0 0114.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0020.49 15',
  sparkle: 'M12 3l1.9 5.6L19.5 10l-5.6 1.4L12 17l-1.9-5.6L4.5 10l5.6-1.4z|M19 15l.7 2.1L22 18l-2.3.9L19 21l-.7-2.1L16 18l2.3-.9z',
  send:    'M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z',
  bot:     'M12 2v4M5 8h14a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2v-8a2 2 0 012-2z|M9 13h.01M15 13h.01M9 17h6',
  bulb:    'M9 18h6M10 22h4M12 2a7 7 0 00-4 12.7c.6.5 1 1.3 1 2.3h6c0-1 .4-1.8 1-2.3A7 7 0 0012 2z',
  clip:    'M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48',
  file:    'M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z|M14 2v6h6',
  sun:     'M12 17a5 5 0 100-10 5 5 0 000 10z|M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42',
  moon:    'M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z',
};

/* ---------- Rasmni o'lchamini kichraytirib base64 data URL ga aylantirish ---------- */
// file: <input type=file> dan; maxSize: eng katta tomon (px); type: 'image/png'|'image/jpeg'
function fileToDataURL(file, maxSize = 256, type = 'image/png', quality = 0.9) {
  return new Promise((resolve, reject) => {
    if (!file) return reject(new Error('Fayl tanlanmadi'));
    if (!/^image\//.test(file.type)) return reject(new Error('Faqat rasm fayli'));
    const reader = new FileReader();
    reader.onerror = () => reject(new Error('Faylni oʻqib boʻlmadi'));
    reader.onload = () => {
      const img = new Image();
      img.onerror = () => reject(new Error('Rasmni yuklab boʻlmadi'));
      img.onload = () => {
        let w = img.width, h = img.height;
        const scale = Math.min(1, maxSize / Math.max(w, h));
        w = Math.max(1, Math.round(w * scale));
        h = Math.max(1, Math.round(h * scale));
        const canvas = document.createElement('canvas');
        canvas.width = w; canvas.height = h;
        const ctx = canvas.getContext('2d');
        ctx.drawImage(img, 0, 0, w, h);
        try { resolve(canvas.toDataURL(type, quality)); }
        catch (e) { reject(new Error('Rasmni qayta ishlab boʻlmadi')); }
      };
      img.src = reader.result;
    };
    reader.readAsDataURL(file);
  });
}

/* ---------- Mobil ekran aniqlash (matchMedia) ---------- */
function useIsMobile(maxWidth = 760) {
  const q = '(max-width: ' + maxWidth + 'px)';
  const [m, setM] = useState(() => (typeof window !== 'undefined' && window.matchMedia) ? window.matchMedia(q).matches : false);
  useEffect(() => {
    if (!window.matchMedia) return;
    const mql = window.matchMedia(q);
    const h = (e) => setM(e.matches);
    setM(mql.matches);
    if (mql.addEventListener) mql.addEventListener('change', h); else mql.addListener(h);
    return () => { if (mql.removeEventListener) mql.removeEventListener('change', h); else mql.removeListener(h); };
  }, [q]);
  return m;
}

/* ---------- Avatar (rasm yoki bosh harflar) ---------- */
function Avatar({ src, name = '', size = 36, radius = 10, accent = false }) {
  const initials = (name || '').split(' ').map(s => s[0]).join('').slice(0, 2).toUpperCase();
  const common = { width: size, height: size, borderRadius: radius, flex: 'none', overflow: 'hidden' };
  if (src) {
    return <img src={src} alt={name} title={name} style={{ ...common, objectFit: 'cover', display: 'block' }} />;
  }
  return (
    <div title={name} style={{ ...common, background: accent ? 'var(--brand)' : 'var(--bg-2)', color: accent ? '#fff' : 'var(--ink-2)',
                               display: 'grid', placeItems: 'center', fontWeight: 800, fontSize: Math.round(size * 0.36) }}>
      {initials}
    </div>
  );
}

function Icon({ name, size = 18, stroke = 2, fill = 'none', style, className }) {
  const d = ICONS[name] || '';
  const parts = d.split('|');
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill={fill} stroke="currentColor"
         strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round"
         style={{ flex: 'none', ...style }} className={className} aria-hidden="true">
      {parts.map((p, i) => <path key={i} d={p} />)}
    </svg>
  );
}

/* ---------- Million Moxito logo ---------- */
function Star({ size = 22, color = 'var(--brand)' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill={color} aria-hidden="true" style={{ flex: 'none' }}>
      <path d="M12 1.6l2.74 6.03 6.56.62-4.93 4.37 1.45 6.45L12 16.1l-5.82 3.57 1.45-6.45L2.7 8.85l6.56-.62z" />
    </svg>
  );
}

function Logo({ compact = false, onLight = false }) {
  const custom = (window.DB && DB.BRANDING && DB.BRANDING.logo) || null;
  if (custom) {
    // Maxsus yuklangan logo — rasmni butun ko'rsatamiz
    return (
      <div style={{ display: 'flex', alignItems: 'center' }}>
        <img src={custom} alt="Logo" style={{ height: compact ? 32 : 36, maxWidth: compact ? 40 : 168, objectFit: 'contain', display: 'block' }} />
      </div>
    );
  }
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 9 }}>
      <div style={{
        width: 34, height: 34, borderRadius: 9, background: onLight ? 'rgba(255,255,255,.16)' : 'var(--brand)',
        display: 'grid', placeItems: 'center', boxShadow: onLight ? 'none' : 'var(--sh-1)',
      }}>
        <span style={{ color: '#fff', fontWeight: 800, fontSize: 15, letterSpacing: '-.04em' }}>MM</span>
      </div>
      {!compact && (
        <div style={{ lineHeight: 1 }}>
          <div style={{ fontWeight: 700, fontSize: 17, letterSpacing: '-.02em', color: onLight ? '#fff' : 'var(--ink)' }}>
            Million <span style={{ color: onLight ? '#fff' : 'var(--accent-2)' }}>Moxito</span>
          </div>
        </div>
      )}
    </div>
  );
}

/* ---------- Status nuqtasi + label ---------- */
function StatusDot({ status, size = 8 }) {
  const col = DB.COLUMNS[DB.COL_INDEX[status]].color;
  return <span className="dot" style={{ width: size, height: size, background: col }} />;
}

/* ---------- Brend rozetkasi ---------- */
function BrandTag({ brandId, size = 'sm' }) {
  const b = DB.BRANDS.find(x => x.id === brandId);
  if (!b) return null;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 5, padding: size === 'sm' ? '2px 7px' : '3px 9px',
      borderRadius: 5, fontSize: size === 'sm' ? 10.5 : 12, fontWeight: 700, letterSpacing: '.02em',
      color: '#fff', background: b.color,
    }}>{b.name}</span>
  );
}

/* ---------- Modal qobig'i ---------- */
function Modal({ children, onClose, width = 480, align = 'center' }) {
  useEffect(() => {
    const h = (e) => { if (e.key === 'Escape') onClose && onClose(); };
    window.addEventListener('keydown', h);
    return () => window.removeEventListener('keydown', h);
  }, [onClose]);
  // Bola elementlarni 3 qismga ajratamiz: sarlavha (1-chi) — tepada qotgan,
  // footer (oxirgi, agar 3+ bola bo'lsa) — pastda qotgan, qolgani (tana) — scroll bo'ladi.
  // Shu tufayli har qanday telefonda (iPhone/Samsung) ham "Saqlash" tugmasi doim ko'rinadi.
  const arr = React.Children.toArray(children);
  let header = null, footer = null, body = arr;
  if (arr.length === 2) { header = arr[0]; body = [arr[1]]; }
  else if (arr.length >= 3) { header = arr[0]; footer = arr[arr.length - 1]; body = arr.slice(1, -1); }
  return (
    <div className="scrim" style={{ alignItems: align === 'center' ? 'center' : 'stretch', justifyContent: 'center' }}
         onMouseDown={(e) => { if (e.target === e.currentTarget) onClose && onClose(); }}>
      <div className="modal-card" style={{
        background: 'var(--surface)', borderRadius: 'var(--r-lg)', width,
        minWidth: 0, overflow: 'hidden', boxShadow: 'var(--sh-3)',
        display: 'flex', flexDirection: 'column', animation: 'popIn .22s var(--ease)', margin: 'auto',
      }}>
        {header && <div className="modal-head-wrap" style={{ flex: '0 0 auto' }}>{header}</div>}
        <div className="modal-body-scroll" style={{ flex: '1 1 auto', minHeight: 0, overflowY: 'auto', WebkitOverflowScrolling: 'touch' }}>{body}</div>
        {footer && <div className="modal-foot-wrap" style={{ flex: '0 0 auto' }}>{footer}</div>}
      </div>
    </div>
  );
}

function ModalHeader({ title, subtitle, onClose }) {
  return (
    <div style={{ display: 'flex', alignItems: 'flex-start', gap: 12, padding: '18px 20px',
                  borderBottom: '1px solid var(--border)' }}>
      <div style={{ flex: 1 }}>
        <div style={{ fontWeight: 700, fontSize: 16.5, letterSpacing: '-.01em' }}>{title}</div>
        {subtitle && <div style={{ fontSize: 12.5, color: 'var(--ink-3)', marginTop: 3 }}>{subtitle}</div>}
      </div>
      {onClose && (
        <button className="btn btn--icon btn--ghost" onClick={onClose} style={{ marginTop: -2 }} aria-label="Yopish">
          <Icon name="x" size={17} />
        </button>
      )}
    </div>
  );
}

/* ---------- Bo'sh holat ---------- */
function Empty({ icon = 'box', text }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8, padding: '24px 12px',
                  color: 'var(--ink-4)', textAlign: 'center' }}>
      <Icon name={icon} size={26} stroke={1.6} />
      <div style={{ fontSize: 12.5, fontWeight: 500 }}>{text}</div>
    </div>
  );
}

/* ---------- Toast ---------- */
function Toast({ msg, onDone }) {
  useEffect(() => { const t = setTimeout(onDone, 2600); return () => clearTimeout(t); }, [msg]);
  return (
    <div style={{ position: 'fixed', bottom: 22, left: '50%', transform: 'translateX(-50%)', zIndex: 90,
                  background: 'var(--ink)', color: '#fff', padding: '11px 18px', borderRadius: 100,
                  fontSize: 13, fontWeight: 600, boxShadow: 'var(--sh-3)', display: 'flex', alignItems: 'center', gap: 9,
                  animation: 'popIn .2s var(--ease)' }}>
      <span style={{ color: 'var(--brand)', display: 'inline-flex' }}><Icon name="check" size={16} stroke={2.6} /></span>
      {msg}
    </div>
  );
}

Object.assign(window, {
  useState, useEffect, useRef, useMemo, useCallback, useIsMobile,
  Icon, Star, Logo, Avatar, fileToDataURL, StatusDot, BrandTag, Modal, ModalHeader, Empty, Toast,
});
