/* global React, Icons */
// Blue Human UI components — styled via CSS classes in styles.css.

const cx = (...xs) => xs.filter(Boolean).join(" ");

/* ===== Button ===== */
const Button = ({
  variant = "solid", size, block, icon, iconRight, className, children, as = "button", href, ...rest
}) => {
  const cls = cx(
    "gs-btn",
    `gs-btn--${variant}`,
    size && `gs-btn--${size}`,
    block && "gs-btn--block",
    className
  );
  const inner = <>{icon}{children}{iconRight}</>;
  if (as === "a" || href) return <a className={cls} href={href} {...rest}>{inner}</a>;
  return <button className={cls} {...rest}>{inner}</button>;
};

const IconButton = ({ children, className, size, ...rest }) => (
  <button className={cx("gs-btn", "gs-btn--ghost", "gs-btn--icon", size && `gs-btn--${size}`, className)} {...rest}>
    {children}
  </button>
);

/* ===== Input ===== */
const Input = React.forwardRef(({ className, leading, trailing, ...rest }, ref) => {
  if (leading || trailing) {
    return (
      <label className={cx("gs-input-wrap", className)}>
        {leading}
        <input ref={ref} className="gs-input-bare" {...rest} />
        {trailing}
      </label>
    );
  }
  return <input ref={ref} className={cx("gs-input", className)} {...rest} />;
});

const Textarea = ({ className, ...rest }) => (
  <textarea className={cx("gs-textarea", className)} {...rest} />
);

// The label is tied to its single field (Input / Textarea / Select) so screen readers
// announce it and clicking it focuses the field; help/error text is its description.
const FormCtl = ({ label, help, error, required, children }) => {
  const auto = React.useId();
  const field = React.isValidElement(children) ? children : null;
  const id = field?.props.id || auto;
  const note = error || help ? `${id}-note` : undefined;
  const control = field ? React.cloneElement(field, { id, "aria-describedby": note, "aria-invalid": error ? true : undefined }) : children;
  return (
    <div className="gs-formctl">
      {label && (
        <label className="gs-label" htmlFor={field ? id : undefined}>
          {label}{required && <span aria-hidden="true" style={{ color: "var(--contrast)", marginLeft: 2 }}>*</span>}
        </label>
      )}
      {control}
      {error ? <span id={note} className="gs-error">{error}</span> : help && <span id={note} className="gs-help">{help}</span>}
    </div>
  );
};

/* ===== Card / Heading / Text ===== */
const Card = ({ flush, hover, className, style, children, ...rest }) => (
  <div className={cx("gs-card", flush && "gs-card--flush", hover && "gs-card--hover", className)} style={style} {...rest}>
    {children}
  </div>
);

const Heading = ({ size = "h3", serif, className, children, ...rest }) => {
  const Tag = size.startsWith("h") ? size : "div";
  return <Tag className={cx(`gs-${size}`, serif && "gs-serif", className)} {...rest}>{children}</Tag>;
};

const Text = ({ size, muted, subtle, serif, as = "p", className, children, ...rest }) => {
  const Tag = as;
  const base = size === "sm" ? "gs-text-sm" : size === "xs" ? "gs-text-xs" : size === "lg" ? "gs-text-lg" : "gs-text";
  return (
    <Tag className={cx(base, muted && "gs-text-muted", subtle && "gs-text-subtle", serif && "gs-serif", className)} {...rest}>
      {children}
    </Tag>
  );
};

const Divider = ({ vertical, className, style }) => (
  <div className={cx(vertical ? "gs-divider-v" : "gs-divider", className)} style={style} />
);

/* ===== Avatar ===== */
const Avatar = ({ size = "md", name, src, color, className, style }) => {
  const initials = name ? name.split(" ").slice(0, 2).map(s => s[0]).join("").toUpperCase() : "";
  return (
    <div className={cx("gs-avatar", `gs-avatar--${size}`, className)} style={{ background: color, ...style }}>
      {src ? <img src={src} alt={name} /> : initials}
    </div>
  );
};

const AvatarGroup = ({ children, className }) => (
  <div className={cx("gs-avatar-group", className)}>{children}</div>
);

/* ===== Badge ===== */
const Badge = ({ variant, size, leading, className, style, children }) => (
  <span className={cx("gs-badge", variant && `gs-badge--${variant}`, size && `gs-badge--${size}`, className)} style={style}>
    {leading}{children}
  </span>
);

/* ===== Progress ===== */
const Progress = ({ value = 0, max = 100, size, variant, className, style }) => {
  const pct = Math.min(100, Math.max(0, (value / max) * 100));
  return (
    <div className={cx("gs-progress", size === "lg" && "gs-progress--lg", className)} style={style}>
      <div className={cx("gs-progress-fill", variant && `gs-progress-fill--${variant}`)} style={{ width: `${pct}%` }} />
    </div>
  );
};

