/**
 * SET 96a — deterministic context bundle assembly.
 *
 * Builds the watcher digest, advisory union page, and superbuffer from one
 * snapshot. This module never invokes an LLM; callers retain ownership of any
 * watcher synthesis that refreshes the optional cached reading.
 */
import type { FeatureNode, FeatureSpec, GeneratedFile, LedgerRow } from '../core/types';
import type { IRParts } from '../core/irScaffold';
import {
  buildEpochDigest,
  formatDigest,
  formatUnionPage,
} from './watcher';
import type { EpochDigest, WatchEpoch, WatchReport } from './watcher';
import {
  assembleSuperbuffer,
  formatSuperbufferForPrompt,
} from './superbuffer';
import type {
  SuperbufferAssembly,
  SuperbufferContext,
  SuperbufferStage,
} from './superbuffer';
import type { Tier1Lesson } from './substrate';
import type { SubstrateHandoff } from './substrateHandoff';

export interface ContextBundle {
  /** Deterministic digest of the ledger and artifact snapshot. */
  digest: EpochDigest;
  /** Advisory union page, using the supplied watcher reading when available. */
  unionText: string;
  /** Full assembly for existing emission/metrics ownership in the runner. */
  assembly: SuperbufferAssembly;
  /** Prompt-ready superbuffer bytes. */
  superbufferText: string;
  /** Candidate-zero material reserved for SET 96b; not used by SET 96a callers. */
  digestPreamble: string;
}

/**
 * Inputs for deterministic digest + superbuffer assembly. The optional fields
 * mirror every contextual field accepted by `assembleSuperbuffer`.
 */
export interface AssembleContextOpts {
  stage: WatchEpoch;
  featureId: string;
  spec: FeatureSpec;
  feature: FeatureNode;
  parts: IRParts | null;
  stubs: GeneratedFile[];
  lessons: Tier1Lesson[];
  siblingParts: Map<string, IRParts>;
  target: string;
  ledgerRows: readonly LedgerRow[];
  artifact: GeneratedFile[];
  cachedReading?: WatchReport | null;
  substrateHandoff?: SubstrateHandoff | null;
  conceptText?: string | null;
  siblingImpls?: GeneratedFile[];
  signature?: SuperbufferContext['signature'];
  findingEvidence?: string | null;
  exhibitText?: string | null;
  traceText?: string | null;
  ledgerText?: string | null;
  superbufferStage?: SuperbufferStage;
}

export function assembleContext(opts: AssembleContextOpts): ContextBundle {
  const digest = buildEpochDigest({
    epoch: opts.stage,
    rows: opts.ledgerRows,
    artifact: opts.artifact,
    featureId: opts.featureId,
  });
  const unionText = formatUnionPage(digest, opts.cachedReading ?? null);
  const assembly = assembleSuperbuffer({
    spec: opts.spec,
    feature: opts.feature,
    parts: opts.parts,
    stubs: opts.stubs,
    lessons: opts.lessons,
    siblingParts: opts.siblingParts,
    target: opts.target,
    stage: opts.superbufferStage ?? 'fill',
    substrateHandoff: opts.substrateHandoff ?? null,
    conceptText: opts.conceptText ?? null,
    siblingImpls: opts.siblingImpls,
    signature: opts.signature,
    findingEvidence: opts.findingEvidence ?? null,
    exhibitText: opts.exhibitText ?? null,
    traceText: opts.traceText ?? null,
    ledgerText: opts.ledgerText ?? null,
    unionText,
  });
  const superbufferText = formatSuperbufferForPrompt(assembly);
  const digestPreamble = [
    'The pipeline ledger records this activity so far:',
    formatDigest(digest).slice(0, 800),
    '',
    'Note the recurring patterns above before writing your response.',
  ].join('\n');

  return { digest, unionText, assembly, superbufferText, digestPreamble };
}
