/* ============================================================
   SalaryBar — two styles, switched by tweak:
     'linear'    — horizontal bar with markers; multi-color zone gradient
     'stacked'   — labelled zones with a thin fill underneath
   Apron vs Cap mode toggle lives INSIDE the bar header.

   Mode rules:
     - Cap mode: cap holds count; only the Cap line is shown.
     - Apron mode: cap holds ignored; Cap + 1st apron + 2nd apron lines.

   Color scheme (apron mode):
     0 → cap        green (var(--pos))
     cap → 1st apr  yellow (var(--warn))
     1st → 2nd      orange-warn
     past 2nd       red (var(--danger))

   Hard-cap state is NOT YET WIRED (no triggering tool yet). When it is,
   set state.hardCap = true and the bar will show the "hard hat" badge.
   ============================================================ */

function SalaryBar({ derived, state, dispatch, style = "linear", modeOverride }) {
  const { committed, zone, apronTotal, unlikely = 0, rosterCount = 0 } = derived;
  const { cap, apron1, apron2 } = CAP_2026;
  // The Apron/Cap toggle here is VIEW-ONLY — it changes nothing but
  // this graphic, and only a cap team ever sees it. Default view tracks
  // modeOverride (cap step 3 = apron) then state.mode.
  const [viewOverride, setViewOverride] = useState(null);
  const effMode = viewOverride || modeOverride || state.mode;
  const showToggle = state.mode === "cap";

  // R4: unlikely-bonus toggle. Only when the rostered players carry unlikely
  // incentives. The DEFAULT "Apron" view paints the true apron figure
  // (committed + unlikely, the stricter apron-with-unlikely value); the "Tax"
  // view drops to the likely-only `committed`. (State stays keyed "likely" for
  // the committed-only branch to minimize churn.)
  const [bonusView, setBonusView] = useState("apron");
  const hasUnlikely = unlikely > 0;
  const effCommitted = (hasUnlikely && bonusView === "apron")
    ? committed + unlikely : committed;

  // Luxury tax bill (apron view only) — on `committed`, never the toggle value.
  // Guarded: undefined engine / first paint → null.
  const taxR = (window.Engine && effMode === "apron" && committed > CAP_2026.taxLine)
    ? window.Engine.luxuryTax(committed, window.Engine.CBA_2026_27,
        { repeater: (window.REPEATER_TEAMS && window.REPEATER_TEAMS.has(state.team)) }) : null;
  // Salary-floor flag (both views) — on the holds-free apronTotal, gated so a
  // near-empty roster doesn't alarm.
  const floorR = window.Engine
    ? window.Engine.belowMinSalaryFloor(apronTotal, window.Engine.CBA_2026_27) : null;
  const showFloor = rosterCount >= 14 && floorR && floorR.below;

  // mode-aware headline — short
  let headlineNum = "", headlineLabel = "";
  if (effMode === "cap") {
    const room = cap - committed;
    if (room > 0) { headlineNum = fmt$(room); headlineLabel = "under cap"; }
    else { headlineNum = fmt$(committed - cap); headlineLabel = "over cap"; }
  } else {
    const toApron1 = apron1 - committed;
    if (toApron1 > 0) { headlineNum = fmt$(toApron1); headlineLabel = "below 1st apron"; }
    else {
      const toApron2 = apron2 - committed;
      if (toApron2 > 0) { headlineNum = fmt$(committed - apron1); headlineLabel = "over 1st apron"; }
      else { headlineNum = fmt$(committed - apron2); headlineLabel = "over 2nd apron"; }
    }
  }
  const headlineColor = effMode === "cap"
    ? (committed > cap ? "var(--info)" : "var(--pos)")
    : (zone === "over-apron2" ? "var(--danger)" : zone === "apron-zone-2" || zone === "apron-zone-1" ? "var(--warn)" : "var(--pos)");

  return (
    <section className="salary-bar-band">
      <div className="salary-bar-inner">
        <div className="salary-bar-head">
          <div className="sb-head-left">
            <div className="sb-total num">
              {fmt$Full(committed)}
              <span className="sb-of">/ {fmt$(effMode === "apron" ? apron1 : cap)}</span>
            </div>
            <div className="sb-headline">
              <b style={{ color: headlineColor }}>{headlineNum}</b>
              <span style={{ color: "var(--text-faint)" }}>{headlineLabel}</span>
            </div>
            {taxR && (
              <div className="sb-stat">
                <b className="num">{fmt$(taxR.tax)}</b>
                <span style={{ color: "var(--text-faint)" }}>Luxury tax</span>
              </div>
            )}
            {state.hardCap && (
              <span className="sb-hardcap" title="Team is hard-capped">
                <Icon.HardHat /> Hard-capped
              </span>
            )}
            {showFloor && (
              <span className="sb-floor-badge">Below floor · −{fmt$(floorR.shortfall)}</span>
            )}
          </div>
          {(showToggle || hasUnlikely) && (
            <div className="sb-head-right">
              {showToggle && (
                <div className="sb-mode-toggle" title="Changes this graphic only">
                  <button className={effMode === "apron" ? "on" : ""}
                          onClick={() => setViewOverride("apron")}>Apron</button>
                  <button className={effMode === "cap" ? "on" : ""}
                          onClick={() => setViewOverride("cap")}>Cap</button>
                </div>
              )}
              {hasUnlikely && (
                <div className="sb-bonus-toggle-wrap">
                  <div className="sb-mode-toggle" title="Include unlikely incentive bonuses in the chart">
                    <button className={bonusView === "apron" ? "on" : ""}
                            onClick={() => setBonusView("apron")}>Apron</button>
                    <button className={bonusView === "likely" ? "on" : ""}
                            onClick={() => setBonusView("likely")}>Tax</button>
                  </div>
                  <span className="sb-bonus-info" tabIndex={0} role="img"
                        aria-label="What counts toward the apron versus the luxury tax"
                        title="Apron counts salary, likely incentives, and unlikely incentives (the rare, hard-to-hit ones). The luxury tax is projected on salary and likely incentives only — an unlikely incentive is taxed only if it's actually earned.">ⓘ</span>
                </div>
              )}
            </div>
          )}
        </div>

        {style === "linear" && <SalaryBarLinear committed={effCommitted} mode={effMode} hardCap={state.hardCap} />}
        {style === "stacked" && <SalaryBarStacked committed={effCommitted} mode={effMode} />}
      </div>
    </section>
  );
}

