/* global React, Icon */
/* Primitives: Button, IconBtn, Chip, Badge, Pill, Tag, Avatar,
   Input, Textarea, Select, Toggle, Checkbox, Radio, Slider, FilePick,
   Tabs, Segmented, Accordion, Breadcrumb, Kbd, Spinner */

const { useState, useRef, useEffect, useId, useCallback } = React;

/* ---------- Button ---------- */
function Button({
  variant = "primary", size = "md", icon, iconRight, children,
  disabled, loading, fullWidth, onClick, type = "button", style, className = "", ...rest
}) {
  const sz = {
    xs: { h: 28, px: 12, fs: 12 },
    sm: { h: 32, px: 14, fs: 13 },
    md: { h: "var(--d-btn-h)", px: "var(--d-btn-px)", fs: 14 },
    lg: { h: 48, px: 24, fs: 15 }
  }[size];
  const base = {
    height: sz.h, padding: `0 ${typeof sz.px === "number" ? sz.px + "px" : sz.px}`,
    fontSize: sz.fs, fontWeight: 500, fontFamily: "var(--sans)",
    borderRadius: 2,
    display: "inline-flex", alignItems: "center", justifyContent: "center",
    gap: 8, cursor: disabled ? "not-allowed" : "pointer",
    border: "1px solid transparent",
    transition: "background 220ms ease, color 220ms ease, border-color 220ms ease, opacity 200ms",
    opacity: disabled ? 0.4 : 1, position: "relative", overflow: "hidden",
    whiteSpace: "nowrap", letterSpacing: "-0.005em",
    width: fullWidth ? "100%" : "auto"
  };
  const variants = {
    primary: { background: "var(--brand-grad)", color: "white" },
    ink: { background: "var(--ink)", color: "var(--bg)" },
    secondary: { background: "transparent", color: "var(--ink)", border: "1px solid var(--ink)" },
    ghost: { background: "transparent", color: "var(--ink)" },
    quiet: { background: "var(--bg-2)", color: "var(--ink)" },
    danger: { background: "transparent", color: "var(--neg)", border: "1px solid var(--neg)" }
  };
  return (
    <button
      type={type} disabled={disabled || loading} onClick={onClick}
      className={`btn btn-${variant} ${className}`}
      style={{ ...base, ...variants[variant], ...style }}
      {...rest}>
      
      {loading && <Spinner size={14} />}
      {!loading && icon}
      {children}
      {!loading && iconRight}
    </button>);

}

function IconBtn({ icon, size = 36, onClick, label, active, className = "", style }) {
  return (
    <button
      type="button" onClick={onClick} aria-label={label}
      className={`icon-btn ${className}`}
      style={{
        width: size, height: size,
        display: "inline-flex", alignItems: "center", justifyContent: "center",
        background: active ? "var(--bg-2)" : "transparent",
        color: "var(--ink)",
        border: "1px solid " + (active ? "var(--line-2)" : "transparent"),
        borderRadius: "var(--r-sharp)", cursor: "pointer",
        transition: "background 200ms ease, border-color 200ms ease",
        ...style
      }}>
      
      {icon}
    </button>);

}

/* ---------- Spinner ---------- */
function Spinner({ size = 16, color = "currentColor" }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" style={{ animation: "spin 800ms linear infinite" }}>
      <circle cx="12" cy="12" r="9" stroke={color} strokeOpacity="0.2" strokeWidth="2" fill="none" />
      <path d="M21 12a9 9 0 0 0-9-9" stroke={color} strokeWidth="2" strokeLinecap="round" fill="none" />
    </svg>);

}

