#!/bin/bash
# test-playground-actions.sh — Playground v3 ACTIONS handler-state-effekter
#
# Verifiserer at de 6 pure-state-ACTIONS-handlerne (project-select-artifact,
# project-show-overview, import-open, import-close, artifact-reimport,
# artifact-delete) muterer state korrekt.
#
# Handlerne import-detect og import-save krever document/DOM og dekkes ikke
# her — de testes implisitt via browser-walkthrough før release og via
# manuell QA per playground/MANUAL-CHECKLIST.md.
#
# Bash 3.2-kompatibel. Bruker node til JS-eval. Ingen npm-deps.

set -euo pipefail

PLUGIN_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
HTML_FILE="$PLUGIN_ROOT/playground/ms-ai-architect-playground.html"

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

init_suite "Playground v3 — ACTIONS handler state-effekter"

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

NODE_OUT=$(node -e '
const fs = require("fs");
const htmlPath = process.argv[1];
const htmlSrc = fs.readFileSync(htmlPath, "utf8");

// Ekstraher ACTIONS-blokken fra "// PROJECT-VIEW V2 ACTIONS" (sesjon 3-kommentaren)
// til starten av smart-detect-blokken. Tar med projectViewUiState + 6 handlere.
const startMarker = "// PROJECT-VIEW V2 ACTIONS (Sesjon 3)";
const endMarker = "// Smart-detect på textarea-input i import-modal.";
const startIdx = htmlSrc.indexOf(startMarker);
const endIdx = htmlSrc.indexOf(endMarker);
if (startIdx < 0 || endIdx < 0) {
  console.error("MARKERS_MISSING start=" + startIdx + " end=" + endIdx);
  process.exit(2);
}
const block = htmlSrc.substring(startIdx, endIdx);

// Stubs som gir handlerne et minimums-miljø uten document/window.
const stubs = `
  let __store_state = null;
  const store = {
    get state() { return __store_state; },
    save: function () {}
  };
  function setStoreState(s) { __store_state = s; }
  function findProject(id) {
    const list = (store.state && store.state.projects) || [];
    for (let i = 0; i < list.length; i++) if (list[i].id === id) return list[i];
    return null;
  }
  let __renderCount = 0;
  function scheduleRender() { __renderCount++; }
  let __confirmAnswer = true;
  function confirm() { return __confirmAnswer; }
  function setConfirmAnswer(b) { __confirmAnswer = b; }
  function renderCount() { return __renderCount; }
  function resetRenderCount() { __renderCount = 0; }
  const ACTIONS = {};
`;
const wrapped = stubs + block + "\nreturn { ACTIONS, setStoreState, setConfirmAnswer, renderCount, resetRenderCount, projectViewUiState };";
let api;
try {
  api = (new Function(wrapped))();
} catch (e) {
  console.error("EVAL_FAILED: " + e.message);
  process.exit(3);
}

function emit(ok, desc) { console.log((ok ? "PASS" : "FAIL") + "\t" + desc); }

function freshState(opts) {
  const o = opts || {};
  return {
    schemaVersion: 1,
    dataVersion: 3,
    activeProjectId: "p1",
    projects: [{
      id: "p1",
      name: "Demo",
      artifacts: {
        classify: { commandId: "classify", raw_markdown: "RAW_CLASSIFY", parsed: { risk_level: "minimal" }, verdict: "go", keyStats: [], importedAt: "x", updatedAt: "x" },
        ros: { commandId: "ros", raw_markdown: "RAW_ROS", parsed: { threats: [] }, verdict: "approved", keyStats: [], importedAt: "x", updatedAt: "x" }
      },
      reports: {
        classify: { raw_markdown: "RAW_CLASSIFY", parsed: { risk_level: "minimal" } },
        ros: { raw_markdown: "RAW_ROS", parsed: { threats: [] } }
      }
    }],
    ui: o.ui || {}
  };
}

// ---- API ----
emit(typeof api.ACTIONS === "object" && api.ACTIONS !== null, "ACTIONS-objekt eksponert");
emit(typeof api.ACTIONS["project-select-artifact"] === "function", "project-select-artifact handler finnes");
emit(typeof api.ACTIONS["project-show-overview"] === "function",   "project-show-overview handler finnes");
emit(typeof api.ACTIONS["import-open"] === "function",             "import-open handler finnes");
emit(typeof api.ACTIONS["import-close"] === "function",            "import-close handler finnes");
emit(typeof api.ACTIONS["artifact-reimport"] === "function",       "artifact-reimport handler finnes");
emit(typeof api.ACTIONS["artifact-delete"] === "function",         "artifact-delete handler finnes");

// ---- project-select-artifact ----
(function () {
  const state = freshState();
  api.setStoreState(state);
  api.resetRenderCount();
  api.ACTIONS["project-select-artifact"]({}, { dataset: { artifactId: "classify" } });
  const ok = state.ui.projectView && state.ui.projectView.selectedArtifactId === "classify"
    && api.renderCount() === 1;
  emit(ok, "project-select-artifact setter selectedArtifactId og trigger scheduleRender (got=" + (state.ui.projectView && state.ui.projectView.selectedArtifactId) + ")");
})();

// ---- project-select-artifact uten artifactId — no-op ----
(function () {
  const state = freshState({ ui: { projectView: { selectedArtifactId: "ros", searchQuery: "" }, importModal: { open: false, prefillCommandId: "", prefillMarkdown: "" } } });
  api.setStoreState(state);
  api.resetRenderCount();
  api.ACTIONS["project-select-artifact"]({}, { dataset: {} });
  const ok = state.ui.projectView.selectedArtifactId === "ros" && api.renderCount() === 0;
  emit(ok, "project-select-artifact uten dataset.artifactId → no-op (selectedArtifactId beholdt, ingen render)");
})();

// ---- project-show-overview ----
(function () {
  const state = freshState({ ui: { projectView: { selectedArtifactId: "classify", searchQuery: "" }, importModal: { open: false, prefillCommandId: "", prefillMarkdown: "" } } });
  api.setStoreState(state);
  api.resetRenderCount();
  api.ACTIONS["project-show-overview"]({}, {});
  const ok = state.ui.projectView.selectedArtifactId === null && api.renderCount() === 1;
  emit(ok, "project-show-overview tømmer selectedArtifactId");
})();

// ---- import-open med prefill-command (eksisterende artifact gir prefillMarkdown) ----
(function () {
  const state = freshState();
  api.setStoreState(state);
  api.resetRenderCount();
  api.ACTIONS["import-open"]({}, { dataset: { prefillCommand: "ros" } });
  const m = state.ui.importModal;
  const ok = m && m.open === true && m.prefillCommandId === "ros"
    && m.prefillMarkdown === "RAW_ROS" && api.renderCount() === 1;
  emit(ok, "import-open med prefillCommand=\"ros\" åpner modal + prefyller raw_markdown");
})();

// ---- import-open uten prefill-command ----
(function () {
  const state = freshState();
  api.setStoreState(state);
  api.resetRenderCount();
  api.ACTIONS["import-open"]({}, { dataset: {} });
  const m = state.ui.importModal;
  const ok = m && m.open === true && m.prefillCommandId === "" && m.prefillMarkdown === "";
  emit(ok, "import-open uten prefill → modal åpnet, ingen prefyll");
})();

// ---- import-close ----
(function () {
  const state = freshState({ ui: { projectView: { selectedArtifactId: null, searchQuery: "" }, importModal: { open: true, prefillCommandId: "ros", prefillMarkdown: "RAW_ROS" } } });
  api.setStoreState(state);
  api.resetRenderCount();
  api.ACTIONS["import-close"]({}, {});
  const m = state.ui.importModal;
  const ok = m.open === false && m.prefillCommandId === "" && m.prefillMarkdown === "" && api.renderCount() === 1;
  emit(ok, "import-close tilbakestiller modal-state");
})();

// ---- artifact-reimport prefyller modal med eksisterende markdown ----
(function () {
  const state = freshState();
  api.setStoreState(state);
  api.resetRenderCount();
  api.ACTIONS["artifact-reimport"]({}, { dataset: { command: "classify" } });
  const m = state.ui.importModal;
  const ok = m.open === true && m.prefillCommandId === "classify" && m.prefillMarkdown === "RAW_CLASSIFY";
  emit(ok, "artifact-reimport åpner modal med prefill fra eksisterende artifact");
})();

// ---- artifact-delete med confirm=false → no-op ----
(function () {
  const state = freshState();
  api.setStoreState(state);
  api.setConfirmAnswer(false);
  api.resetRenderCount();
  api.ACTIONS["artifact-delete"]({}, { dataset: { command: "classify" } });
  const ok = state.projects[0].artifacts.classify !== undefined && api.renderCount() === 0;
  emit(ok, "artifact-delete med confirm=false → artifact bevart, ingen render");
})();

// ---- artifact-delete med confirm=true → sletter + clearer selectedArtifactId ----
(function () {
  const state = freshState({ ui: { projectView: { selectedArtifactId: "classify", searchQuery: "" }, importModal: { open: false, prefillCommandId: "", prefillMarkdown: "" } } });
  api.setStoreState(state);
  api.setConfirmAnswer(true);
  api.resetRenderCount();
  api.ACTIONS["artifact-delete"]({}, { dataset: { command: "classify" } });
  const p = state.projects[0];
  const ok = p.artifacts.classify === undefined && p.reports.classify === undefined
    && state.ui.projectView.selectedArtifactId === null && api.renderCount() === 1;
  emit(ok, "artifact-delete med confirm=true sletter artifact + reports + clearer selectedArtifactId");
})();

// ---- artifact-delete bevarer andre artifacts ----
(function () {
  const state = freshState();
  api.setStoreState(state);
  api.setConfirmAnswer(true);
  api.ACTIONS["artifact-delete"]({}, { dataset: { command: "ros" } });
  const p = state.projects[0];
  const ok = p.artifacts.classify !== undefined && p.artifacts.ros === undefined;
  emit(ok, "artifact-delete sletter bare den ene — andre artifacts bevart");
})();

// ---- projectViewUiState initialiserer state-grener idempotent ----
(function () {
  const state = { projects: [], ui: {} };
  api.setStoreState(state);
  const ui1 = api.projectViewUiState();
  const ui2 = api.projectViewUiState();
  const ok = ui1 === ui2
    && ui1.projectView && ui1.projectView.selectedArtifactId === null && ui1.projectView.searchQuery === ""
    && ui1.importModal && ui1.importModal.open === false;
  emit(ok, "projectViewUiState initialiserer projectView + importModal idempotent");
})();
' "$HTML_FILE" 2>&1) || NODE_RC=$?

if [ "${NODE_RC:-0}" -ne 0 ]; then
  fail "node-eval feilet (rc=${NODE_RC:-0}): $NODE_OUT"
  print_summary; exit 1
fi

while IFS=$'\t' read -r status desc; do
  case "$status" in
    PASS) pass "$desc" ;;
    FAIL) fail "$desc" ;;
    WARN) warn "$desc" ;;
  esac
done <<< "$NODE_OUT"

print_summary