/* === STYLE 1: linear with markers; smooth multi-zone gradient ===
   - Apron mode: green → yellow → orange (smooth blends between zones).
                 Red only kicks in past the 2nd apron OR if hard-capped.
   - Cap mode  : green → red (hard transition right at cap).
   The fill uses a fixed multi-color background gradient with stops at the
   thresholds. clip-path reveals only up to `committed`. Colors stay aligned
   to the cap/apron tick marks at all times.
*/
function SalaryBarLinear({ committed, mode, hardCap }) {
  const { cap, apron1, apron2 } = CAP_2026;
  // Two stacked bars so the cap/apron lines (all $125M+) get full
  // resolution and their labels never crowd the right edge / overflow.
  const SPLIT = 125_000_000, MAX = 250_000_000;
  const ROWS = [{ lo: 0, hi: SPLIT }, { lo: SPLIT, hi: MAX }];

  const stops = mode === "cap"
    ? [{ name: "Cap", value: cap, className: "cap" }]
    : [
        { name: "Cap",       value: cap,    className: "cap"    },
        { name: "1st apron", value: apron1, className: "apron1" },
        { name: "2nd apron", value: apron2, className: "apron2" },
      ];

  const zoneColor = mode === "cap"
    ? (committed > cap ? "var(--danger)" : "var(--pos)")
    : (committed > apron2 || hardCap ? "var(--danger)"
       : committed > apron1 ? "var(--orange)"
       : committed > cap ? "var(--warn)" : "var(--pos)");

  return (
    <div className="sb-dual">
      {ROWS.map((r, ri) => {
        const span = r.hi - r.lo;
        const fillPct = Math.max(0, Math.min(100, ((committed - r.lo) / span) * 100));
        const pos = (v) => ((v - r.lo) / span) * 100;
        const rowStops = stops.filter(s => s.value > r.lo && s.value <= r.hi);
        const inRow = committed > r.lo && committed <= r.hi;
        return (
          <div className={`sb-linear ${hardCap ? "hard-capped" : ""}`} key={ri}>
            <span className="sb-row-cap">{ri === 0 ? "$0" : fmt$(SPLIT)}</span>
            <span className="sb-row-cap right">{fmt$(r.hi)}</span>
            <div className="bar-track" />
            <div className="bar-fill" style={{
              background: zoneColor,
              clipPath: `inset(0 ${100 - fillPct}% 0 0 round 6px)`,
            }} />
            {rowStops.map(s => (
              <div key={"m" + s.name} className={`marker ${s.className}`}
                   style={{ left: pos(s.value) + "%" }} />
            ))}
            {rowStops.map((s, si) => {
              const lp = Math.max(7, Math.min(93, pos(s.value)));
              // stagger consecutive labels onto two tiers so close
              // markers (1st apron / 2nd apron) never overlap
              const tier = si % 2;
              return (
                <div key={"l" + s.name} className="marker-label"
                     style={{ left: lp + "%", top: (30 + tier * 17) + "px",
                              transform: "translateX(-50%)" }}>
                  <span>{s.name}</span> <span className="val">{fmt$(s.value)}</span>
                </div>
              );
            })}
            {inRow && committed > 0 && (
              <div className="sb-here" style={{ left: Math.min(99, fillPct) + "%" }} title="Current">
                <span className="sb-here-val">{fmt$(committed)}</span>
              </div>
            )}
          </div>
        );
      })}
    </div>
  );
}