/* ---------- Chip / Tag / Badge / Pill ---------- */
function Chip({ children, onRemove, active, icon, dot, onClick, size = "md" }) {
  const sizes = { sm: { h: 22, px: 8, fs: 11 }, md: { h: 28, px: 12, fs: 12 }, lg: { h: 32, px: 14, fs: 13 } };
  const s = sizes[size];
  return (
    <span
      onClick={onClick}
      style={{
        height: s.h, padding: `0 ${s.px}px`, fontSize: s.fs,
        display: "inline-flex", alignItems: "center", gap: 6,
        background: active ? "var(--ink)" : "var(--bg-2)",
        color: active ? "var(--bg)" : "var(--ink)",
        border: "1px solid " + (active ? "var(--ink)" : "var(--line)"),
        borderRadius: "var(--r-pill)",
        fontFamily: "var(--sans)", fontWeight: 500, cursor: onClick ? "pointer" : "default",
        whiteSpace: "nowrap"
      }}>
      
      {dot && <i style={{ width: 6, height: 6, borderRadius: 999, background: dot }} />}
      {icon}
      {children}
      {onRemove &&
      <button onClick={(e) => {e.stopPropagation();onRemove();}}
      style={{ display: "inline-flex", marginLeft: 2, padding: 0, border: 0, background: "transparent", cursor: "pointer", color: "inherit" }}>
          <Icon.X size={11} />
        </button>
      }
    </span>);

}

function Badge({ children, tone = "neutral", style }) {
  const tones = {
    neutral: { bg: "var(--bg-2)", color: "var(--ink)", border: "var(--line)" },
    pos: { bg: "var(--pos-bg)", color: "var(--pos)", border: "transparent" },
    neg: { bg: "var(--neg-bg)", color: "var(--neg)", border: "transparent" },
    warn: { bg: "var(--warn-bg)", color: "var(--warn)", border: "transparent" },
    info: { bg: "var(--info-bg)", color: "var(--info)", border: "transparent" },
    grad: { bg: "transparent", color: "white", border: "transparent", grad: true },
    ink: { bg: "var(--ink)", color: "var(--bg)", border: "var(--ink)" }
  };
  const t = tones[tone];
  return (
    <span style={{
      fontFamily: "var(--mono)", fontSize: 10, letterSpacing: "0.08em", textTransform: "uppercase",
      fontWeight: 700, padding: "3px 8px",
      background: t.grad ? "var(--brand-grad)" : t.bg,
      color: t.color, border: `1px solid ${t.border}`,
      borderRadius: "var(--r-sharp)", display: "inline-flex", alignItems: "center", gap: 6,
      ...style
    }}>{children}</span>);

}

function Pill({ children, tone = "neutral", dot }) {
  const tones = {
    neutral: { bg: "var(--bg-2)", color: "var(--ink-2)" },
    pos: { bg: "var(--pos-bg)", color: "var(--pos)" },
    neg: { bg: "var(--neg-bg)", color: "var(--neg)" },
    warn: { bg: "var(--warn-bg)", color: "var(--warn)" },
    info: { bg: "var(--info-bg)", color: "var(--info)" }
  };
  const t = tones[tone];
  const dotColor = { neutral: "var(--ink-3)", pos: "var(--pos)", neg: "var(--neg)", warn: "var(--warn)", info: "var(--info)" }[tone];
  return (
    <span style={{
      display: "inline-flex", alignItems: "center", gap: 6,
      padding: "4px 10px", borderRadius: 999,
      background: t.bg, color: t.color,
      fontSize: 12, fontWeight: 500, whiteSpace: "nowrap"
    }}>
      {dot && <i style={{ width: 6, height: 6, borderRadius: 999, background: dotColor }} />}
      {children}
    </span>);

}

/* ---------- Avatar ---------- */
function Avatar({ name = "", size = 32, tint, ring, src }) {
  const initials = name.split(/\s+/).slice(0, 2).map((s) => s[0]).join("").toUpperCase();
  const tints = ["var(--ph-pink)", "var(--ph-teal)", "var(--ph-magenta)", "var(--ph-orange)", "var(--ph-ink)"];
  const idx = (name.charCodeAt(0) || 0) % tints.length;
  return (
    <span style={{
      width: size, height: size, borderRadius: 999,
      background: src ? `url(${src}) center/cover` : tint || tints[idx],
      color: "white", display: "inline-flex", alignItems: "center", justifyContent: "center",
      fontFamily: "var(--sans)", fontWeight: 600, fontSize: Math.round(size * 0.38),
      letterSpacing: "-0.02em", flexShrink: 0,
      boxShadow: ring ? "0 0 0 2px var(--bg), 0 0 0 3px var(--ink)" : undefined
    }}>{!src && initials}</span>);

}

