// HireArt Onboarding Form — component library
// Helpers + primitives used by the main form

const { useState, useRef, useEffect, useMemo } = React;

const ICON_BASE = "assets/icons/";
const __ICON_SRC = (name) => (window.__resources && window.__resources["icon-" + name]) || `${ICON_BASE}${name}.svg`;

// ---------- Icon ----------
function Icon({ name, size = 18, color, style = {}, className = "" }) {
  const invert = color === "#fff" || color === "white";
  return (
    <img
      src={__ICON_SRC(name)}
      alt=""
      width={size}
      height={size}
      className={`icon ${invert ? "icon-invert" : ""} ${className}`}
      style={style}
    />
  );
}

// ---------- Button ----------
function Button({ children, variant = "primary", size = "md", iconLeft, iconRight, disabled, onClick, type = "button", style = {}, className = "", "aria-label": ariaLabel }) {
  const iconOnly = !children && (iconLeft || iconRight);
  const iconClass = iconOnly
    ? "btn-icon-only"
    : iconLeft && iconRight
      ? "btn-icon-both"
      : iconLeft
        ? "btn-icon-start"
        : iconRight
          ? "btn-icon-end"
          : "";
  const cls = `btn btn-${variant} ${size !== "md" ? `btn-${size}` : ""} ${iconClass} ${className}`.trim();
  // Per DS spec: most variants have neutral-100 (black) text/icons; accent (purple) has neutral-10 (white)
  const iconColor = variant === "accent" ? "#fff" : undefined;
  const iconSize = size === "sm" ? 16 : size === "lg" ? 22 : 20;
  return (
    <button type={type} disabled={disabled} onClick={onClick} className={cls} style={style} aria-label={ariaLabel}>
      {iconLeft && <Icon name={iconLeft} size={iconSize} color={iconColor} />}
      {children}
      {iconRight && <Icon name={iconRight} size={iconSize} color={iconColor} />}
    </button>
  );
}

// ---------- Input / Textarea ----------
function Input({ value, onChange, onBlur, placeholder, type = "text", error, className = "", style = {}, id, ...rest }) {
  return (
    <input
      id={id}
      type={type}
      value={value ?? ""}
      onChange={(e) => onChange?.(e.target.value)}
      onBlur={onBlur}
      placeholder={placeholder}
      className={`input ${error ? "error" : ""} ${className}`}
      style={style}
      {...rest}
    />
  );
}
function Textarea({ value, onChange, placeholder, rows = 3, error, className = "", style = {} }) {
  return (
    <textarea
      value={value ?? ""}
      onChange={(e) => onChange?.(e.target.value)}
      placeholder={placeholder}
      rows={rows}
      className={`textarea ${error ? "error" : ""} ${className}`}
      style={style}
    />
  );
}

// ---------- Label / Field ----------
function Label({ children, required, optional, htmlFor, className = "" }) {
  return (
    <label htmlFor={htmlFor} className={`label ${required ? "label-required" : ""} ${className}`}>
      {children}
      {optional && <span className="label-optional">(optional)</span>}
    </label>
  );
}

// ---------- Radio (standard, vertical list) ----------
function RadioGroup({ value, onChange, children, name, style }) {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 4, ...(style || {}) }} data-radio-group={name}>
      {React.Children.map(children, (child) => {
        if (!React.isValidElement(child)) return child;
        return React.cloneElement(child, {
          checked: child.props.value === value,
          onSelect: () => onChange?.(child.props.value),
          name,
        });
      })}
    </div>
  );
}
function RadioItem({ value, label, description, checked, onSelect, name, id }) {
  const rid = id || `${name}-${value}`;
  return (
    <label className="radio-row" htmlFor={rid}>
      <input type="radio" id={rid} name={name} checked={!!checked} onChange={onSelect} />
      <span className="radio-dot" />
      <span className="radio-label">
        {label}
        {description && <span className="radio-label-description">{description}</span>}
      </span>
    </label>
  );
}