/* === STYLE 2: labelled zones + fill underneath === */
function SalaryBarStacked({ committed, mode }) {
  const { cap, taxLine, apron1, apron2 } = CAP_2026;
  const scale = apron2 * 1.12;
  const capPct = (cap / scale) * 100;
  const midPct = ((taxLine - cap) / scale) * 100;
  const a1Pct  = ((apron1 - taxLine) / scale) * 100;
  const a2Pct  = ((apron2 - apron1) / scale) * 100;
  const fillPct = Math.min(100, (committed / scale) * 100);
  const over = committed > apron2;
  const styleVars = {
    "--cap-pct": capPct + "%",
    "--mid-pct": midPct + "%",
    "--a1-pct":  a1Pct + "%",
    "--a2-pct":  a2Pct + "%",
    "--fill-pct": fillPct + "%",
  };
  return (
    <div className={`sb-stacked ${mode === "cap" ? "cap-mode" : ""}`} style={styleVars}>
      <div className="zones">
        <div className="zone z-cap">  <span className="zlbl">Cap room</span><span className="zval">{fmt$(cap)}</span></div>
        <div className="zone z-tax">  <span className="zlbl">Tax</span><span className="zval">{fmt$(taxLine)}</span></div>
        <div className="zone z-a1">   <span className="zlbl">1A</span></div>
        <div className="zone z-a2">   <span className="zlbl">2A</span></div>
        <div className="zone z-over"> <span className="zlbl" style={{ color: "var(--danger)" }}>Frozen</span></div>
      </div>
      <div className="fill-row">
        <div className={`fill ${over ? "over" : ""}`} />
      </div>
    </div>
  );
}

Object.assign(window, { SalaryBar });