/* ---------- Inputs ---------- */
function Field({ label, hint, error, required, children, style }) {
  return (
    <label className="col gap-6" style={{ minWidth: 0, ...style }}>
      {label &&
      <span className="row gap-6" style={{
        fontFamily: "var(--mono)", fontSize: 11, fontWeight: 700,
        letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--ink)"
      }}>
          {label}
          {required && <i style={{ color: "var(--grad-4)" }}>*</i>}
        </span>
      }
      {children}
      {error ?
      <span style={{ fontSize: 12, color: "var(--neg)" }}>{error}</span> :
      hint ?
      <span style={{ fontSize: 12, color: "var(--ink-3)" }}>{hint}</span> :
      null}
    </label>);

}

function Input({ icon, suffix, value, onChange, placeholder, type = "text", error, fullWidth = true, style, ...rest }) {
  return (
    <div style={{
      display: "flex", alignItems: "center", gap: 8,
      height: "var(--d-input-h)", padding: "0 var(--d-input-px)",
      background: "var(--bg)",
      border: `1px solid ${error ? "var(--neg)" : "var(--line)"}`,
      borderRadius: "var(--r-sharp)", color: "var(--ink)",
      transition: "border-color 200ms ease",
      width: fullWidth ? "100%" : "auto", ...style
    }}
    onFocus={(e) => e.currentTarget.style.borderColor = "var(--ink)"}
    onBlur={(e) => e.currentTarget.style.borderColor = error ? "var(--neg)" : "var(--line)"}>
      
      {icon && <span style={{ color: "var(--ink-3)", display: "inline-flex" }}>{icon}</span>}
      <input
        type={type} value={value} onChange={onChange} placeholder={placeholder}
        style={{
          flex: 1, minWidth: 0, height: "100%", border: 0, outline: 0,
          background: "transparent", color: "inherit",
          fontFamily: "var(--sans)", fontSize: 14, padding: 0
        }}
        {...rest} />
      
      {suffix && <span style={{ color: "var(--ink-3)", fontSize: 12, fontFamily: "var(--mono)" }}>{suffix}</span>}
    </div>);

}

function Textarea({ value, onChange, placeholder, rows = 4, error, ...rest }) {
  return (
    <textarea
      value={value} onChange={onChange} placeholder={placeholder} rows={rows}
      style={{
        width: "100%", padding: "12px 16px", resize: "vertical",
        background: "var(--bg)", color: "var(--ink)",
        border: `1px solid ${error ? "var(--neg)" : "var(--line)"}`,
        borderRadius: "var(--r-sharp)",
        fontFamily: "var(--sans)", fontSize: 14, lineHeight: 1.55, outline: 0,
        transition: "border-color 200ms ease"
      }}
      onFocus={(e) => e.currentTarget.style.borderColor = "var(--ink)"}
      onBlur={(e) => e.currentTarget.style.borderColor = error ? "var(--neg)" : "var(--line)"}
      {...rest} />);


}

