/* ============================================================
   Reframe Work Orders — shared UI primitives (JSX)
   Exports to window for the other view scripts.
   ============================================================ */
const { useState, useEffect, useRef, useMemo } = React;

/* ---- Responsive helper: true on phone-width viewports ------------------ */
function useIsMobile(breakpoint = 760) {
  const q = "(max-width: " + breakpoint + "px)";
  const get = () => (typeof window !== "undefined" && window.matchMedia ? window.matchMedia(q).matches : false);
  const [mobile, setMobile] = useState(get);
  useEffect(() => {
    if (!window.matchMedia) return;
    const mq = window.matchMedia(q);
    const on = (e) => setMobile(e.matches);
    setMobile(mq.matches);
    mq.addEventListener ? mq.addEventListener("change", on) : mq.addListener(on);
    return () => { mq.removeEventListener ? mq.removeEventListener("change", on) : mq.removeListener(on); };
  }, [q]);
  return mobile;
}

/* ---- Inline icon set (lucide-style, 1.75px uniform stroke) ------------- */
const ICON_PATHS = {
  plus: '<line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/>',
  x: '<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>',
  check: '<polyline points="20 6 9 17 4 12"/>',
  "check-circle": '<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/>',
  camera: '<path d="M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"/><circle cx="12" cy="13" r="3"/>',
  image: '<rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-3.5-3.5a2 2 0 0 0-2.8 0L6 20"/>',
  clock: '<circle cx="12" cy="12" r="9"/><polyline points="12 7 12 12 15 14"/>',
  user: '<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>',
  users: '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>',
  search: '<circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>',
  "arrow-right": '<line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/>',
  "arrow-left": '<line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/>',
  "chevron-down": '<polyline points="6 9 12 15 18 9"/>',
  "chevron-right": '<polyline points="9 18 15 12 9 6"/>',
  "log-out": '<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/>',
  phone: '<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.36 1.9.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.91.34 1.85.57 2.81.7A2 2 0 0 1 22 16.92z"/>',
  mail: '<rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 7-10 6L2 7"/>',
  "map-pin": '<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/>',
  building: '<rect x="4" y="2" width="16" height="20" rx="2"/><line x1="9" y1="6" x2="9" y2="6"/><line x1="15" y1="6" x2="15" y2="6"/><line x1="9" y1="10" x2="9" y2="10"/><line x1="15" y1="10" x2="15" y2="10"/><line x1="9" y1="14" x2="9" y2="14"/><line x1="15" y1="14" x2="15" y2="14"/><path d="M9 22v-4h6v4"/>',
  "alert-triangle": '<path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12" y2="17"/>',
  inbox: '<polyline points="22 12 16 12 14 15 10 15 8 12 2 12"/><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"/>',
  "rotate-ccw": '<polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/>',
  "layout-grid": '<rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/>',
  wrench: '<path d="M14.7 6.3a4 4 0 0 0-5.4 5.4L3 18v3h3l6.3-6.3a4 4 0 0 0 5.4-5.4l-2.7 2.7-2-2 2.7-2.7z"/>',
  "trending-up": '<polyline points="22 7 13.5 15.5 8.5 10.5 2 17"/><polyline points="16 7 22 7 22 13"/>',
  paperclip: '<path d="m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/>',
  "more-vertical": '<circle cx="12" cy="5" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="12" cy="19" r="1"/>',
  send: '<line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/>',
  "calendar": '<rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/>',
  "list-checks": '<path d="m3 17 2 2 4-4"/><path d="m3 7 2 2 4-4"/><line x1="13" y1="6" x2="21" y2="6"/><line x1="13" y1="12" x2="21" y2="12"/><line x1="13" y1="18" x2="21" y2="18"/>',
  briefcase: '<rect x="2" y="7" width="20" height="14" rx="2"/><path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"/>',
  filter: '<polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"/>',
  shield: '<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>',
  archive: '<rect x="2" y="3" width="20" height="5" rx="1"/><path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"/><line x1="10" y1="12" x2="14" y2="12"/>',
  trash: '<polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>',
};

function Icon({ name, size = 18, stroke = 1.75, color = "currentColor", style = {} }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none"
      stroke={color} strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round"
      style={{ display: "block", flexShrink: 0, ...style }}
      dangerouslySetInnerHTML={{ __html: ICON_PATHS[name] || "" }} />
  );
}

