// LeaveTrackerLite — shared components
const { useState, useRef, useEffect } = React;

/* ───────────────────────── Tooltip ───────────────────────── */
/* Rendered in a portal at document.body so overflow:hidden containers never clip it. */
function Tooltip({ label, children, side = "top" }) {
  const [pos, setPos] = useState(null);
  const ref = useRef(null);
  function show() {
    const el = ref.current;
    if (!el) return;
    const r = el.getBoundingClientRect();
    setPos({ x: r.left + r.width / 2, y: side === "top" ? r.top : r.bottom });
  }
  return (
    <span ref={ref} style={{ position: "relative", display: "inline-flex" }}
          onMouseEnter={show} onMouseLeave={() => setPos(null)}>
      {children}
      {pos && ReactDOM.createPortal(
        <span style={{
          position: "fixed", left: pos.x, top: pos.y, zIndex: 200, whiteSpace: "nowrap",
          transform: side === "top" ? "translate(-50%, calc(-100% - 8px))" : "translate(-50%, 8px)",
          background: "oklch(0.27 0.012 250)", color: "#fff", fontSize: 12.5, fontWeight: 500,
          padding: "6px 9px", borderRadius: 7, boxShadow: "var(--shadow-pop)", pointerEvents: "none",
          letterSpacing: ".01em",
        }}>{label}</span>,
        document.body
      )}
    </span>
  );
}

/* ───────────────────────── Avatar ───────────────────────── */
const AVATAR_HUES = { DR: 25, AP: 285, SH: 200, RO: 145, MS: 330, NP: 255, MB: 50, JL: 175, GL: 95, ET: 310, DK: 120, HK: 230, OH: 10, PK: 270, TB: 65, LF: 190, CM: 350, RA: 160 };
function Avatar({ initials, size = 34 }) {
  const hue = AVATAR_HUES[initials] ?? 220;
  return (
    <span className="i" style={{
      width: size, height: size, borderRadius: "50%", flex: "none",
      background: `oklch(0.93 0.035 ${hue})`,
      color: `oklch(0.42 0.09 ${hue})`,
      fontWeight: 600, fontSize: size * 0.38, letterSpacing: ".01em",
    }}>{initials}</span>
  );
}

/* ───────────────────────── Chips ───────────────────────── */
function Chip({ children, color, bg, icon, dot, weight = 600, style }) {
  return (
    <span className="i" style={{
      gap: 5, padding: "3px 9px 3px " + (dot || icon ? "8px" : "9px"),
      borderRadius: 999, fontSize: 12.5, fontWeight: weight, lineHeight: 1.45,
      color, background: bg, whiteSpace: "nowrap", ...style,
    }}>
      {dot && <span style={{ width: 6, height: 6, borderRadius: "50%", background: color, flex: "none" }} />}
      {icon && <i className={"ph-fill " + icon} style={{ fontSize: 13 }} />}
      {children}
    </span>
  );
}

const STATUS_TONES = {
  Active:    { color: "var(--green)",      bg: "var(--green-soft)" },
  Upcoming:  { color: "var(--blue)",       bg: "var(--blue-soft)" },
  Exhausted: { color: "var(--amber-deep)", bg: "var(--amber-soft)" },
};
function StatusChip({ status }) {
  const t = STATUS_TONES[status] || STATUS_TONES.Active;
  return <Chip color={t.color} bg={t.bg} dot>{status}</Chip>;
}

/* Muted reason chip — for attention reasons with no other visual signal in the row */
function FlagChip({ children }) {
  return (
    <span className="i" style={{ gap: 4, padding: "2px 6px", borderRadius: 999, fontSize: 10.5, fontWeight: 600, lineHeight: 1.4, color: "var(--amber-deep)", background: "var(--surface-2)", border: "1px solid var(--line)", whiteSpace: "nowrap" }}>
      {children}
    </span>
  );
}

const TYPE_META = {
  "Workers' comp":        "ph-first-aid-kit",
  "Pregnancy / parental": "ph-baby",
  "Personal":             "ph-user",
  "Medical":              "ph-heartbeat",
  "Intermittent":         "ph-arrows-clockwise",
  "Accommodation":        "ph-wheelchair",
};
function TypeTag({ type, fmla, weeks }) {
  return (
    <span style={{ display: "inline-flex", flexDirection: "column", gap: 4, alignItems: "flex-start" }}>
      <span className="i" style={{ gap: 7, color: "var(--ink-2)", fontSize: "var(--cell-font)", fontWeight: 500 }}>
        <i className={"ph " + (TYPE_META[type] || "ph-tag")} style={{ fontSize: 16, color: "var(--ink-3)" }} />
        {type}
        {fmla && (
          <Tooltip label="FMLA — rolling 12-month balance">
            <span style={{ fontSize: 10, fontWeight: 700, letterSpacing: ".05em", color: "var(--accent-strong)", border: "1px solid var(--accent-soft-2)", background: "var(--accent-soft)", borderRadius: 5, padding: "1.5px 5px", lineHeight: 1.3 }}>FMLA</span>
          </Tooltip>
        )}
      </span>
      {weeks && <Sparkline weeks={weeks} />}
    </span>
  );
}

