/* =============================================================
   CoreIQ Office — Floor & Shelf Planner (main screen)
   Registers window.OFFICE_SCREENS.planner
   Rail + scan modal live in office-screens-planner-panels.jsx
   (referenced via window.PlannerRail / window.PlannerScanModal).
   ============================================================= */
const { useState: plUseState, useMemo: plUseMemo, useRef: plUseRef, useEffect: plUseEffect } = React;

const PL = window.PLANNER_DATA;
const SCALE = 56; // px per metre (top-down)

// ---- heat colour helpers --------------------------------------
function lerp(a, b, t) { return a + (b - a) * t; }
function clamp01(x) { return Math.max(0, Math.min(1, x)); }

// sequential: light slate → teal
function heatSeq(t) {
  t = clamp01(t);
  const h = lerp(210, 186, t), s = lerp(34, 68, t), l = lerp(86, 40, t);
  return `hsl(${h}, ${s}%, ${l}%)`;
}
// diverging for space-to-sales: <1 over-spaced (rose) · ~1 balanced (slate) · >1 under-spaced (green)
function heatS2S(idx) {
  if (idx >= 1) {
    const t = clamp01((idx - 1) / 0.8); // 1 → 1.8
    return `hsl(${lerp(205, 152, t)}, ${lerp(20, 55, t)}%, ${lerp(72, 42, t)}%)`;
  }
  const t = clamp01((1 - idx) / 0.6); // 1 → 0.4
  return `hsl(${lerp(205, 350, t)}, ${lerp(20, 68, t)}%, ${lerp(72, 55, t)}%)`;
}

// per-bay metric value (category metric attributed to the bay by linear share)
function bayMetricValue(plan, bay, metric, period, basis) {
  if (!bay.cat) return null;
  const storeId = plan.storeId;
  if (metric === "s2s") return window.plannerSpaceToSales(plan, bay.cat, period).index;
  const catM = window.plannerCatLinearM(plan, bay.cat) || bay.m || 1;
  const share = (bay.m || 0) / catM;
  if (metric === "sales") return window.plannerCatSales(bay.cat, storeId, period) * share;
  if (metric === "value") return window.plannerCatInventoryValue(bay.cat, storeId, basis) * share;
  if (metric === "units") return window.plannerCatUnits(bay.cat, storeId, period) * share;
  if (metric === "gp")    return window.plannerCatGP(bay.cat, storeId, period) * share;
  return null;
}

function fmtMetric(metric, v, money) {
  if (v == null) return "—";
  if (metric === "s2s") return v.toFixed(2) + "×";
  if (metric === "units") return Math.round(v).toLocaleString();
  return money(v);
}

