// ui.jsx — design-system primitives (tokens from the brief)
const { useState, useEffect, useRef } = React;

// tone → full Tailwind class strings (literal so the CDN JIT picks them up)
const TONE = {
  brand:            { text:'text-brand',         bg:'bg-brand/12',         dot:'bg-brand' },
  info:             { text:'text-info',          bg:'bg-info/12',          dot:'bg-info' },
  success:          { text:'text-success',       bg:'bg-success/15',       dot:'bg-success' },
  warning:          { text:'text-warning',       bg:'bg-warning/15',       dot:'bg-warning' },
  danger:           { text:'text-danger',        bg:'bg-danger/12',        dot:'bg-danger' },
  accent:           { text:'text-accent',        bg:'bg-accent/12',        dot:'bg-accent' },
  'accent-warm':    { text:'text-accent-warm',   bg:'bg-accent-warm/15',   dot:'bg-accent-warm' },
  'text-muted':     { text:'text-text-muted',    bg:'bg-surface-muted',    dot:'bg-text-muted' },
  'text-secondary': { text:'text-text-secondary',bg:'bg-surface-muted',    dot:'bg-text-secondary' },
  'cat-hydraulika': { text:'text-cat-hydraulika',bg:'bg-cat-hydraulika/12',dot:'bg-cat-hydraulika' },
  'cat-elektryka':  { text:'text-cat-elektryka', bg:'bg-cat-elektryka/12', dot:'bg-cat-elektryka' },
  'cat-winda':      { text:'text-cat-winda',     bg:'bg-cat-winda/12',     dot:'bg-cat-winda' },
  'cat-czystosc':   { text:'text-cat-czystosc',  bg:'bg-cat-czystosc/12',  dot:'bg-cat-czystosc' },
  'cat-zielone':    { text:'text-cat-zielone',   bg:'bg-cat-zielone/12',   dot:'bg-cat-zielone' },
};
const tone = (t) => TONE[t] || TONE.brand;

function Spinner({ size = 18 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" className="animate-spin">
      <circle cx="12" cy="12" r="9" stroke="currentColor" strokeOpacity="0.25" strokeWidth="3"/>
      <path d="M21 12a9 9 0 0 0-9-9" stroke="currentColor" strokeWidth="3" strokeLinecap="round"/>
    </svg>
  );
}

function Btn({ children, variant = 'primary', size = 'md', icon, iconRight, loading, block, className = '', ...rest }) {
  const sizes = {
    sm: 'h-9 px-3.5 text-[13px] gap-1.5',
    md: 'h-11 px-5 text-[15px] gap-2',
    lg: 'h-[52px] px-6 text-base gap-2.5',
  };
  const variants = {
    primary:  'bg-brand text-brand-fg hover:bg-brand-strong shadow-sm active:scale-[.97]',
    secondary:'bg-surface text-text border border-border hover:bg-surface-muted active:scale-[.97]',
    ghost:    'bg-transparent text-text-secondary hover:bg-surface-muted active:scale-[.97]',
    danger:   'bg-danger text-white hover:brightness-95 shadow-sm active:scale-[.97]',
    link:     'bg-transparent text-brand hover:underline px-0 h-auto',
  };
  return (
    <button
      className={`focusable inline-flex items-center justify-center font-display font-700 rounded-pill transition-all duration-150 select-none disabled:opacity-50 disabled:pointer-events-none ${sizes[size]} ${variants[variant]} ${block ? 'w-full' : ''} ${className}`}
      {...rest}>
      {loading ? <Spinner /> : icon && <Icon name={icon} size={size === 'sm' ? 16 : 19} stroke={2.2} />}
      {children}
      {!loading && iconRight && <Icon name={iconRight} size={size === 'sm' ? 16 : 19} stroke={2.2} />}
    </button>
  );
}

function IconBtn({ name, label, className = '', size = 22, ...rest }) {
  return (
    <button aria-label={label} title={label}
      className={`focusable inline-flex items-center justify-center rounded-pill text-text-secondary hover:bg-surface-muted hover:text-text transition-colors active:scale-90 ${className}`}
      style={{ width: 44, height: 44 }} {...rest}>
      <Icon name={name} size={size} stroke={2} />
    </button>
  );
}

