import type { SerializedWorld } from "./repository";
import type { ObjRef } from "./types";
import type { EffectTranscript, TranscriptValidation } from "./effect-transcript";
import { transcriptTouchedStateHash, validateTranscriptAgainstSerializedWorld } from "./effect-transcript";

export type ShadowCommitReceipt = {
  kind: "woo.commit_receipt.shadow.v1";
  id?: string;
  route: EffectTranscript["route"];
  scope: ObjRef;
  seq: number;
  transcript_hash: string;
  pre_state_hash: string;
  post_state_hash: string;
  accepted: boolean;
  errors: string[];
};

export function shadowCommitReceipt(
  serializedBefore: SerializedWorld,
  serializedAfter: SerializedWorld,
  transcript: EffectTranscript,
  extraErrors: string[] = [],
  precomputedValidation?: TranscriptValidation
): ShadowCommitReceipt {
  return shadowCommitReceiptFromTouchedStateHashes(
    transcript,
    transcriptTouchedStateHash(serializedBefore, transcript),
    transcriptTouchedStateHash(serializedAfter, transcript),
    extraErrors,
    precomputedValidation ?? validateTranscriptAgainstSerializedWorld(serializedBefore, transcript)
  );
}

export function shadowCommitReceiptFromTouchedStateHashes(
  transcript: EffectTranscript,
  preStateHash: string,
  postStateHash: string,
  extraErrors: string[] = [],
  precomputedValidation: TranscriptValidation = { ok: true, errors: [] }
): ShadowCommitReceipt {
  const errors = [
    ...precomputedValidation.errors,
    ...extraErrors,
    ...(transcript.complete ? [] : transcript.incompleteReasons.map((reason) => `incomplete:${reason}`))
  ];
  return {
    kind: "woo.commit_receipt.shadow.v1",
    id: transcript.id,
    route: transcript.route,
    scope: transcript.scope,
    seq: transcript.seq,
    transcript_hash: transcript.hash,
    pre_state_hash: preStateHash,
    post_state_hash: postStateHash,
    accepted: errors.length === 0,
    errors
  };
}