/* Tiny 12-week usage sparkline — word-sized tick marks */
function Sparkline({ weeks }) {
  const max = Math.max(...weeks, 1);
  return (
    <Tooltip label="Hours used per week, last 12 weeks">
      <span style={{ display: "inline-flex", alignItems: "flex-end", gap: 2, height: 12, padding: "0 1px" }}>
        {weeks.map((w, i) => (
          <span key={i} style={{
            width: 3, borderRadius: 1, flex: "none",
            height: w === 0 ? 2 : Math.max(4, Math.round((w / max) * 12)),
            background: w === 0 ? "oklch(0.9 0.004 250)" : "var(--accent)",
            opacity: w === 0 ? 1 : 0.55 + 0.45 * (w / max),
          }} />
        ))}
      </span>
    </Tooltip>
  );
}

/* Rolling-balance regeneration hint */
function RegenHint({ c }) {
  if (!c.regen) return null;
  return (
    <Tooltip label={`Rolling 12-month window — ${c.regen.hours}h of past usage ages out ${c.regen.date}`}>
      <span className="i" style={{ gap: 4, fontSize: 11.5, color: "var(--ink-faint)", whiteSpace: "nowrap", fontWeight: 500 }}>
        <i className="ph ph-clock-counter-clockwise" style={{ fontSize: 12 }} />
        <span><span style={{ color: "var(--accent-strong)", fontWeight: 600 }}>+{c.regen.hours}h</span> back {c.regen.date}</span>
      </span>
    </Tooltip>
  );
}

function DocChip({ status, label }) {
  if (status === "complete")
    return <Tooltip label="Documentation complete"><Chip color="var(--ink-2)" bg="var(--surface-2)" icon="ph-check-circle" style={{ border: "1px solid var(--line)" }}>Complete</Chip></Tooltip>;
  if (status === "received")
    return <Tooltip label="Paperwork received — under review"><Chip color="var(--blue)" bg="var(--blue-soft)" icon="ph-file-text">Received</Chip></Tooltip>;
  return <Tooltip label={label}><Chip color="var(--amber-deep)" bg="var(--amber-soft)" icon="ph-warning">Missing</Chip></Tooltip>;
}

/* ───────────────────────── Return cell ───────────────────────── */
function ReturnCell({ c }) {
  if (c.ongoing)
    return <span style={{ color: "var(--ink-3)", fontSize: "var(--cell-font)", fontStyle: "italic" }}>Ongoing</span>;
  const soon = c.retDays != null && c.retDays >= 0 && c.retDays <= 7;
  const past = c.retPast;
  return (
    <span className="i" style={{ gap: 7, justifyContent: "flex-start" }}>
      <span className="tnum" style={{ fontSize: "var(--cell-font)", color: past ? "var(--rose)" : "var(--ink)", fontWeight: past ? 600 : 500 }}>{c.ret}</span>
      {past && <Chip color="var(--rose)" bg="var(--rose-soft)" weight={600} style={{ fontSize: 11.5, padding: "2px 7px" }}>Past due</Chip>}
      {soon && <Chip color="var(--blue)" bg="var(--blue-soft)" weight={600} style={{ fontSize: 11.5, padding: "2px 7px" }}>{c.retDays === 0 ? "Today" : "in " + c.retDays + "d"}</Chip>}
    </span>
  );
}

/* ───────────────────────── Balance viz ───────────────────────── */
function pct(c) { return c.appr ? Math.min(100, Math.round((c.used / c.appr) * 100)) : 0; }
function isCrit(c) { return c.lowBalance || (c.appr != null && c.remaining === 0); }

function BalanceBar({ c }) {
  if (c.appr == null)
    return <NABalance />;
  const p = pct(c);
  const low = isCrit(c);
  const fill = low ? "var(--amber)" : "var(--accent)";
  return (
    <div style={{ minWidth: 116 }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 5, gap: 6, whiteSpace: "nowrap" }}>
        <span className="tnum" style={{ fontSize: 12.5, color: "var(--ink-3)" }}>{c.used}<span style={{ color: "var(--ink-faint)" }}> / {c.appr}h</span></span>
        <RemainingLabel c={c} compact />
      </div>
      <div style={{ height: 6, borderRadius: 999, background: "oklch(0.93 0.005 250)", overflow: "hidden" }}>
        <div style={{ width: p + "%", height: "100%", borderRadius: 999, background: fill, transition: "width .5s cubic-bezier(.2,.7,.2,1)" }} />
      </div>
      {c.regen && <div style={{ display: "flex", justifyContent: "flex-end", marginTop: 4 }}><RegenHint c={c} /></div>}
    </div>
  );
}