// Badge — semantyczny / kategorialny, zawsze kolor + (ikona) + tekst
function Badge({ children, tone: t = 'brand', icon, dot, size = 'md', className = '' }) {
  const c = tone(t);
  const sz = size === 'sm' ? 'text-[11px] px-2 py-0.5 gap-1' : 'text-xs px-2.5 py-1 gap-1.5';
  return (
    <span className={`inline-flex items-center font-display font-700 rounded-pill ${c.bg} ${c.text} ${sz} ${className}`}>
      {dot && <span className={`w-1.5 h-1.5 rounded-full ${c.dot}`} />}
      {icon && <Icon name={icon} size={size === 'sm' ? 12 : 13} stroke={2.4} />}
      <span className="leading-none whitespace-nowrap">{children}</span>
    </span>
  );
}

// Chip filtra — wybieralny
function Chip({ children, active, onClick, icon, count, tone: t }) {
  const c = t ? tone(t) : null;
  return (
    <button onClick={onClick}
      className={`focusable shrink-0 inline-flex items-center gap-1.5 h-9 px-3.5 rounded-pill text-[13px] font-display font-600 border transition-all active:scale-95
        ${active
          ? 'bg-text text-bg border-text'
          : `bg-surface text-text-secondary border-border hover:border-text-muted`}`}>
      {icon && <span className={active ? '' : (c ? c.text : '')}><Icon name={icon} size={15} stroke={2.2} /></span>}
      {children}
      {count != null && <span className={`text-[11px] font-700 ${active ? 'opacity-70' : 'text-text-muted'}`}>{count}</span>}
    </button>
  );
}

function Card({ children, className = '', as = 'div', ...rest }) {
  const C = as;
  return <C className={`bg-surface border border-border rounded-xl shadow-sm ${className}`} {...rest}>{children}</C>;
}

function Avatar({ name, size = 40, initials }) {
  const h = avatarHue(name || '');
  const ini = initials || (name || '?').split(' ').map(w => w[0]).slice(0, 2).join('').toUpperCase();
  return (
    <div className="flex items-center justify-center rounded-full font-display font-700 text-white shrink-0"
      style={{ width: size, height: size, fontSize: size * 0.38,
        background: `linear-gradient(135deg, hsl(${h} 60% 52%), hsl(${(h+40)%360} 62% 46%))` }}>
      {ini}
    </div>
  );
}

function Segmented({ options, value, onChange }) {
  return (
    <div role="tablist" className="flex p-1 bg-surface-muted rounded-pill gap-1">
      {options.map(o => (
        <button key={o.value} role="tab" aria-selected={value === o.value} onClick={() => onChange(o.value)}
          className={`focusable flex-1 h-10 rounded-pill text-[14px] font-display font-700 transition-all flex items-center justify-center gap-1.5
            ${value === o.value ? 'bg-surface text-text shadow-sm' : 'text-text-secondary hover:text-text'}`}>
          {o.icon && <Icon name={o.icon} size={16} stroke={2.2} />}{o.label}
        </button>
      ))}
    </div>
  );
}

function Toggle({ checked, onChange, label }) {
  return (
    <button role="switch" aria-checked={checked} aria-label={label} onClick={() => onChange(!checked)}
      className={`focusable relative shrink-0 rounded-pill transition-colors duration-200 ${checked ? 'bg-brand' : 'bg-border'}`}
      style={{ width: 48, height: 28 }}>
      <span className="absolute top-1 left-1 bg-white rounded-full shadow transition-transform duration-200"
        style={{ width: 20, height: 20, transform: checked ? 'translateX(20px)' : 'none' }} />
    </button>
  );
}

function Stars({ value = 0, onChange, size = 32 }) {
  const [hover, setHover] = useState(0);
  return (
    <div className="flex gap-1.5" role="radiogroup" aria-label="Ocena">
      {[1,2,3,4,5].map(n => {
        const on = (hover || value) >= n;
        return (
          <button key={n} aria-label={`${n} z 5`} onClick={() => onChange(n)}
            onMouseEnter={() => setHover(n)} onMouseLeave={() => setHover(0)}
            className={`focusable transition-transform active:scale-90 ${on ? 'text-accent-warm' : 'text-border'}`}>
            <Icon name="star" size={size} fill={on} stroke={1.8} />
          </button>
        );
      })}
    </div>
  );
}

// Skeleton
function Sk({ className = '', w, h = 14, r = 8 }) {
  return <div className={`skeleton ${className}`} style={{ width: w, height: h, borderRadius: r }} />;
}

