/**
 * # src/fill/held-position — the HELD POSITION AS OF THE GRADED BUS (the theta-floor owner)
 *
 * ## What this owns (and why it exists)
 * ONE surface answers the whole question "what is held, at what basis, worth what at each wake, and
 * therefore what does standing pat cost?" — reconstruction + basis + marking + the floor decision:
 *
 *   1. **Reconstruction** — net the graded ORDER `fill` stream per (strike, right) into the option
 *      inventory a STAND-PAT watcher actually carries ({@link reconstructHeldOptionLegs}).
 *   2. **Basis** — each held leg's ABS-qty-weighted blended premium over the FULL fill history,
 *      including the portion later closed (the cost basis the bleed marks against).
 *   3. **Marking** — the per-wake mark of those legs against the tape's own option book
 *      ({@link markHeldLegsPerWake}, the pure marking kernel this owner drives).
 *   4. **The floor decision** — the stand-down floor and the `theta_bleed` record (or `null`) the sim
 *      driver folds into the graded Blotter.
 *
 * Before this owner, (1)+(2) lived as an *untested private function inside the sim driver* and the driver
 * hand-assembled (4) around a call to (3). The floor was therefore decided by driver glue sitting
 * downstream of reconstruction nothing could reach: a tested leaf below an untested private step. The
 * theta gate's own history is the cautionary tale — `markHeldLegsPerWake` had a green UNIT test while
 * nothing threaded the flag into the sim, so the property was inert in production. Concentrating the
 * three steps behind this one surface makes the TESTED thing the thing that decides the floor.
 *
 * ## Gated, additive, byte-identical when OFF
 * The gate is {@link HeldPositionInput.markToModel}. `false`/absent ⇒ nothing is reconstructed, nothing
 * marked, `standDownFloorUsd` is exactly `0` and {@link HeldPositionResult.thetaBleed} is `null` — the
 * driver emits no record and every existing pinned floor is byte-identical. The bleed only binds when a
 * position is actually HELD across ≥1 delivered wake: a flat book, or a watcher that closed out
 * (net-zero inventory), yields no legs and hence no record.
 *
 * Pure: no wall clock, no RNG, no lookahead (each wake folds the book only up to its own ts).
 */

import type { BusEvent, Right, TelemetryThetaBleedPayload } from "../bus/types.ts";
import { markHeldLegsPerWake, type HeldOptionLeg, type WakeMark } from "./mark-to-model.ts";

export interface HeldPositionInput {
  /** The GRADED bus (the driver's emitted stream) — the ORDER `fill` events the position is netted from. */
  readonly graded: readonly BusEvent[];
  /** The TAPE (BOOK events are folded into the running option book the legs are marked against). */
  readonly tape: readonly BusEvent[];
  /** The option-underlier symbol whose fills are netted and whose book is folded (e.g. `"SPY"`). */
  readonly instrument: string;
  /** The DELIVERED wake instants (UTC ms) to mark at. Empty ⇒ nothing held across a wake ⇒ no bleed. */
  readonly wakeTsList: readonly number[];
  /** THE GATE. `false`/absent ⇒ no reconstruction, no marking, `thetaBleed = null` — byte-identical. */
  readonly markToModel?: boolean;
  /** The ts to stamp the emitted `theta_bleed` record at (the session's last ts). */
  readonly recordTs: number;
  /** Contract multiplier (defaults to the marking kernel's listed-option 100). */
  readonly multiplier?: number;
}

export interface HeldPositionResult {
  /** Whether the marking pass actually ran (gate ON, ≥1 wake, ≥1 held leg) — an inert seam reads `false`. */
  readonly enabled: boolean;
  /** The reconstructed net held legs with their blended basis (empty when the gate is OFF). */
  readonly legs: readonly HeldOptionLeg[];
  /** The per-wake mark series (empty when disabled or nothing is held). */
  readonly marks: readonly WakeMark[];
  /** The realized floor of STANDING DOWN at the LAST marked wake; `0` when nothing was marked. */
  readonly standDownFloorUsd: number;
  /**
   * The ONE `TELEMETRY theta_bleed` record the driver emits for this session, ready to stamp — or `null`
   * when there is nothing to charge (gate OFF, no delivered wake, or no held inventory). THIS is the
   * decision: the driver emits exactly what this surface returns and adds no judgement of its own.
   */
  readonly thetaBleed: (TelemetryThetaBleedPayload & { readonly ts: number }) | null;
}