function BalanceRing({ c }) {
  if (c.appr == null)
    return <NABalance />;
  const p = pct(c);
  const r = 15, circ = 2 * Math.PI * r;
  const low = isCrit(c);
  const stroke = low ? "var(--amber)" : "var(--accent)";
  return (
    <div className="i" style={{ gap: 11, justifyContent: "flex-start" }}>
      <span className="i" style={{ position: "relative", width: 38, height: 38, flex: "none" }}>
        <svg width="38" height="38" viewBox="0 0 38 38" style={{ transform: "rotate(-90deg)" }}>
          <circle cx="19" cy="19" r={r} fill="none" stroke="oklch(0.93 0.005 250)" strokeWidth="4" />
          <circle cx="19" cy="19" r={r} fill="none" stroke={stroke} strokeWidth="4" strokeLinecap="round"
                  strokeDasharray={circ} strokeDashoffset={circ * (1 - p / 100)}
                  style={{ transition: "stroke-dashoffset .5s cubic-bezier(.2,.7,.2,1)" }} />
        </svg>
        <span className="tnum" style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", fontSize: 10.5, fontWeight: 700, color: low ? "var(--amber-deep)" : "var(--accent-strong)" }}>{p}%</span>
      </span>
      <span style={{ lineHeight: 1.25, display: "inline-flex", flexDirection: "column", gap: 2, alignItems: "flex-start" }}>
        <RemainingLabel c={c} />
        <span className="tnum" style={{ fontSize: 12, color: "var(--ink-faint)", whiteSpace: "nowrap" }}>{c.used} of {c.appr}h used</span>
        <RegenHint c={c} />
      </span>
    </div>
  );
}

function BalanceNumbers({ c }) {
  if (c.appr == null) return <NABalance />;
  return (
    <span style={{ display: "inline-flex", flexDirection: "column", gap: 4, alignItems: "flex-start" }}>
      <span className="i" style={{ gap: 14, justifyContent: "flex-start" }}>
        <NumCol label="Appr." val={c.appr} />
        <NumCol label="Used" val={c.used} />
        <NumCol label="Avail." val={c.remaining} low={c.lowBalance} />
      </span>
      <RegenHint c={c} />
    </span>
  );
}
function NumCol({ label, val, low }) {
  return (
    <span style={{ textAlign: "right" }}>
      <span className="tnum" style={{ display: "block", fontSize: 14.5, fontWeight: 600, color: low ? "var(--amber-deep)" : "var(--ink)" }}>{val}</span>
      <span style={{ display: "block", fontSize: 10.5, textTransform: "uppercase", letterSpacing: ".05em", color: "var(--ink-faint)", fontWeight: 600 }}>{label}</span>
    </span>
  );
}

function RemainingLabel({ c, compact }) {
  const low = isCrit(c);
  return (
    <span className="i" style={{ gap: 5, whiteSpace: "nowrap" }}>
      <span className="tnum" style={{ fontSize: compact ? 13 : 14, fontWeight: 600, color: low ? "var(--amber-deep)" : "var(--ink)" }}>{c.remaining}h avail.</span>
      {low && <Chip color="var(--amber-deep)" bg="var(--amber-soft)" weight={600} style={{ fontSize: 10, padding: "1px 5px" }}>Low</Chip>}
    </span>
  );
}

function NABalance() {
  return (
    <Tooltip label="No approved hour allotment for this case">
      <span className="i" style={{ gap: 6, color: "var(--ink-faint)" }}>
        <span style={{ width: 100, height: 6, borderRadius: 999, background: "repeating-linear-gradient(90deg, oklch(0.92 0.004 250) 0 5px, transparent 5px 10px)" }} />
        <span style={{ fontSize: 13, fontWeight: 500 }}>N/A</span>
      </span>
    </Tooltip>
  );
}

function Balance({ c, mode }) {
  if (mode === "ring") return <BalanceRing c={c} />;
  if (mode === "numbers") return <BalanceNumbers c={c} />;
  return <BalanceBar c={c} />;
}

Object.assign(window, {
  Tooltip, Avatar, Chip, StatusChip, FlagChip, TypeTag, DocChip, ReturnCell, Sparkline, RegenHint,
  Balance, BalanceBar, BalanceRing, BalanceNumbers, RemainingLabel, NABalance, pct, isCrit,
});
