// InteractiveSimulator.jsx
//
// A rubycrm.ai-style live event panel: three buttons let a visitor force a
// scenario (Optimal / Yield Loss Alert / GRN Backlog), and a log console
// streams JSON payloads shaped exactly like the real backend's
// Production/WIP event stream -
//   trans-backend/src/inventory/events/stock-movement.events.ts
//     (StockInEvent / StockOutEvent / GrnStockInEvent: companyId, productId,
//      warehouseId, quantity, stockMovementId, performedById, occurredAt)
//   trans-backend/src/entities/wastage-ledger.entity.ts
//     (stageId, productId, cycleId, accumulatedStageStockIn/Out,
//      remainingInProgressQuantity, wastageQuantity, wastagePercentage,
//      isCycleClosed, hasNegativeBalanceWarning, triggeredByEventAction)
//   trans-backend/src/types.ts (TargetEventAction enum: STOCK_IN, STOCK_OUT,
//      GRN_STOCK_IN, MANUAL_ADJUSTMENT)
//
// Scenario names are the real signals the data already carries - a
// wastage-percentage spike with a negative WIP balance (hasNegativeBalanceWarning,
// a real WastageLedger field) is labeled "Yield Loss Alert", and stalled
// GRN receipts against continuing stock-out is labeled "GRN Backlog" -
// not invented floor-automation buzzwords like a fictional temperature
// sensor. No values here are live or connected to any company account -
// every number is generated client-side on a timer, per SPEC-07 Section 5's
// anti-hallucination guardrail for this exact component.
//
// Loaded as a classic (non-module) Babel-transformed script - see
// index.html's header comment. React 19 ships no UMD global, so
// `window.React` here is the bridge index.html's ESM import sets up; hooks
// are called as `React.useState` etc. (fully qualified, not destructured at
// top level) because sibling classic scripts share one global lexical
// scope - a repeated top-level `const useState = ...` across files is a
// SyntaxError there, not a harmless shadow.

const SCENARIOS = {
  optimal: {
    key: "optimal",
    label: "Optimal",
    subtitle: "Yield within target range",
    dot: "bg-emerald-500",
    badge: "border-emerald-200 bg-emerald-50 text-emerald-700",
    ring: "ring-emerald-500/30",
  },
  yieldAlert: {
    key: "yieldAlert",
    label: "Yield Loss Alert",
    subtitle: "Wastage spike, negative WIP balance flagged",
    dot: "bg-red-500",
    badge: "border-red-200 bg-red-50 text-red-700",
    ring: "ring-red-500/30",
  },
  grnBacklog: {
    key: "grnBacklog",
    label: "GRN Backlog",
    subtitle: "GRN receipts lagging stage demand",
    dot: "bg-amber-500",
    badge: "border-amber-200 bg-amber-50 text-amber-700",
    ring: "ring-amber-500/30",
  },
};

const PRODUCTS = [
  { id: "PC-8841", name: "HDPE Resin Pellets", unit: "KG" },
  { id: "PC-2207", name: "Recycled PET Flakes", unit: "KG" },
  { id: "PC-5519", name: "Woven Sack Fabric", unit: "MT" },
];

const WAREHOUSES = [
  { id: "WH-MAIN", name: "Main Warehouse" },
  { id: "WH-DEPOT2", name: "Depot-2" },
];

const STAGES = [
  { id: "STG-EXT-01", name: "Extrusion" },
  { id: "STG-BLND-02", name: "Blending" },
  { id: "STG-PACK-03", name: "Packing" },
];

const INITIAL_METRICS = { inputMass: 4820, wastage: 96, yieldLossPct: 2.1, negBalance: false };

function pick(arr) {
  return arr[Math.floor(Math.random() * arr.length)];
}

function randomFloat(min, max, decimals = 2) {
  return parseFloat((Math.random() * (max - min) + min).toFixed(decimals));
}

function randomId(prefix) {
  return `${prefix}_${Math.random().toString(16).slice(2, 10)}`;
}

