#!/bin/bash
# test-playground-migrations.sh — Playground v3 dataVersion v1->v2 idempotency
#
# Verifiserer:
#   1. fixture (playground/test-fixtures/state-v1-snapshot.json) eksisterer + er v1
#   2. V2_FOUNDATION-blokken kan ekstraheres fra HTML-fila
#   3. migrateDataVersion(fixture) gir resultat A
#   4. migrateDataVersion(A) gir resultat B
#   5. JSON.stringify(A) === JSON.stringify(B)  -> idempotency
#   6. A.dataVersion === 2  -> migrasjonen ble utført
#
# Bash 3.2-kompatibel. Bruker node til JS-eval; ingen npm-deps.
# Designet for å integreres i tests/run-e2e.sh --playground.

set -euo pipefail

PLUGIN_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
HTML_FILE="$PLUGIN_ROOT/playground/ms-ai-architect-playground.html"
FIXTURE_FILE="$PLUGIN_ROOT/playground/test-fixtures/state-v1-snapshot.json"

# shellcheck disable=SC1091
source "$PLUGIN_ROOT/tests/lib/e2e-helpers.sh"

init_suite "Playground v3 — dataVersion v1->v2 migration idempotency"

# ---- 1. Filer eksisterer ----
if [ ! -f "$HTML_FILE" ]; then
  fail "HTML-fila finnes ikke: $HTML_FILE"
  print_summary; exit 1
fi
pass "HTML-fil finnes: $(basename "$HTML_FILE")"

if [ ! -f "$FIXTURE_FILE" ]; then
  fail "Fixture mangler: $FIXTURE_FILE"
  print_summary; exit 1
fi
pass "Fixture finnes: $(basename "$FIXTURE_FILE")"

# ---- 2. Fixture er v1 (mangler dataVersion eller dataVersion < 2) ----
if node -e "
const f = JSON.parse(require('fs').readFileSync(process.argv[1], 'utf8'));
if (f.dataVersion === 2) { console.error('fixture er allerede v2'); process.exit(1); }
if (typeof f.schemaVersion !== 'number') { console.error('fixture mangler schemaVersion'); process.exit(1); }
if (!Array.isArray(f.projects) || f.projects.length === 0) { console.error('fixture har ingen projects'); process.exit(1); }
" "$FIXTURE_FILE" 2>/dev/null; then
  pass "Fixture er v1-state (dataVersion ikke satt)"
else
  fail "Fixture er ikke gyldig v1-state"
  print_summary; exit 1
fi

# ---- 3. V2_FOUNDATION-markører eksisterer i HTML ----
if grep -q "V2_FOUNDATION_BEGIN" "$HTML_FILE" && grep -q "V2_FOUNDATION_END" "$HTML_FILE"; then
  pass "V2_FOUNDATION_BEGIN/END markører finnes"
else
  fail "Mangler V2_FOUNDATION-markører i HTML"
  print_summary; exit 1
fi

# ---- 4. migrateDataVersion-funksjonen er definert ----
if grep -q "function migrateDataVersion" "$HTML_FILE"; then
  pass "migrateDataVersion-funksjonen finnes"
else
  fail "migrateDataVersion-funksjonen mangler"
  print_summary; exit 1
fi

# ---- 5. Eval idempotency-test i node ----
# Strategi: ekstraher V2_FOUNDATION-blokken via sed, wrap med stubs (window,
# CATALOG-mock som returnerer archetype basert på fixture command-IDs), eval,
# kjør migrasjon to ganger på fixture-deep-copy, sammenlign JSON.stringify.