/**
 * Reconstruct the NET HELD option legs of `instrument` from the graded ORDER `fill` stream — the
 * inventory a STAND-PAT watcher carries across the wakes. Nets buys against sells per (strike, right): a
 * closed round-trip nets to zero and is dropped, an open lot leaves a held leg. Each leg's
 * `basisPremium` is the ABS-qty-weighted average fill price over the FULL fill history (including the
 * closed portion) — the cost basis the theta bleed marks against. SPOT/equity legs (no strike/right,
 * ADR-0017) carry no option book to mark and are skipped. The leg `expiry` is deliberately omitted (a
 * fill carries none) — a reconstructed leg marks against the book's own single expiry, so the marking
 * kernel's multi-tenor guard is never engaged. Pure; no wall clock, no RNG.
 *
 * Exported so the reconstruction rule is reachable BESIDE the surface that consumes it; the sim driver
 * calls {@link heldPositionAsOfGradedBus}, never this directly.
 */
export function reconstructHeldOptionLegs(graded: readonly BusEvent[], instrument: string): HeldOptionLeg[] {
  interface Acc {
    qty: number;
    absQtyPx: number;
    absQty: number;
    strike: number;
    right: Right;
  }
  const acc = new Map<string, Acc>();
  for (const e of graded) {
    if (e.stream !== "ORDER" || e.type !== "fill") continue;
    if (e.instrument !== instrument) continue;
    if (e.strike === undefined || e.right === undefined) continue; // a spot/equity leg — no option book to mark
    const signed = e.side === "buy" ? e.qty : -e.qty;
    const key = `${e.strike}|${e.right}`;
    const a = acc.get(key) ?? { qty: 0, absQtyPx: 0, absQty: 0, strike: e.strike, right: e.right as Right };
    a.qty += signed;
    a.absQtyPx += Math.abs(e.qty) * (e.px ?? 0);
    a.absQty += Math.abs(e.qty);
    acc.set(key, a);
  }
  const legs: HeldOptionLeg[] = [];
  for (const a of acc.values()) {
    if (a.qty === 0) continue; // a closed round-trip — nothing held to bleed
    legs.push({
      side: a.qty > 0 ? "buy" : "sell",
      qty: Math.abs(a.qty),
      strike: a.strike,
      right: a.right,
      basisPremium: a.absQty > 0 ? a.absQtyPx / a.absQty : 0,
    });
  }
  return legs;
}

const INERT: HeldPositionResult = { enabled: false, legs: [], marks: [], standDownFloorUsd: 0, thetaBleed: null };

/**
 * The held position as of the graded bus: reconstruct → basis → mark → decide the theta floor. See the
 * module header. The sim driver's ENTIRE theta-cell step is one call to this plus emitting
 * {@link HeldPositionResult.thetaBleed} when it is non-`null`. Pure.
 */
export function heldPositionAsOfGradedBus(input: HeldPositionInput): HeldPositionResult {
  if (input.markToModel !== true || input.wakeTsList.length === 0) return INERT;

  const legs = reconstructHeldOptionLegs(input.graded, input.instrument);
  if (legs.length === 0) return INERT; // flat, or the watcher closed out — nothing held to bleed

  const multOpt = input.multiplier === undefined ? {} : { multiplier: input.multiplier };
  const marked = markHeldLegsPerWake({
    events: input.tape,
    instrument: input.instrument,
    legs,
    wakeTsList: input.wakeTsList,
    markToModel: true,
    ...multOpt,
  });
  const lastMark = marked.marks[marked.marks.length - 1];
  if (lastMark === undefined) return { ...INERT, legs }; // no wake resolved to a mark — nothing to charge

  return {
    enabled: true,
    legs,
    marks: marked.marks,
    standDownFloorUsd: marked.standDownFloorUsd,
    thetaBleed: {
      ts: input.recordTs,
      instrument: input.instrument,
      floor_pnl: marked.standDownFloorUsd,
      wakes: marked.marks.length,
      last_sellable: lastMark.sellablePerContract,
    },
  };
}