// ---------- RadioCardGroup ----------
function RadioCardGroup({ value, onChange, children, name, layout = "vertical", variant = "standard" }) {
  const className = `radio-card-group ${layout === "horizontal" ? "horizontal" : layout === "grid" ? "grid" : ""} ${variant === "bold" ? "bold" : ""}`.trim();
  return (
    <div className={className} data-radio-card-group={name}>
      {React.Children.map(children, (child) => {
        if (!React.isValidElement(child)) return child;
        return React.cloneElement(child, {
          checked: child.props.value === value,
          onSelect: () => onChange?.(child.props.value),
          name,
        });
      })}
    </div>
  );
}
function RadioCard({ value, title, description, icon, badge, checked, onSelect, name, id, children }) {
  const rid = id || `${name}-${value}`;
  return (
    <label className={`radio-card ${checked ? "selected" : ""}`} htmlFor={rid}>
      <input type="radio" id={rid} name={name} checked={!!checked} onChange={onSelect} />
      <span className="radio-card-dot" />
      {icon && (
        <span className="radio-card-icon">
          <Icon name={icon} size={20} />
        </span>
      )}
      <div className="radio-card-content">
        <div className="radio-card-title">
          <span>{title}</span>
          {badge && <span className={`badge ${badge.variant ? `badge-${badge.variant}` : ""}`}>{badge.label}</span>}
        </div>
        {description && <div className="radio-card-description">{description}</div>}
        {children}
      </div>
    </label>
  );
}

// ---------- Checkbox ----------
function Checkbox({ checked, onChange, label, description, id, name, disabled }) {
  return (
    <label className="checkbox-row" htmlFor={id}>
      <input
        type="checkbox"
        id={id}
        name={name}
        checked={!!checked}
        disabled={disabled}
        onChange={(e) => onChange?.(e.target.checked)}
      />
      <span className="checkbox-box">
        <svg className="checkbox-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
          <polyline points="20 6 9 17 4 12" />
        </svg>
      </span>
      <span className="checkbox-label">
        {label}
        {description && <span className="checkbox-label-description">{description}</span>}
      </span>
    </label>
  );
}

// ---------- Tabs ----------
function Tabs({ value, onChange, children }) {
  return (
    <div className="tabs-list" role="tablist">
      {React.Children.map(children, (child) => {
        if (!React.isValidElement(child)) return child;
        return React.cloneElement(child, {
          active: child.props.value === value,
          onSelect: () => onChange?.(child.props.value),
        });
      })}
    </div>
  );
}
function Tab({ value, label, active, onSelect }) {
  return (
    <button type="button" className={`tab-trigger ${active ? "active" : ""}`} onClick={onSelect} role="tab" aria-selected={active}>
      {label}
    </button>
  );
}

