// Cross-runtime parity helper — Go side.
//
// Specification: /home/profit/lakehouse/docs/specs/SUBJECT_MANIFESTS_ON_CATALOGD.md §5 Step 8.
//
// Counterpart of crates/catalogd/src/bin/parity_subject_audit.rs.
// Both helpers MUST produce byte-identical output for the same input.
//
// Modes:
//
//   --known-answer
//       Print canonical-JSON + HMAC for a hardcoded fixture. Compared
//       byte-for-byte against the Rust helper's output. If they
//       differ, the canonical-JSON or HMAC algorithm has drifted.
//
//   --verify <audit_log_path> --key <key_path>
//       Replay the HMAC chain on a real audit JSONL. Print one JSON
//       object: {mode, count, tip, verified, error}.
package main

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	cat "git.agentview.dev/profit/golangLAKEHOUSE/internal/catalogd"
)

const genesis = "GENESIS"

func deterministicKey() []byte {
	k := make([]byte, 32)
	for i := range k {
		k[i] = byte(i)
	}
	return k
}

// knownAnswerOut is intentionally identical to KnownAnswerOut in the
// Rust helper so a stdout diff is a one-line semantic comparison.
type knownAnswerOut struct {
	Mode              string `json:"mode"`
	Canonical         string `json:"canonical"`
	Hmac              string `json:"hmac"`
	CanonicalBytesLen int    `json:"canonical_bytes_len"`
}

type verifyOut struct {
	Mode     string `json:"mode"`
	Count    int    `json:"count"`
	Tip      string `json:"tip"`
	Verified bool   `json:"verified"`
	Error    *string `json:"error"`
}

func runKnownAnswer() {
	row := cat.SubjectAuditRow{
		Schema:      "subject_audit.v1",
		Ts:          time.Date(2026, 5, 3, 12, 0, 0, 0, time.UTC),
		CandidateID: "WORKER-FIXED",
		Accessor: cat.AuditAccessor{
			Kind:    "gateway_lookup",
			Daemon:  "gateway",
			Purpose: "parity_test",
			TraceID: "trace-fixed",
		},
		FieldsAccessed: []string{"name"},
		Result:         "success",
		PrevChainHash:  genesis,
	}
	canonical, hmacHex, err := cat.CanonicalAndHmac(&row, deterministicKey(), genesis)
	if err != nil {
		die("canonical/hmac: %v", err)
	}
	out := knownAnswerOut{
		Mode:              "known_answer",
		Canonical:         string(canonical),
		Hmac:              hmacHex,
		CanonicalBytesLen: len(canonical),
	}
	emit(out)
}

func runVerify(auditPath, keyPath string) {
	entries, err := cat.ReadAuditLog(auditPath)
	if err != nil {
		die("read audit log: %v", err)
	}
	key, err := os.ReadFile(keyPath)
	if err != nil {
		die("read key: %v", err)
	}
	count, tip, verr := cat.VerifyChain(entries, key)
	out := verifyOut{
		Mode:     "verify",
		Count:    count,
		Tip:      tip,
		Verified: verr == nil,
	}
	if verr != nil {
		s := verr.Error()
		out.Error = &s
		// Reset count + tip to match the Rust helper's error semantics.
		out.Count = 0
		out.Tip = genesis
	}
	emit(out)
}

func emit(v any) {
	bs, err := json.Marshal(v)
	if err != nil {
		die("marshal output: %v", err)
	}
	fmt.Println(string(bs))
}

func die(format string, a ...any) {
	fmt.Fprintf(os.Stderr, format+"\n", a...)
	os.Exit(2)
}

func main() {
	args := os.Args[1:]
	var (
		knownAnswer bool
		auditPath   string
		keyPath     string
	)
	for i := 0; i < len(args); i++ {
		switch args[i] {
		case "--known-answer":
			knownAnswer = true
		case "--verify":
			if i+1 >= len(args) {
				die("--verify needs a path")
			}
			auditPath = args[i+1]
			i++
		case "--key":
			if i+1 >= len(args) {
				die("--key needs a path")
			}
			keyPath = args[i+1]
			i++
		case "-h", "--help":
			fmt.Fprintln(os.Stderr, "subject_audit_helper --known-answer")
			fmt.Fprintln(os.Stderr, "subject_audit_helper --verify <audit_log> --key <key_file>")
			os.Exit(0)
		default:
			die("unknown arg: %s", args[i])
		}
	}
	if knownAnswer {
		runKnownAnswer()
		return
	}
	if auditPath == "" || keyPath == "" {
		die("need --known-answer OR (--verify <path> --key <path>)")
	}
	// Sanity: file naming convention <candidate_id>.audit.jsonl.
	if !strings.HasSuffix(filepath.Base(auditPath), ".audit.jsonl") {
		die("audit log path must end with .audit.jsonl")
	}
	runVerify(auditPath, keyPath)
}