// ---- single fixture ------------------------------------------
function Fixture({ plan, fixture, ctx }) {
  const { mode, metric, period, basis, showLabels, selBay, onSelectBay,
          dragCat, dropBay, setDropBay, onDrop, range, money } = ctx;
  const vertical = fixture.h >= fixture.w;
  const isService = !(window.PLANNER_DATA.ASSIGNABLE_TYPES.includes(fixture.type)) || (fixture.bays || []).length === 0;

  const style = {
    left: fixture.x * SCALE, top: fixture.y * SCALE,
    width: fixture.w * SCALE, height: fixture.h * SCALE,
  };

  if (isService) {
    return (
      <div className="pl-fix pl-fix--service" style={style}>
        <span className="pl-fix-svc-label">{fixture.label}</span>
      </div>
    );
  }

  return (
    <div className={"pl-fix" + (vertical ? " pl-fix--vertical" : "")} style={style}>
      {(fixture.bays || []).map(bay => {
        const selected = selBay && selBay.fixtureId === fixture.id && selBay.bayId === bay.id;
        const isDrop = dropBay && dropBay.fixtureId === fixture.id && dropBay.bayId === bay.id;
        let bg, tag = null, content = null;
        if (!bay.cat) {
          // empty
          content = <span className="pl-bay-empty-ic"><window.OIcon name="plus"/></span>;
        } else if (mode === "plan") {
          bg = window.plannerDeptColor(window.plannerCatDept(bay.cat), 0.92);
          tag = <span className="pl-bay-tag">{window.plannerCatName(bay.cat)}</span>;
        } else {
          const v = bayMetricValue(plan, bay, metric, period, basis);
          if (metric === "s2s") bg = heatS2S(v);
          else { const t = range.max > range.min ? (v - range.min) / (range.max - range.min) : 0.5; bg = heatSeq(t); }
          tag = <span className="pl-bay-tag">{fmtMetric(metric, v, money)}</span>;
        }
        return (
          <div
            key={bay.id}
            className={"pl-bay" + (!bay.cat ? " pl-bay--empty" : "") + (selected ? " pl-bay--selected" : "") + (isDrop ? " pl-bay--drop" : "")}
            style={bg ? { background: bg } : undefined}
            onClick={() => onSelectBay(fixture.id, bay.id)}
            onDragOver={dragCat ? (e) => { e.preventDefault(); setDropBay({ fixtureId: fixture.id, bayId: bay.id }); } : undefined}
            onDragLeave={dragCat ? () => setDropBay(null) : undefined}
            onDrop={dragCat ? (e) => { e.preventDefault(); onDrop(fixture.id, bay.id); } : undefined}
            title={bay.cat ? window.plannerCatName(bay.cat) : "Empty bay — assign a category"}
          >
            {content}{tag}
          </div>
        );
      })}
      {showLabels && mode === "plan" && (
        <div className="pl-fix-label" style={{ left: fixture.w * SCALE / 2, top: -2, transform: "translate(-50%,-100%)" }}>{fixture.label}</div>
      )}
    </div>
  );
}

// ---- the floor plan canvas -----------------------------------
function FloorPlan({ plan, ctx }) {
  const { view } = ctx;
  const W = plan.room.w * SCALE, H = plan.room.h * SCALE;
  return (
    <div className={"pl-stage" + (view === "3d" ? " pl-stage--3d" : "")} style={{ width: W, height: H }}>
      <div className={"pl-room" + (view === "3d" ? " pl-room--3d" : "")} style={{ width: W, height: H }}>
        {plan.zones.map(z => (
          <div key={z.id} className={"pl-zone" + (z.kind === "clinical" ? " pl-zone--clinical" : "")}
               style={{ left: z.x * SCALE, top: z.y * SCALE, width: z.w * SCALE, height: z.h * SCALE }}>
            <span className="pl-zone-label">{z.label}</span>
          </div>
        ))}
        {/* entrance */}
        {plan.room.entrance && (
          <>
            <div className="pl-entrance" style={{ left: plan.room.entrance.x * SCALE, top: H - 3, width: plan.room.entrance.w * SCALE }}/>
            <div className="pl-entrance-label" style={{ left: (plan.room.entrance.x + plan.room.entrance.w / 2) * SCALE, top: H }}>Entrance</div>
          </>
        )}
        {plan.fixtures.map(f => <Fixture key={f.id} plan={plan} fixture={f} ctx={ctx}/>)}
      </div>
    </div>
  );
}

// ---- segmented control ----------------------------------------
function Seg({ value, onChange, options, accent }) {
  return (
    <div className="pl-seg">
      {options.map(o => (
        <button key={o.value} className={"pl-seg-btn" + (value === o.value ? " pl-seg-btn--active" + (accent ? " is-accent" : "") : "")} onClick={() => onChange(o.value)}>
          {o.icon && <window.OIcon name={o.icon}/>}{o.label}
        </button>
      ))}
    </div>
  );
}