function buildLogEntry(scenarioKey, tick) {
  const product = pick(PRODUCTS);
  const warehouse = pick(WAREHOUSES);
  const stage = pick(STAGES);
  const now = new Date().toISOString();
  const emitWastageEval = tick % 3 === 2 || scenarioKey !== "optimal";

  if (!emitWastageEval) {
    const eventType =
      scenarioKey === "grnBacklog"
        ? pick(["STOCK_OUT", "STOCK_OUT", "STOCK_IN"])
        : pick(["STOCK_IN", "STOCK_OUT", "GRN_STOCK_IN"]);
    const eventNameMap = {
      STOCK_IN: "inventory.stock-in",
      STOCK_OUT: "inventory.stock-out",
      GRN_STOCK_IN: "inventory.grn-stock-in",
    };
    const qty =
      scenarioKey === "grnBacklog" && eventType === "GRN_STOCK_IN"
        ? randomFloat(2, 15)
        : randomFloat(80, 420);

    return {
      tone: eventType === "STOCK_OUT" ? "neutral" : "positive",
      summary: `${eventType.replace(/_/g, " ")} · ${product.name} · ${warehouse.name} · ${qty} ${product.unit}`,
      json: {
        event: eventNameMap[eventType],
        payload: {
          companyId: randomId("co"),
          productId: product.id,
          warehouseId: warehouse.id,
          quantity: qty,
          stockMovementId: randomId("mv"),
          performedById: randomId("usr"),
          occurredAt: now,
        },
      },
    };
  }

  const stockIn = scenarioKey === "grnBacklog" ? randomFloat(2, 20) : randomFloat(300, 600);
  const stockOut = scenarioKey === "yieldAlert" ? randomFloat(250, 520) : randomFloat(150, 350);
  const remaining = parseFloat((stockIn - stockOut).toFixed(2));
  const wastage =
    scenarioKey === "yieldAlert" ? randomFloat(60, 140) : scenarioKey === "grnBacklog" ? randomFloat(5, 20) : randomFloat(2, 18);
  const wastagePct = parseFloat(((wastage / Math.max(stockIn, 1)) * 100).toFixed(2));
  const negBalance = remaining < 0 || scenarioKey === "yieldAlert";

  return {
    tone: scenarioKey === "yieldAlert" ? "danger" : scenarioKey === "grnBacklog" ? "warning" : "positive",
    summary: `WASTAGE EVAL · ${stage.name} · Yield Loss ${wastagePct}%${negBalance ? " ⚠ negative balance" : ""}`,
    json: {
      event: "production.wastage-ledger.evaluated",
      payload: {
        stageId: stage.id,
        productId: product.id,
        cycleId: randomId("cyc"),
        accumulatedStageStockIn: stockIn,
        accumulatedStageStockOut: stockOut,
        remainingInProgressQuantity: remaining,
        wastageQuantity: wastage,
        wastagePercentage: wastagePct,
        isCycleClosed: tick % 5 === 0,
        hasNegativeBalanceWarning: negBalance,
        triggeredByEventAction: scenarioKey === "grnBacklog" ? "STOCK_OUT" : "STOCK_IN",
        evaluatedAt: now,
      },
    },
  };
}

function nextMetrics(scenarioKey, prev) {
  let { inputMass, wastage, yieldLossPct } = prev;
  let negBalance = prev.negBalance;

  if (scenarioKey === "optimal") {
    inputMass += randomFloat(40, 90);
    wastage += randomFloat(0.5, 2);
    yieldLossPct = parseFloat(Math.max(1, yieldLossPct + randomFloat(-0.3, 0.3)).toFixed(1));
    negBalance = false;
  } else if (scenarioKey === "yieldAlert") {
    inputMass += randomFloat(10, 30);
    wastage += randomFloat(8, 22);
    yieldLossPct = parseFloat(Math.min(38, yieldLossPct + randomFloat(1.5, 4)).toFixed(1));
    negBalance = yieldLossPct > 14;
  } else {
    inputMass += randomFloat(0, 8);
    wastage += randomFloat(1, 5);
    yieldLossPct = parseFloat(Math.min(22, yieldLossPct + randomFloat(0.5, 1.8)).toFixed(1));
    negBalance = true;
  }

  return {
    inputMass: parseFloat(inputMass.toFixed(1)),
    wastage: parseFloat(wastage.toFixed(1)),
    yieldLossPct,
    negBalance,
  };
}

const TONE_STYLES = {
  positive: { dot: "bg-emerald-500", text: "text-emerald-300" },
  neutral: { dot: "bg-blue-300", text: "text-blue-200" },
  warning: { dot: "bg-amber-400", text: "text-amber-300" },
  danger: { dot: "bg-red-400", text: "text-red-300" },
};

function StatTile({ label, value, unit, danger }) {
  return (
    <div className="rounded-card border border-slate-200 bg-surface-card p-4 shadow-card">
      <div className="text-xs font-semibold uppercase tracking-wide text-brand-steel">{label}</div>
      <div className={`mt-1.5 text-2xl font-bold ${danger ? "text-red-600" : "text-brand-navy"}`}>
        {value}
        {unit ? <span className="ml-1 text-sm font-medium text-brand-steel">{unit}</span> : null}
      </div>
    </div>
  );
}