// ---------- Select / SearchableSelect ----------
function SearchableSelect({ value, onChange, items = [], placeholder = "Select…", searchPlaceholder = "Search…", emptyMessage = "Nothing found.", renderItem, renderSelected, selectedOverride, onCreateNew, createLabel, createPlacement = "top", popoverWidth, size = "md" }) {
  const [open, setOpen] = useState(false);
  const [query, setQuery] = useState("");
  const ref = useRef();

  useEffect(() => {
    if (!open) return;
    function onClick(e) { if (ref.current && !ref.current.contains(e.target)) setOpen(false); }
    document.addEventListener("mousedown", onClick);
    return () => document.removeEventListener("mousedown", onClick);
  }, [open]);

  const filtered = useMemo(() => {
    if (!query.trim()) return items;
    const q = query.toLowerCase();
    return items.filter(it => (it.label || "").toLowerCase().includes(q));
  }, [items, query]);

  const selected = items.find(it => it.id === value);

  return (
    <div ref={ref} style={{ position: "relative", width: "100%" }}>
      <button type="button" className={`select-trigger ${!selected && !selectedOverride ? "placeholder" : ""}`} onClick={() => setOpen(o => !o)}>
        <span style={{ flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
          {selectedOverride
            ? selectedOverride
            : (selected ? (renderSelected ? renderSelected(selected) : selected.label) : placeholder)}
        </span>
        <Icon name="chevron-down" size={16} className="chevron" />
      </button>
      {open && (
        <div className="popover" style={{ width: popoverWidth || "100%" }}>
          <div className="popover-search">
            <input autoFocus placeholder={searchPlaceholder} value={query} onChange={(e) => setQuery(e.target.value)} />
          {createPlacement === "top" && onCreateNew && (
            <button
              type="button"
              className="popover-create-link"
              onClick={() => { onCreateNew(); setOpen(false); }}
            >
              <Icon name="plus" size={13} />
              {createLabel || "Add new"}
            </button>
          )}
          </div>
          {filtered.length === 0 ? (
            <div className="popover-empty">{emptyMessage}</div>
          ) : (
            filtered.map(it => (
              <div
                key={it.id}
                className={`popover-item ${it.id === value ? "selected" : ""}`}
                onClick={() => { onChange?.(it.id); setOpen(false); setQuery(""); }}
              >
                {renderItem ? renderItem(it) : it.label}
              </div>
            ))
          )}
          {createPlacement === "bottom" && onCreateNew && (
            <div className="popover-item create" onClick={() => { onCreateNew(); setOpen(false); }}>
              <Icon name="plus" size={14} /> {createLabel || "Add new"}
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// ---------- Dialog ----------
function Dialog({ open, onClose, title, description, icon, children, footer }) {
  useEffect(() => {
    function onKey(e) { if (e.key === "Escape") onClose?.(); }
    if (open) document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div className="dialog-overlay" onClick={(e) => { if (e.target === e.currentTarget) onClose?.(); }}>
      <div className="dialog">
        <div className="dialog-header">
          <h3 className="dialog-title">
            {icon && <Icon name={icon} size={20} />}
            {title}
          </h3>
          {description && <p className="dialog-description">{description}</p>}
        </div>
        <div className="dialog-body">{children}</div>
        {footer && <div className="dialog-footer">{footer}</div>}
      </div>
    </div>
  );
}

// ---------- Alert ----------
function Alert({ variant = "info", icon, children }) {
  const defaultIcon = { warn: "alert-triangle", info: "info", error: "alert-circle", brand: "info" }[variant];
  return (
    <div className={`alert alert-${variant}`}>
      <Icon name={icon || defaultIcon} size={18} className="alert-icon" />
      <div>{children}</div>
    </div>
  );
}

// ---------- Badge ----------
function Badge({ children, variant }) {
  return <span className={`badge ${variant ? `badge-${variant}` : ""}`}>{children}</span>;
}

// ---------- Calendar (simple) ----------
function Calendar({ value, onChange }) {
  const today = new Date();
  const [viewMonth, setViewMonth] = useState(value ? new Date(value.getFullYear(), value.getMonth(), 1) : new Date(today.getFullYear(), today.getMonth(), 1));
  const monthName = viewMonth.toLocaleString("default", { month: "long", year: "numeric" });
  const firstDay = viewMonth.getDay();
  const daysInMonth = new Date(viewMonth.getFullYear(), viewMonth.getMonth() + 1, 0).getDate();
  const days = [];
  for (let i = 0; i < firstDay; i++) days.push(null);
  for (let d = 1; d <= daysInMonth; d++) days.push(d);
  const ymd = (y, m, d) => `${y}-${String(m+1).padStart(2,"0")}-${String(d).padStart(2,"0")}`;
  const selKey = value ? ymd(value.getFullYear(), value.getMonth(), value.getDate()) : "";
  return (
    <div style={{ padding: 12, minWidth: 280 }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 10 }}>
        <button type="button" className="btn btn-ghost btn-sm" onClick={() => setViewMonth(new Date(viewMonth.getFullYear(), viewMonth.getMonth() - 1, 1))}>
          <Icon name="chevron-left" size={14} />
        </button>
        <div style={{ fontWeight: 700, fontSize: 14 }}>{monthName}</div>
        <button type="button" className="btn btn-ghost btn-sm" onClick={() => setViewMonth(new Date(viewMonth.getFullYear(), viewMonth.getMonth() + 1, 1))}>
          <Icon name="chevron-right" size={14} />
        </button>
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(7,1fr)", gap: 2, marginBottom: 4 }}>
        {["S","M","T","W","T","F","S"].map((d, i) => (
          <div key={i} style={{ fontSize: 11, fontWeight: 700, color: "var(--color-neutral-60)", textAlign: "center", padding: "4px 0" }}>{d}</div>
        ))}
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(7,1fr)", gap: 2 }}>
        {days.map((d, i) => {
          if (d === null) return <div key={i} />;
          const key = ymd(viewMonth.getFullYear(), viewMonth.getMonth(), d);
          const isSel = key === selKey;
          const isToday = key === ymd(today.getFullYear(), today.getMonth(), today.getDate());
          return (
            <button
              key={i}
              type="button"
              onClick={() => onChange?.(new Date(viewMonth.getFullYear(), viewMonth.getMonth(), d))}
              style={{
                padding: "6px 0",
                fontSize: 13,
                border: isSel ? "1.5px solid var(--color-neutral-100)" : "1.5px solid transparent",
                background: isSel ? "var(--color-red-60)" : "transparent",
                color: isSel ? "#fff" : "var(--color-neutral-100)",
                borderRadius: 6,
                cursor: "pointer",
                fontWeight: isToday ? 700 : 500,
              }}
            >
              {d}
            </button>
          );
        })}
      </div>
    </div>
  );
}

// Export to window
Object.assign(window, {
  Icon, Button, Input, Textarea, Label,
  RadioGroup, RadioItem, RadioCardGroup, RadioCard,
  Tabs, Tab, SearchableSelect, Dialog, Alert, Badge, Calendar, Checkbox,
});
