// Hotel Walks — shared UI primitives.
// Use sparingly; layout is mostly bespoke per screen.

const UI = (() => {
  const C = {
    ink: "var(--ink)",
    bone: "var(--bone)",
    bone2: "var(--bone-2)",
    rule: "var(--rule)",
    ruleStrong: "var(--rule-strong)",
    muted: "var(--muted)",
    warn: "var(--warn)",
    good: "var(--good)",
  };

  function Caps({ children, color, style, className }) {
    return (
      <span className={"caps" + (className ? " " + className : "")} style={{ color: color || C.muted, ...style }}>{children}</span>
    );
  }

  function SerifI({ children, size = 24, style }) {
    return (
      <span className="serif-i" style={{ fontSize: size, lineHeight: 1.05, ...style }}>{children}</span>
    );
  }

  // Primary button — Ink filled on Bone, or Bone filled on Ink.
  function Btn({ children, onClick, kind = "primary", size = "md", disabled, style, type, full, as = "button", href }) {
    const sizes = {
      sm: { padding: "9px 14px",  fontSize: 12, letterSpacing: "0.08em" },
      md: { padding: "13px 22px", fontSize: 12, letterSpacing: "0.12em" },
      lg: { padding: "18px 28px", fontSize: 13, letterSpacing: "0.14em" },
    };
    const base = {
      ...sizes[size],
      fontFamily: "'JetBrains Mono', monospace",
      textTransform: "uppercase",
      border: "1px solid " + C.ink,
      borderRadius: 0,
      cursor: disabled ? "not-allowed" : "pointer",
      opacity: disabled ? 0.4 : 1,
      transition: "background 0.12s, color 0.12s, border-color 0.12s",
      width: full ? "100%" : undefined,
      display: "inline-block",
      textAlign: "center",
      textDecoration: "none",
      whiteSpace: "nowrap",
    };
    const kinds = {
      primary: { background: C.ink, color: C.bone },
      ghost:   { background: "transparent", color: C.ink },
      danger:  { background: "transparent", color: C.warn, borderColor: C.warn },
      onInk:   { background: C.bone, color: C.ink, borderColor: C.bone },
      onInkGhost: { background: "transparent", color: C.bone, borderColor: C.bone },
    };
    const Tag = as;
    return (
      <Tag
        type={Tag === "button" ? (type || "button") : undefined}
        href={href}
        onClick={disabled ? undefined : onClick}
        className={`hw-btn hw-btn-${kind}`}
        style={{ ...base, ...kinds[kind], ...style }}>
        {children}
      </Tag>
    );
  }

  // Field — label sits as a caps row above the underlined input.
  function Field({ label, suffix, children, hint, style }) {
    return (
      <label style={{ display: "block", ...style }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 8 }}>
          <Caps>{label}</Caps>
          {suffix && <Caps>{suffix}</Caps>}
        </div>
        {children}
        {hint && <div style={{ marginTop: 6, fontSize: 12, color: C.muted }}>{hint}</div>}
      </label>
    );
  }

  function Input({ value, onChange, placeholder, type = "text", mono, style }) {
    return (
      <input
        type={type}
        value={value}
        placeholder={placeholder}
        onChange={onChange}
        style={{
          width: "100%",
          background: "transparent",
          border: "none",
          borderBottom: "1px solid " + C.ink,
          padding: "10px 0 8px",
          fontSize: 18,
          color: C.ink,
          fontFamily: mono ? "'JetBrains Mono', monospace" : "inherit",
          outline: "none",
          borderRadius: 0,
          ...style,
        }}
      />
    );
  }

  // Numeric stepper — for room counts, rates, days
  function Stepper({ value, onChange, min = 0, max = 99, step = 1, prefix, mono = true, width = 140 }) {
    const v = value;
    const set = (n) => onChange(Math.max(min, Math.min(max, n)));
    return (
      <div style={{
        display: "inline-flex", alignItems: "stretch",
        border: "1px solid " + C.ink, width,
      }}>
        <button onClick={() => set(v - step)} style={{ background: "transparent", border: "none", padding: "10px 12px", color: C.ink, fontFamily: "'JetBrains Mono', monospace" }}>–</button>
        <div style={{
          flex: 1, textAlign: "center", padding: "10px 0",
          borderLeft: "1px solid " + C.ink, borderRight: "1px solid " + C.ink,
          fontFamily: mono ? "'JetBrains Mono', monospace" : "inherit",
          fontSize: 16,
        }}>{prefix}{v}</div>
        <button onClick={() => set(v + step)} style={{ background: "transparent", border: "none", padding: "10px 12px", color: C.ink, fontFamily: "'JetBrains Mono', monospace" }}>+</button>
      </div>
    );
  }

  // Small stroke icons paired with status pills — non-color-only signals.
  function PillIcon({ tone }) {
    const sw = 1.6;
    const common = { width: 11, height: 11, viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: sw, strokeLinecap: "square", strokeLinejoin: "round" };
    if (tone === "warn") return (
      <svg {...common}>
        <polygon points="6,1.2 11,10.8 1,10.8" />
        <line x1="6" y1="4.8" x2="6" y2="7.6" />
        <circle cx="6" cy="9.4" r="0.55" fill="currentColor" stroke="none" />
      </svg>
    );
    if (tone === "good") return (
      <svg {...common}>
        <polyline points="1.8,6.5 5,9 10.2,3" />
      </svg>
    );
    return null;
  }

  // Pill — for status badges. Filled (solid) for warn/good/filled; outline for neutral/muted.
  // Auto-prepends a small icon for warn/good tones.
  function Pill({ children, tone = "neutral", style, icon = "auto" }) {
    const tones = {
      neutral: { color: C.ink,  border: "1px solid " + C.ruleStrong, background: "transparent" },
      filled:  { color: C.bone, border: "1px solid " + C.ink,        background: C.ink },
      warn:    { color: C.bone, border: "1px solid " + C.warn,       background: C.warn },
      good:    { color: C.bone, border: "1px solid " + C.good,       background: C.good },
      muted:   { color: C.muted, border: "1px solid " + C.rule,      background: "transparent" },
    };
    const showIcon = icon === "auto" ? (tone === "warn" || tone === "good") : !!icon;
    return (
      <span style={{
        display: "inline-flex", alignItems: "center", gap: 6,
        padding: "5px 10px",
        fontFamily: "'JetBrains Mono', monospace",
        fontSize: 11, letterSpacing: "0.12em", textTransform: "uppercase",
        ...tones[tone], ...style,
      }}>
        {showIcon && <PillIcon tone={tone} />}
        {children}
      </span>
    );
  }

  // Toggle — for no-show, urgent etc.
  function Toggle({ on, onChange, label }) {
    return (
      <button onClick={() => onChange(!on)} style={{
        display: "inline-flex", alignItems: "center", gap: 10,
        background: "transparent", border: "none", padding: 0, color: C.ink,
      }}>
        <span style={{
          width: 36, height: 18, borderRadius: 10,
          background: on ? C.ink : "transparent",
          border: "1px solid " + C.ink,
          position: "relative", transition: "background 0.15s",
        }}>
          <span style={{
            position: "absolute", top: 2, left: on ? 19 : 2,
            width: 12, height: 12, borderRadius: 8,
            background: on ? C.bone : C.ink,
            transition: "left 0.15s",
          }}/>
        </span>
        {label && <span style={{ fontSize: 13 }}>{label}</span>}
      </button>
    );
  }

  // Plain horizontal rule
  function Hr({ tone = "default", style }) {
    return <hr style={{
      border: "none",
      borderTop: "1px solid " + (tone === "strong" ? C.ruleStrong : C.rule),
      margin: 0, ...style,
    }} />;
  }

  // Section heading — caps eyebrow + italic title
  function SectionHead({ eyebrow, title, sub, right, style }) {
    return (
      <div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between", gap: 24, ...style }}>
        <div>
          {eyebrow && <div style={{ marginBottom: 12 }}><Caps>{eyebrow}</Caps></div>}
          <div className="serif-i" style={{ fontSize: 38, lineHeight: 1, marginBottom: sub ? 10 : 0 }}>{title}</div>
          {sub && <div style={{ fontSize: 14, color: C.muted, maxWidth: 60 + "ch" }}>{sub}</div>}
        </div>
        {right}
      </div>
    );
  }

  // Money helpers — integer dollars look natural; fractions get 2 decimals.
  const money = (n) => {
    const v = Number(n);
    const hasFrac = Math.round(v * 100) !== Math.round(v) * 100;
    return "$" + v.toLocaleString(undefined, {
      minimumFractionDigits: hasFrac ? 2 : 0,
      maximumFractionDigits: 2,
    });
  };

  return { C, Caps, SerifI, Btn, Field, Input, Stepper, Pill, Toggle, Hr, SectionHead, money };
})();

window.UI = UI;