/* ---- Brand mark — JNW Scout Reservation badge ------------- */
function BrandMark({ size = 28, color }) {
  // Real badge art is a full-color circle on white; clip into a white circular
  // chip and slightly overscale so the ring meets the edge and the white
  // corners are cropped — reads cleanly on both light and dark surfaces.
  return (
    <div style={{ width: size, height: size, borderRadius: "50%", overflow: "hidden", background: "#fff", flexShrink: 0 }}>
      <img src="/assets/jnw-logo.jpg" alt="" style={{ width: "114%", height: "114%", objectFit: "cover", transform: "translate(-6%, -6%)", display: "block" }} />
    </div>
  );
}

function BrandLockup({ tone = "dark", iconColor }) {
  const c = tone === "light" ? "#FFFFFF" : "#16331E";
  const sub = tone === "light" ? "rgba(255,255,255,0.62)" : "#6E7D71";
  return (
    <div style={{ display: "inline-flex", alignItems: "center", gap: 11 }}>
      <BrandMark size={38} />
      <div style={{ lineHeight: 1.05 }}>
        <div style={{ fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 16.5, letterSpacing: "-0.02em", color: c }}>Camp Maintenance</div>
        <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: "0.13em", textTransform: "uppercase", color: sub, marginTop: 2 }}>June Norcross Webster</div>
      </div>
    </div>
  );
}

/* ---- Avatar ----------------------------------------------------------- */
function initials(name) {
  return name.split(" ").filter(Boolean).slice(0, 2).map((p) => p[0]).join("").toUpperCase();
}
function Avatar({ name, color = "#2F6B3A", size = 34, ring = false }) {
  return (
    <div style={{
      width: size, height: size, borderRadius: "50%", background: color, color: "#fff",
      display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0,
      fontFamily: "var(--font-display)", fontWeight: 600, fontSize: size * 0.4, letterSpacing: "-0.01em",
      boxShadow: ring ? "0 0 0 2px #fff, 0 0 0 3.5px " + color : "none",
    }}>{initials(name)}</div>
  );
}

/* ---- Status + priority chips ------------------------------------------ */
const STATUS_COLORS = {
  new:         { dot: "#515151", bg: "#F2F2F2", fg: "#515151" },
  assigned:    { dot: "#6FA07C", bg: "#EBF3EC", fg: "#3C6E47" },
  in_progress: { dot: "#2F6B3A", bg: "#E5F0E7", fg: "#245730" },
  done:        { dot: "#0DAB4A", bg: "#E6F6EC", fg: "#05873C" },
};

function StatusPill({ status }) {
  const m = WOData.statusMeta(status);
  const c = STATUS_COLORS[status];
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 6, padding: "4px 10px 4px 8px", borderRadius: 999, background: c.bg, color: c.fg, fontSize: 12, fontWeight: 600, fontFamily: "var(--font-sans)" }}>
      <span style={{ width: 7, height: 7, borderRadius: "50%", background: c.dot }}></span>{m.label}
    </span>
  );
}

function PriorityChip({ priority, compact = false }) {
  const m = WOData.priorityMeta(priority);
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 5, padding: compact ? "2px 8px" : "4px 10px", borderRadius: 999, background: m.color + "1A", color: m.color, fontSize: compact ? 11 : 12, fontWeight: 700, letterSpacing: "0.01em", fontFamily: "var(--font-sans)" }}>
      {priority === "urgent" && <Icon name="alert-triangle" size={compact ? 11 : 12} color={m.color} stroke={2} />}
      {m.label}
    </span>
  );
}

function CategoryTag({ category }) {
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 5, fontSize: 12, fontWeight: 500, color: "#515151", fontFamily: "var(--font-sans)" }}>
      <Icon name="wrench" size={12} color="#9AA3A5" /> {category}
    </span>
  );
}

/* ---- Photo thumbnail (uploaded dataURL or placeholder) ---------------- */
function PhotoThumb({ photo, size = 56, onClick }) {
  const common = { width: size, height: size, borderRadius: 8, overflow: "hidden", flexShrink: 0, cursor: onClick ? "pointer" : "default", border: "1px solid #E6E6E6" };
  if (photo.kind === "ph") {
    return (
      <div onClick={onClick} title={photo.label} style={{ ...common, background: photo.color, display: "flex", alignItems: "flex-end", padding: 5, position: "relative" }}>
        <Icon name="image" size={14} color="rgba(255,255,255,0.85)" style={{ position: "absolute", top: 6, right: 6 }} />
        <span style={{ fontSize: 8.5, color: "rgba(255,255,255,0.95)", fontWeight: 600, lineHeight: 1.1 }}>{photo.label}</span>
      </div>
    );
  }
  return <img src={photo.url} alt="" onClick={onClick} style={{ ...common, objectFit: "cover" }} />;
}