// =================================================================
// PLANNER SCREEN
// =================================================================
function FloorPlanner() {
  const { scope, pushToast } = window.useOffice();
  const initStore = (scope && scope !== "all") ? scope : "S-001";

  const [storeId, setStoreId] = plUseState(initStore);
  const [mode, setMode] = plUseState("plan");        // plan | perf
  const [period, setPeriod] = plUseState("week");
  const [view, setView] = plUseState("top");          // top | 3d
  const [metric, setMetric] = plUseState("s2s");
  const [basis, setBasis] = plUseState("cost");       // cost | retail
  const [showLabels, setShowLabels] = plUseState(true);
  const [selBay, setSelBay] = plUseState(null);
  const [dragCat, setDragCat] = plUseState(null);
  const [dropBay, setDropBay] = plUseState(null);
  const [scanOpen, setScanOpen] = plUseState(false);

  // mutable copies of all plans
  const [plans, setPlans] = plUseState(() => JSON.parse(JSON.stringify(PL.PLANS)));
  const plan = plans[storeId];
  const money = window.officeMoney;

  // expose tweak hooks (read external tweak state if present)
  plUseEffect(() => {
    const t = window.__plannerTweaks;
    if (!t) return;
    if (t.metric) setMetric(t.metric);
    if (t.period) setPeriod(t.period);
    if (t.basis) setBasis(t.basis);
    if (typeof t.showLabels === "boolean") setShowLabels(t.showLabels);
  }, []);

  function assignBay(fixtureId, bayId, catId) {
    setPlans(prev => {
      const next = { ...prev, [storeId]: JSON.parse(JSON.stringify(prev[storeId])) };
      const f = next[storeId].fixtures.find(x => x.id === fixtureId);
      const b = f && f.bays.find(x => x.id === bayId);
      if (b) b.cat = catId;
      return next;
    });
    setDropBay(null); setDragCat(null);
    pushToast({ kind: "paid", icon: "check-circle", title: `${window.plannerCatName(catId)} assigned`, meta: "Bay updated · plan saved" });
  }
  function clearBay(fixtureId, bayId) {
    setPlans(prev => {
      const next = { ...prev, [storeId]: JSON.parse(JSON.stringify(prev[storeId])) };
      const f = next[storeId].fixtures.find(x => x.id === fixtureId);
      const b = f && f.bays.find(x => x.id === bayId);
      if (b) b.cat = null;
      return next;
    });
  }
  function onSelectBay(fixtureId, bayId) {
    // click-to-assign: if dragging not active but a category is "armed" via selBay+chip, handled in rail.
    setSelBay({ fixtureId, bayId });
  }

  // metric range across bays (perf mode shading)
  const range = plUseMemo(() => {
    if (mode !== "perf" || metric === "s2s") return { min: 0, max: 1 };
    let min = Infinity, max = -Infinity;
    window.plannerAllBays(plan).forEach(b => {
      const v = bayMetricValue(plan, b, metric, period, basis);
      if (v == null) return; if (v < min) min = v; if (v > max) max = v;
    });
    return min === Infinity ? { min: 0, max: 1 } : { min, max };
  }, [plan, mode, metric, period, basis]);

  const ctx = {
    mode, metric, period, basis, showLabels, view,
    selBay, onSelectBay,
    dragCat, dropBay, setDropBay,
    onDrop: (fid, bid) => dragCat && assignBay(fid, bid, dragCat),
    range, money,
  };

  const store = window.findOfficeStore(storeId);

  return (
    <div className="off-screen pl-screen">
      <header className="off-screen-header">
        <div className="off-screen-header-meta">
          <span className="off-screen-eyebrow">Stock · Space management</span>
          <h2 className="off-screen-title">Floor &amp; Shelf Planner</h2>
        </div>
        <div className="off-screen-actions">
          <span className="badge badge--neutral" style={{fontSize:11}}><window.OIcon name="info" width={12} height={12}/> {plan.meta.scanned}</span>
          <button className="btn btn--secondary" onClick={() => setScanOpen(true)}><window.OIcon name="phone"/> Import scan</button>
        </div>
      </header>

      {/* toolbar */}
      <div className="pl-toolbar">
        <div className="pl-toolbar-group">
          {window.OFFICE_DATA.STORES.map(s => (
            <button key={s.id} className={"pl-store-chip" + (storeId === s.id ? " pl-store-chip--active" : "")} onClick={() => { setStoreId(s.id); setSelBay(null); }}>
              <span className="pl-store-chip-code">{s.code}</span>{s.name}
            </button>
          ))}
        </div>

        <div className="pl-toolbar-sep"/>

        <Seg value={mode} onChange={setMode} accent options={[
          { value: "plan", label: "Plan", icon: "edit" },
          { value: "perf", label: "Performance", icon: "chart" },
        ]}/>

        <div className="pl-toolbar-spacer"/>

        {mode === "perf" && (
          <div className="pl-toolbar-group">
            <span className="pl-tool-label">Heatmap</span>
            <select className="pl-select" value={metric} onChange={e => setMetric(e.target.value)}>
              {PL.METRICS.map(m => <option key={m.key} value={m.key}>{m.label}</option>)}
            </select>
          </div>
        )}

        {(mode === "perf" || true) && (
          <div className="pl-toolbar-group">
            <span className="pl-tool-label">Period</span>
            <Seg value={period} onChange={setPeriod} options={[
              { value: "day", label: "D" }, { value: "week", label: "W" },
              { value: "month", label: "M" }, { value: "quarter", label: "Q" },
            ]}/>
          </div>
        )}

        <div className="pl-toolbar-sep"/>

        <Seg value={view} onChange={setView} options={[
          { value: "top", label: "Top-down" }, { value: "3d", label: "3D" },
        ]}/>

        <div className="pl-toolbar-group" style={{gap:4}}>
          <button className={"pl-store-chip" + (showLabels ? " pl-store-chip--active" : "")} style={{padding:"7px 9px"}} title="Show fixture labels" onClick={() => setShowLabels(v => !v)}>
            <window.OIcon name="eye" width={15} height={15}/>
          </button>
          <button className="pl-store-chip" style={{padding:"7px 9px"}} title="Toggle theme" onClick={() => {
            const cur = document.documentElement.getAttribute("data-theme") === "dark" ? "light" : "dark";
            document.documentElement.setAttribute("data-theme", cur);
            try { localStorage.setItem("coreiq-office-theme", cur); } catch (_) {}
          }}>
            <window.OIcon name="moon" width={15} height={15}/>
          </button>
        </div>
      </div>

      {/* body */}
      <div className="pl-body">
        <div className="pl-canvas-wrap">
          <FloorPlan plan={plan} ctx={ctx}/>
        </div>

        {window.PlannerRail
          ? <window.PlannerRail
              plan={plan} storeId={storeId} mode={mode} period={period} metric={metric}
              basis={basis} setBasis={setBasis} showLabels={showLabels} setShowLabels={setShowLabels}
              selBay={selBay} setSelBay={setSelBay}
              assignBay={assignBay} clearBay={clearBay}
              dragCat={dragCat} setDragCat={setDragCat}
              money={money}
            />
          : <div className="pl-rail"/>}
      </div>

      {scanOpen && window.PlannerScanModal && (
        <window.PlannerScanModal store={store} plan={plan} onClose={() => setScanOpen(false)}
          onApply={() => { setScanOpen(false); pushToast({ kind: "paid", icon: "check-circle", title: "Floor plan imported", meta: `${plan.fixtures.length} fixtures detected · ${store.name}` }); }}/>
      )}
    </div>
  );
}

window.OFFICE_SCREENS = Object.assign(window.OFFICE_SCREENS || {}, { planner: FloorPlanner });
// shared for the rail file
window.PlannerShared = { SCALE, heatSeq, heatS2S, bayMetricValue, fmtMetric };