// Bottom sheet / modal
function Sheet({ open, onClose, children, title }) {
  if (!open) return null;
  return (
    <div className="absolute inset-0 z-[80] flex items-end justify-center anim-fade" onClick={onClose}>
      <div className="absolute inset-0 bg-black/45 backdrop-blur-[2px]" />
      <div className="relative w-full bg-surface rounded-t-[28px] shadow-lg pb-8 max-h-[88%] overflow-auto app-scroll"
        style={{ animation: 'om-slide-up .32s cubic-bezier(.22,1,.36,1) both' }}
        onClick={e => e.stopPropagation()}>
        <div className="sticky top-0 bg-surface pt-3 pb-2 px-5 rounded-t-[28px]">
          <div className="w-10 h-1.5 rounded-full bg-border mx-auto mb-3" />
          {title && <h3 className="font-display font-700 text-text text-lg">{title}</h3>}
        </div>
        <div className="px-5">{children}</div>
      </div>
    </div>
  );
}

// Toast (a11y: aria-live)
function Toast({ toast }) {
  if (!toast) return null;
  const c = tone(toast.tone || 'success');
  return (
    <div className="absolute left-1/2 z-[90] w-[88%]" style={{ bottom: 96, animation: 'om-toast-in .3s cubic-bezier(.22,1,.36,1) both' }}
      role="status" aria-live="polite">
      <div className="flex items-center gap-3 bg-text text-bg rounded-pill pl-4 pr-5 py-3 shadow-lg">
        <span className={`flex items-center justify-center w-7 h-7 rounded-full ${c.bg}`}>
          <Icon name={toast.icon || 'check'} size={17} stroke={2.6} className={c.text} />
        </span>
        <span className="text-[14px] font-display font-600 leading-tight">{toast.msg}</span>
      </div>
    </div>
  );
}

// inline alert banner
function Banner({ tone: t = 'danger', icon = 'alert', title, children, onClose }) {
  const c = tone(t);
  return (
    <div className={`flex items-start gap-3 rounded-lg p-3.5 ${c.bg} border border-current/15`} role="alert">
      <span className={`${c.text} shrink-0 mt-0.5`}><Icon name={icon} size={20} stroke={2.2} /></span>
      <div className="flex-1 min-w-0">
        {title && <p className={`font-display font-700 text-[14px] ${c.text} leading-tight`}>{title}</p>}
        {children && <p className="text-[13px] text-text-secondary mt-0.5 leading-snug">{children}</p>}
      </div>
      {onClose && <button aria-label="Zamknij" onClick={onClose} className={`${c.text} opacity-70 hover:opacity-100`}><Icon name="x" size={18} /></button>}
    </div>
  );
}

function EmptyState({ icon, title, children, action }) {
  return (
    <div className="flex flex-col items-center text-center px-8 py-12 anim-rise">
      <div className="relative mb-5">
        <div className="absolute inset-0 rounded-[28px] bg-brand/15 blur-xl" />
        <div className="relative w-20 h-20 rounded-[24px] bg-gradient-to-br from-brand/15 to-accent/15 border border-border flex items-center justify-center text-brand">
          <Icon name={icon} size={34} stroke={1.8} />
        </div>
      </div>
      <h3 className="font-display font-700 text-text text-lg">{title}</h3>
      {children && <p className="text-[14px] text-text-secondary mt-1.5 max-w-[15rem] leading-snug">{children}</p>}
      {action && <div className="mt-5">{action}</div>}
    </div>
  );
}

// section header
function SectionHead({ title, action, onAction }) {
  return (
    <div className="flex items-center justify-between mb-3 px-0.5">
      <h2 className="font-display font-700 text-text text-[17px]">{title}</h2>
      {action && <button onClick={onAction} className="focusable text-[13px] font-display font-600 text-brand flex items-center gap-0.5 active:scale-95">{action}<Icon name="chevronRight" size={15} /></button>}
    </div>
  );
}

// PDF / załącznik chip
function Attachment({ name }) {
  return (
    <div className="flex items-center gap-2.5 bg-surface-muted rounded-md p-2.5 pr-3.5 border border-border">
      <span className="flex items-center justify-center w-9 h-9 rounded-md bg-danger/12 text-danger shrink-0"><Icon name="fileText" size={18} /></span>
      <span className="text-[13px] font-display font-600 text-text truncate flex-1">{name}</span>
      <Icon name="chevronRight" size={16} className="text-text-muted" />
    </div>
  );
}

Object.assign(window, {
  TONE, tone, Spinner, Btn, IconBtn, Badge, Chip, Card, Avatar, Segmented,
  Toggle, Stars, Sk, Sheet, Toast, Banner, EmptyState, SectionHead, Attachment,
});