function Select({ value, onChange, options = [], placeholder = "Select…", fullWidth = true, style }) {
  return (
    <div style={{ position: "relative", width: fullWidth ? "100%" : "auto", ...style }}>
      <select value={value} onChange={onChange}
      style={{
        appearance: "none", width: "100%",
        height: "var(--d-input-h)", padding: "0 36px 0 var(--d-input-px)",
        background: "var(--bg)", color: "var(--ink)",
        border: "1px solid var(--line)", borderRadius: "var(--r-sharp)",
        fontFamily: "var(--sans)", fontSize: 14, outline: 0, cursor: "pointer"
      }}>
        
        {placeholder && <option value="">{placeholder}</option>}
        {options.map((o) => {
          const v = typeof o === "string" ? o : o.value;
          const l = typeof o === "string" ? o : o.label;
          return <option key={v} value={v}>{l}</option>;
        })}
      </select>
      <span style={{ position: "absolute", right: 12, top: "50%", transform: "translateY(-50%)", pointerEvents: "none", color: "var(--ink-3)" }}>
        <Icon.ChevronDown size={14} />
      </span>
    </div>);

}

/* ---------- Toggle / Checkbox / Radio ---------- */
function Toggle({ checked, onChange, label, description }) {
  return (
    <label className="row gap-12" style={{ alignItems: "flex-start", cursor: "pointer" }}>
      <span
        role="switch" aria-checked={checked}
        onClick={() => onChange && onChange(!checked)}
        style={{
          width: 36, height: 20, padding: 2, marginTop: 2,
          background: checked ? "var(--ink)" : "var(--bg-3)",
          borderRadius: 999, position: "relative",
          transition: "background 220ms ease", flexShrink: 0
        }}>
        
        <span style={{
          position: "absolute", top: 2, left: checked ? 18 : 2,
          width: 16, height: 16, borderRadius: 999,
          background: checked ? "var(--bg)" : "var(--bg)",
          backgroundImage: checked ? "var(--brand-grad)" : "none",
          transition: "left 220ms ease"
        }} />
      </span>
      {(label || description) &&
      <span className="col gap-4">
          {label && <span style={{ fontSize: 14, fontWeight: 500 }}>{label}</span>}
          {description && <span style={{ fontSize: 13, color: "var(--ink-2)" }}>{description}</span>}
        </span>
      }
    </label>);

}

function Checkbox({ checked, onChange, label, indeterminate }) {
  return (
    <label className="row gap-10" style={{ cursor: "pointer", gap: 10, alignItems: "center" }}>
      <span
        role="checkbox" aria-checked={checked}
        onClick={() => onChange && onChange(!checked)}
        style={{
          width: 16, height: 16, borderRadius: 3,
          border: "1px solid " + (checked || indeterminate ? "var(--ink)" : "var(--line-2)"),
          background: checked || indeterminate ? "var(--ink)" : "var(--bg)",
          color: "var(--bg)", display: "inline-flex", alignItems: "center", justifyContent: "center",
          flexShrink: 0
        }}>
        
        {checked && <Icon.Check size={11} stroke={2.5} />}
        {indeterminate && !checked && <span style={{ width: 8, height: 1.5, background: "var(--bg)" }} />}
      </span>
      {label && <span style={{ fontSize: 14 }}>{label}</span>}
    </label>);

}

function Radio({ checked, onChange, label }) {
  return (
    <label className="row gap-10" style={{ cursor: "pointer", gap: 10, alignItems: "center" }}>
      <span
        onClick={onChange}
        style={{
          width: 16, height: 16, borderRadius: 999,
          border: "1px solid " + (checked ? "var(--ink)" : "var(--line-2)"),
          background: "var(--bg)", display: "inline-flex", alignItems: "center", justifyContent: "center",
          flexShrink: 0
        }}>
        
        {checked && <span style={{ width: 8, height: 8, borderRadius: 999, background: "var(--ink)" }} />}
      </span>
      {label && <span style={{ fontSize: 14 }}>{label}</span>}
    </label>);

}