/* ---- Time helpers ------------------------------------------------------ */
function timeAgo(iso) {
  const diff = Date.now() - new Date(iso).getTime();
  const m = Math.floor(diff / 60000), h = Math.floor(diff / 3600000), d = Math.floor(diff / 86400000);
  if (m < 1) return "just now";
  if (m < 60) return m + "m ago";
  if (h < 24) return h + "h ago";
  if (d < 7) return d + "d ago";
  return new Date(iso).toLocaleDateString(undefined, { month: "short", day: "numeric" });
}
function fmtDate(iso) {
  return new Date(iso).toLocaleDateString(undefined, { month: "short", day: "numeric", hour: "numeric", minute: "2-digit" });
}

/* ---- Button ----------------------------------------------------------- */
function Button({ kind = "primary", size = "md", icon, iconRight, children, onClick, disabled, style = {}, type = "button" }) {
  const [hover, setHover] = useState(false);
  const sizes = {
    sm: { height: 38, pad: "0 14px", fs: 13 },
    md: { height: 46, pad: "0 18px", fs: 14.5 },
    lg: { height: 54, pad: "0 26px", fs: 16 },
  }[size];
  const palettes = {
    primary: { bg: "#2F6B3A", bgH: "#245730", fg: "#fff", bd: "transparent" },
    dark:    { bg: "#16331E", bgH: "#1E4A2A", fg: "#fff", bd: "transparent" },
    green:   { bg: "#0DAB4A", bgH: "#05873C", fg: "#fff", bd: "transparent" },
    ghost:   { bg: "transparent", bgH: "#F2F2F2", fg: "#16331E", bd: "#E6E6E6" },
    subtle:  { bg: "#F2F2F2", bgH: "#E6E6E6", fg: "#16331E", bd: "transparent" },
  }[kind];
  return (
    <button type={type} onClick={onClick} disabled={disabled}
      onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
      style={{
        height: sizes.height, padding: sizes.pad, fontSize: sizes.fs, gap: 8,
        fontFamily: "var(--font-display)", fontWeight: 600, letterSpacing: "-0.01em",
        background: disabled ? "#E6E6E6" : (hover ? palettes.bgH : palettes.bg),
        color: disabled ? "#9AA3A5" : palettes.fg,
        border: "1px solid " + (palettes.bd === "transparent" ? "transparent" : (hover ? "#515151" : palettes.bd)),
        borderRadius: 8, cursor: disabled ? "not-allowed" : "pointer",
        display: "inline-flex", alignItems: "center", justifyContent: "center",
        transition: "background 120ms var(--ease-out), border-color 120ms var(--ease-out)",
        whiteSpace: "nowrap", ...style,
      }}>
      {icon && <Icon name={icon} size={sizes.fs + 2} />}
      {children}
      {iconRight && <Icon name={iconRight} size={sizes.fs + 2} />}
    </button>
  );
}

/* ---- Modal shell ------------------------------------------------------ */
function Modal({ open, onClose, children, width = 560, padded = true }) {
  const mobile = useIsMobile();
  useEffect(() => {
    if (!open) return;
    const h = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", h);
    return () => window.removeEventListener("keydown", h);
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div onMouseDown={onClose} style={{
      position: "fixed", inset: 0, background: "rgba(0,32,38,0.45)", zIndex: 100,
      display: "flex", alignItems: mobile ? "flex-end" : "flex-start", justifyContent: "center",
      padding: mobile ? 0 : "48px 20px", overflowY: "auto",
    }}>
      <div onMouseDown={(e) => e.stopPropagation()} style={{
        background: "#fff", borderRadius: mobile ? "16px 16px 0 0" : 16, width: "100%", maxWidth: mobile ? "100%" : width,
        boxShadow: "var(--shadow-lg)", padding: padded ? 0 : 0, animation: "rfRise 200ms var(--ease-out)",
      }}>{children}</div>
    </div>
  );
}

Object.assign(window, {
  Icon, BrandMark, BrandLockup, Avatar, initials,
  StatusPill, PriorityChip, CategoryTag, PhotoThumb, STATUS_COLORS,
  timeAgo, fmtDate, Button, Modal, useIsMobile,
});