IDEMPOTENCY_RESULT=$(node -e '
const fs = require("fs");
const path = require("path");
const htmlPath = process.argv[1];
const fixturePath = process.argv[2];

const html = fs.readFileSync(htmlPath, "utf8");
const beginMarker = "// === V2_FOUNDATION_BEGIN ===";
const endMarker = "// === V2_FOUNDATION_END ===";
const beginIdx = html.indexOf(beginMarker);
const endIdx = html.indexOf(endMarker);
if (beginIdx < 0 || endIdx < 0) {
  console.error("MARKER_MISSING");
  process.exit(2);
}
const block = html.substring(beginIdx, endIdx + endMarker.length);

// Stub-ene som blokken trenger
const stubs = `
  const window = {};
  function escapeHtml(s) { return String(s == null ? "" : s).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"); }
  function escapeAttr(s) { return escapeHtml(s); }
  // Mock CATALOG: kun de command-id-ene fixture-en bruker.
  const CATALOG = { commands: [
    { id: "classify", report_archetype: "aiact" },
    { id: "ros",      report_archetype: "matrix-risk" },
    { id: "cost",     report_archetype: "cost-distribution" },
    { id: "summary",  report_archetype: "verdict" }
  ]};
`;

const wrapped = stubs + block + "\nreturn { migrateDataVersion, defaultArchetypeFor };";
let api;
try {
  api = (new Function(wrapped))();
} catch (e) {
  console.error("EVAL_FAILED:", e.message);
  process.exit(3);
}

const fixture = JSON.parse(fs.readFileSync(fixturePath, "utf8"));

// Deep clones så vi sammenligner uavhengige objekter
const stateA = JSON.parse(JSON.stringify(fixture));
api.migrateDataVersion(stateA, api.defaultArchetypeFor);

const stateB = JSON.parse(JSON.stringify(stateA));
api.migrateDataVersion(stateB, api.defaultArchetypeFor);

const a = JSON.stringify(stateA);
const b = JSON.stringify(stateB);

if (stateA.dataVersion !== 2) {
  console.error("DATA_VERSION_NOT_BUMPED");
  process.exit(4);
}

// Sjekk at minst én rapport fikk verdict + keyStats utledet
let verdictsAdded = 0, statsAdded = 0;
for (const p of (stateA.projects || [])) {
  for (const id of Object.keys(p.reports || {})) {
    const r = p.reports[id];
    if (r && r.parsed) {
      if (r.parsed.verdict != null) verdictsAdded++;
      if (Array.isArray(r.parsed.keyStats)) statsAdded++;
    }
  }
}
if (verdictsAdded === 0) { console.error("NO_VERDICTS_ADDED"); process.exit(5); }
if (statsAdded === 0)    { console.error("NO_KEYSTATS_ADDED"); process.exit(6); }

if (a === b) {
  console.log("IDEMPOTENT verdicts=" + verdictsAdded + " stats=" + statsAdded);
} else {
  console.error("NOT_IDEMPOTENT");
  process.exit(7);
}
' "$HTML_FILE" "$FIXTURE_FILE" 2>&1) || RC=$?

if [ "${RC:-0}" -eq 0 ] && echo "$IDEMPOTENCY_RESULT" | grep -q "^IDEMPOTENT"; then
  pass "migrateDataVersion er idempotent ($IDEMPOTENCY_RESULT)"
else
  fail "Idempotency-test feilet: $IDEMPOTENCY_RESULT"
fi

# ---- 6. dataVersion bumpes til 2 ved første kjøring ----
DV_RESULT=$(node -e '
const fs = require("fs");
const html = fs.readFileSync(process.argv[1], "utf8");
const begin = html.indexOf("// === V2_FOUNDATION_BEGIN ===");
const end   = html.indexOf("// === V2_FOUNDATION_END ===");
const block = html.substring(begin, end + 32);
const stubs = `
  const window = {};
  function escapeHtml(s) { return String(s == null ? "" : s); }
  function escapeAttr(s) { return escapeHtml(s); }
  const CATALOG = { commands: [
    { id: "classify", report_archetype: "aiact" }
  ]};
`;
const api = (new Function(stubs + block + "\nreturn { migrateDataVersion, defaultArchetypeFor };"))();
const state = { schemaVersion: 1, projects: [] };
api.migrateDataVersion(state, api.defaultArchetypeFor);
console.log(state.dataVersion);
' "$HTML_FILE" 2>&1) || true

if [ "$DV_RESULT" = "2" ]; then
  pass "dataVersion bumpes til 2"
else
  fail "dataVersion ble ikke bumpet til 2 (got '$DV_RESULT')"
fi

print_summary