/* ---------- Slider ---------- */
function Slider({ value, onChange, min = 0, max = 100, step = 1, suffix }) {
  const pct = (value - min) / (max - min) * 100;
  return (
    <div className="col gap-8" style={{ width: "100%" }}>
      <div style={{ position: "relative", height: 24, display: "flex", alignItems: "center" }}>
        <div style={{ position: "absolute", left: 0, right: 0, height: 2, background: "var(--line)", borderRadius: 999 }} />
        <div style={{ position: "absolute", left: 0, width: `${pct}%`, height: 2, background: "var(--brand-grad)", borderRadius: 999 }} />
        <input
          type="range" min={min} max={max} step={step} value={value}
          onChange={(e) => onChange && onChange(Number(e.target.value))}
          style={{ position: "absolute", left: 0, right: 0, width: "100%", opacity: 0, height: 24, margin: 0, cursor: "pointer" }} />
        
        <span style={{
          position: "absolute", left: `calc(${pct}% - 8px)`, width: 16, height: 16,
          borderRadius: 999, background: "var(--ink)", border: "2px solid var(--bg)",
          boxShadow: "0 0 0 1px var(--ink)", pointerEvents: "none"
        }} />
      </div>
      <div className="row between" style={{ fontFamily: "var(--mono)", fontSize: 11, color: "var(--ink-3)", letterSpacing: "0.06em" }}>
        <span>{min}{suffix}</span>
        <span style={{ color: "var(--ink)" }}>{value}{suffix}</span>
        <span>{max}{suffix}</span>
      </div>
    </div>);

}

/* ---------- File Pick ---------- */
function FilePick({ label = "Drop a file or browse", hint, onPick }) {
  const [drag, setDrag] = useState(false);
  return (
    <div
      onDragOver={(e) => {e.preventDefault();setDrag(true);}}
      onDragLeave={() => setDrag(false)}
      onDrop={(e) => {e.preventDefault();setDrag(false);onPick && onPick(e.dataTransfer.files);}}
      style={{
        border: `1px dashed ${drag ? "var(--ink)" : "var(--line-2)"}`,
        background: drag ? "var(--bg-2)" : "transparent",
        padding: 32, borderRadius: "var(--r-sharp)", textAlign: "center",
        transition: "background 200ms ease, border-color 200ms ease",
        cursor: "pointer"
      }}>
      
      <div style={{ display: "inline-flex", padding: 10, background: "var(--bg-2)", borderRadius: 999, marginBottom: 12, color: "var(--ink-2)" }}>
        <Icon.Upload size={18} />
      </div>
      <div style={{ fontSize: 14, fontWeight: 500 }}>{label}</div>
      {hint && <div style={{ fontSize: 12, color: "var(--ink-3)", marginTop: 4 }}>{hint}</div>}
    </div>);

}

/* ---------- Tabs ---------- */
function Tabs({ value, onChange, items = [], variant = "underline" }) {
  if (variant === "pills") {
    return (
      <div className="row gap-6" style={{ background: "var(--bg-2)", padding: 4, borderRadius: "var(--r-pill)", width: "fit-content" }}>
        {items.map((it) => {
          const v = typeof it === "string" ? it : it.value;
          const l = typeof it === "string" ? it : it.label;
          const active = value === v;
          return (
            <button key={v} onClick={() => onChange(v)} style={{
              border: 0, background: active ? "var(--bg)" : "transparent",
              color: "var(--ink)", padding: "6px 14px", fontSize: 13, fontWeight: 500,
              borderRadius: 999, cursor: "pointer", fontFamily: "var(--sans)",
              boxShadow: active ? "0 0 0 1px var(--line)" : "none"
            }}>{l}</button>);

        })}
      </div>);

  }
  return (
    <div className="row" style={{ gap: 4, borderBottom: "1px solid var(--line)" }}>
      {items.map((it) => {
        const v = typeof it === "string" ? it : it.value;
        const l = typeof it === "string" ? it : it.label;
        const c = typeof it === "string" ? null : it.count;
        const active = value === v;
        return (
          <button key={v} onClick={() => onChange(v)} style={{
            border: 0, background: "transparent",
            color: active ? "var(--ink)" : "var(--ink-3)",
            padding: "10px 14px", fontSize: 14, fontWeight: 500,
            cursor: "pointer", fontFamily: "var(--sans)",
            borderBottom: `2px solid ${active ? "var(--ink)" : "transparent"}`,
            marginBottom: -1, display: "inline-flex", alignItems: "center", gap: 8,
            transition: "color 200ms ease"
          }}>
            {l}
            {c != null && <span style={{ fontFamily: "var(--mono)", fontSize: 10, color: "var(--ink-3)" }}>{c}</span>}
          </button>);

      })}
    </div>);

}