function InteractiveSimulator() {
  const [scenario, setScenario] = React.useState("optimal");
  const [tick, setTick] = React.useState(0);
  const [logs, setLogs] = React.useState([]);
  const [metrics, setMetrics] = React.useState(INITIAL_METRICS);
  const logRef = React.useRef(null);

  React.useEffect(() => {
    const interval = setInterval(() => setTick((t) => t + 1), 2200);
    return () => clearInterval(interval);
  }, []);

  React.useEffect(() => {
    if (tick === 0) return;
    const entry = buildLogEntry(scenario, tick);
    setLogs((prev) => [...prev.slice(-24), { id: `${tick}-${Date.now()}`, ...entry }]);
    setMetrics((prev) => nextMetrics(scenario, prev));
  }, [tick]); // eslint-disable-line

  React.useEffect(() => {
    if (logRef.current) logRef.current.scrollTop = logRef.current.scrollHeight;
  }, [logs]);

  const handleScenario = (key) => {
    if (key === scenario) return;
    setScenario(key);
    setTick(0);
    setLogs([]);
    setMetrics(INITIAL_METRICS);
  };

  const active = SCENARIOS[scenario];

  return (
    <div className="overflow-hidden rounded-card border border-slate-200 bg-surface-card shadow-premium">
      {/* Header / status */}
      <div className="flex flex-col gap-4 border-b border-slate-100 p-6 sm:flex-row sm:items-center sm:justify-between">
        <div>
          <div className="flex items-center gap-2">
            <h3 className="text-lg font-bold text-brand-navy">Workflow Engine - Live Event Monitor</h3>
            <span
              className={`inline-flex items-center gap-1.5 rounded-full border px-2.5 py-0.5 text-xs font-semibold ${active.badge}`}
            >
              <span className={`h-1.5 w-1.5 animate-blip rounded-full ${active.dot}`} />
              {active.label}
            </span>
          </div>
          <p className="mt-1 text-sm text-slate-500">{active.subtitle}</p>
        </div>

        {/* Scenario trigger buttons - Accent Green per SPEC-07 UI direction */}
        <div className="flex flex-wrap gap-2">
          {Object.values(SCENARIOS).map((s) => {
            const isActive = s.key === scenario;
            return (
              <button
                key={s.key}
                type="button"
                onClick={() => handleScenario(s.key)}
                className={`rounded-card px-3.5 py-2 text-xs font-semibold transition ${
                  isActive
                    ? `bg-emerald-600 text-white shadow-card ring-2 ring-offset-2 ${active.ring}`
                    : "border border-emerald-600/40 bg-white text-emerald-700 hover:bg-emerald-50"
                }`}
              >
                {s.label}
              </button>
            );
          })}
        </div>
      </div>

      {/* KPI tiles - reuse the real dashboard's own widget titles/units */}
      <div className="grid grid-cols-2 gap-3 p-6 sm:grid-cols-4">
        <StatTile label="Total Input Mass" value={metrics.inputMass.toLocaleString()} unit="KG" />
        <StatTile label="Total Wastage" value={metrics.wastage.toLocaleString()} unit="KG" danger={scenario === "yieldAlert"} />
        <StatTile
          label="Yield / Scrap Loss %"
          value={metrics.yieldLossPct}
          unit="%"
          danger={metrics.yieldLossPct > 12}
        />
        <StatTile
          label="Negative Balance Warning"
          value={metrics.negBalance ? "YES" : "NO"}
          danger={metrics.negBalance}
        />
      </div>

      {/* Log console */}
      <div className="px-6 pb-6">
        <div className="mb-2 flex items-center justify-between">
          <span className="text-xs font-semibold uppercase tracking-wide text-brand-steel">
            Workflow Engine Event Stream
          </span>
          <span className="flex items-center gap-1.5 text-xs text-slate-400">
            <span className="h-1.5 w-1.5 animate-pulse-subtle rounded-full bg-emerald-500" />
            streaming
          </span>
        </div>
        <div
          ref={logRef}
          className="h-72 overflow-y-auto rounded-card bg-blue-950 p-4 font-mono text-xs leading-relaxed text-blue-100"
        >
          {logs.length === 0 ? (
            <p className="text-blue-300/60">Waiting for the first event…</p>
          ) : (
            logs.map((entry) => {
              const tone = TONE_STYLES[entry.tone];
              return (
                <div key={entry.id} className="animate-log-in mb-3 border-b border-white/5 pb-3 last:border-0">
                  <div className="flex items-center gap-2">
                    <span className={`h-1.5 w-1.5 rounded-full ${tone.dot}`} />
                    <span className={`font-semibold ${tone.text}`}>{entry.summary}</span>
                  </div>
                  <pre className="mt-1.5 whitespace-pre-wrap break-words text-blue-200/70">
{JSON.stringify(entry.json, null, 2)}
                  </pre>
                </div>
              );
            })
          )}
        </div>
      </div>

      {/* Mandatory disclaimer - SPEC-07 Section 5 */}
      <div className="border-t border-slate-100 bg-surface px-6 py-3.5 text-xs leading-relaxed text-slate-500">
        Simulated for demonstration only. Event names and field structure mirror SkelBiz's real Workflow
        Engine and Wastage Ledger, but every value here is generated in your browser and is not connected
        to any live company account.
      </div>
    </div>
  );
}