/* ===== Tabs ===== */
const Tabs = ({ tabs, value, onChange, className }) => (
  <div className={cx("gs-tabs", className)}>
    <div className="gs-tabs-list" role="tablist">
      {tabs.map(t => (
        <button
          key={t.value}
          role="tab"
          data-active={value === t.value}
          className="gs-tab"
          onClick={() => onChange?.(t.value)}
        >
          {t.icon}{t.label}{t.count != null && <span className="gs-badge gs-badge--outline">{t.count}</span>}
        </button>
      ))}
    </div>
  </div>
);

/* ===== Accordion ===== */
const Accordion = ({ items, allowMultiple = true, defaultOpen = [] }) => {
  const [open, setOpen] = React.useState(new Set(defaultOpen));
  const toggle = i => {
    setOpen(s => {
      const n = new Set(allowMultiple ? s : []);
      n.has(i) ? n.delete(i) : n.add(i);
      return n;
    });
  };
  return (
    <div className="gs-accordion">
      {items.map((it, i) => (
        <div key={i} className="gs-accordion-item">
          <button
            className="gs-accordion-trigger"
            aria-expanded={open.has(i)}
            onClick={() => toggle(i)}
          >
            <span style={{ display: "flex", alignItems: "center", gap: 12 }}>
              {it.icon}{it.title}
            </span>
            <span style={{ display: "flex", alignItems: "center", gap: 12 }}>
              {it.meta}
              <Icons.Chevron className="gs-accordion-chevron" size={18} />
            </span>
          </button>
          {open.has(i) && <div className="gs-accordion-content">{it.content}</div>}
        </div>
      ))}
    </div>
  );
};

/* ===== Checkbox / Radio / Switch ===== */
const Checkbox = ({ label, checked, onChange, value, className }) => (
  <label className={cx("gs-checkbox", className)}>
    <input type="checkbox" checked={!!checked} onChange={e => onChange?.(e.target.checked, value)} />
    <span className="gs-checkbox-box">
      {checked && <Icons.Check size={12} stroke={3} />}
    </span>
    {label && <span className="gs-checkbox-label">{label}</span>}
  </label>
);

const Radio = ({ label, checked, onChange, name, value, className }) => (
  <label className={cx("gs-radio", className)}>
    <input type="radio" name={name} checked={!!checked} onChange={() => onChange?.(value)} />
    <span className="gs-radio-dot" />
    {label && <span className="gs-checkbox-label">{label}</span>}
  </label>
);

const Switch = ({ checked, onChange }) => (
  <label className="gs-switch">
    <input type="checkbox" checked={!!checked} onChange={e => onChange?.(e.target.checked)} />
    <span className="gs-switch-track" />
  </label>
);

/* ===== Select ===== */
const Select = ({ options, value, onChange, className, ...rest }) => (
  <select className={cx("gs-select", className)} value={value ?? ""} onChange={e => onChange?.(e.target.value)} {...rest}>
    {options.map(o => (
      <option key={o.value} value={o.value}>{o.label}</option>
    ))}
  </select>
);

/* ===== Alert ===== */
const Alert = ({ variant, icon, title, children, className }) => (
  <div className={cx("gs-alert", variant && `gs-alert--${variant}`, className)}>
    {icon && <div style={{ paddingTop: 2 }}>{icon}</div>}
    <div style={{ flex: 1 }}>
      {title && <div style={{ fontWeight: 600, marginBottom: 4 }}>{title}</div>}
      <div style={{ fontSize: 13 }}>{children}</div>
    </div>
  </div>
);

/* ===== Stat tile ===== */
const Stat = ({ label, value, meta, icon }) => (
  <div className="gs-stat">
    <div className="flex items-center justify-between">
      <span className="gs-stat-label">{label}</span>
      {icon && <span style={{ color: "var(--text-muted)" }}>{icon}</span>}
    </div>
    <span className="gs-stat-value">{value}</span>
    {meta && <span className="gs-stat-meta">{meta}</span>}
  </div>
);

/* ===== Menu (popover) ===== */
const Menu = ({ trigger, items, align = "right" }) => {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const onDoc = e => { if (!ref.current?.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, [open]);
  return (
    <div ref={ref} style={{ position: "relative", display: "inline-block" }}>
      <span onClick={() => setOpen(o => !o)}>{trigger}</span>
      {open && (
        <div className="gs-menu" style={{
          position: "absolute",
          top: "calc(100% + 6px)",
          [align]: 0,
          zIndex: 100,
        }}>
          {items.map((it, i) => it.sep
            ? <div key={i} className="gs-menu-sep" />
            : <div key={i} className={cx("gs-menu-item", it.danger && "gs-menu-item--danger")} onClick={() => { it.onClick?.(); setOpen(false); }}>
                {it.icon}{it.label}
              </div>
          )}
        </div>
      )}
    </div>
  );
};

Object.assign(window, {
  cx, Button, IconButton, Input, Textarea, FormCtl,
  Card, Heading, Text, Divider,
  Avatar, AvatarGroup, Badge, Progress, Tabs, Accordion,
  Checkbox, Radio, Switch, Select, Alert, Stat, Menu,
});