function Segmented({ value, onChange, items = [] }) {
  return (
    <div className="row" style={{ border: "1px solid var(--line)", borderRadius: "var(--r-sharp)", padding: 2, background: "var(--bg)", height: "var(--d-btn-h)", boxSizing: "border-box" }}>
      {items.map((it) => {
        const v = typeof it === "string" ? it : it.value;
        const l = typeof it === "string" ? it : it.label;
        const ic = typeof it === "string" ? null : it.icon;
        const active = value === v;
        return (
          <button key={v} onClick={() => onChange(v)} style={{
            border: 0, background: active ? "var(--ink)" : "transparent",
            color: active ? "var(--bg)" : "var(--ink-2)",
            padding: "0 14px", height: "100%", fontSize: 13, fontWeight: 500, fontFamily: "var(--sans)",
            cursor: "pointer", borderRadius: 2, display: "inline-flex", alignItems: "center", gap: 6,
            transition: "background 200ms ease, color 200ms ease"
          }}>
            {ic}
            {l}
          </button>);

      })}
    </div>);

}

/* ---------- Accordion ---------- */
function Accordion({ items = [], defaultOpen = [] }) {
  const [open, setOpen] = useState(new Set(defaultOpen));
  const toggle = (i) => {
    const next = new Set(open);
    next.has(i) ? next.delete(i) : next.add(i);
    setOpen(next);
  };
  return (
    <div className="col" style={{ borderTop: "1px solid var(--line)" }}>
      {items.map((it, i) => {
        const isOpen = open.has(i);
        return (
          <div key={i} style={{ borderBottom: "1px solid var(--line)" }}>
            <button onClick={() => toggle(i)} style={{
              width: "100%", border: 0, background: "transparent", color: "var(--ink)",
              padding: "18px 0", display: "flex", alignItems: "center", justifyContent: "space-between",
              fontFamily: "var(--sans)", fontSize: 16, fontWeight: 600, cursor: "pointer", textAlign: "left"
            }}>
              <span>{it.title}</span>
              <span style={{ transform: isOpen ? "rotate(180deg)" : "rotate(0)", transition: "transform 220ms ease", color: "var(--ink-2)" }}>
                <Icon.ChevronDown size={16} />
              </span>
            </button>
            {isOpen &&
            <div style={{ paddingBottom: 18, color: "var(--ink-2)", fontSize: 14, lineHeight: 1.6 }}>
                {it.body}
              </div>
            }
          </div>);

      })}
    </div>);

}

/* ---------- Breadcrumb ---------- */
function Breadcrumb({ items = [] }) {
  return (
    <nav className="row gap-8" style={{ fontFamily: "var(--mono)", fontSize: 11, letterSpacing: "0.06em", textTransform: "uppercase", color: "var(--ink-3)" }}>
      {items.map((it, i) =>
      <React.Fragment key={i}>
          <span style={{
          color: i === items.length - 1 ? "var(--ink)" : "var(--ink-3)",
          cursor: it.onClick ? "pointer" : "default"
        }} onClick={it.onClick}>{it.label}</span>
          {i < items.length - 1 && <span style={{ opacity: 0.4 }}>/</span>}
        </React.Fragment>
      )}
    </nav>);

}

/* ---------- Kbd / Spinner re-export ---------- */
function Kbd({ children }) {
  return <span className="kbd">{children}</span>;
}

Object.assign(window, {
  Button, IconBtn, Spinner, Chip, Badge, Pill, Avatar,
  Field, Input, Textarea, Select, Toggle, Checkbox, Radio, Slider, FilePick,
  Tabs, Segmented, Accordion, Breadcrumb, Kbd
});