#!/bin/bash
# test-playground-projectview.sh — Playground v3 renderProjectView integration
#
# Verifiserer at renderProjectView + sub-renderers produserer korrekt HTML
# (som strenger — ingen DOM-deps) mot en inline demo-state-snippet.
#
# Dekker 4 view-tilstander:
#   - overview               (selectedArtifactId null)
#   - artifact (filled)      (selectedArtifactId = 'classify')
#   - empty (sidebar-treff)  (selectedArtifactId = 'frimpact' — mangler)
#   - import-modal-open      (top-state, orthogonal)
#
# Pluss:
#   - renderArtifactNav-søk filtrerer
#   - renderProjectOverview har 4 verdict-tiles, top-risks, next-actions, missing
#   - renderImportModal har 17 dropdown-options + prefill
#
# 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 — renderProjectView integration"

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 grep -q "PROJECT_VIEW_V2_BEGIN" "$HTML_FILE" && grep -q "PROJECT_VIEW_V2_END" "$HTML_FILE"; then
  pass "PROJECT_VIEW_V2_BEGIN/END markører finnes"
else
  fail "Mangler PROJECT_VIEW_V2-markører i HTML"
  print_summary; exit 1
fi

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

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

// 17 produces_report-renderers per PROJECT_VIEW_CONFIG.renderers.
// Hver stub returnerer en deterministisk HTML-streng vi kan asserte mot.
const RENDERER_IDS = ["renderAiActPyramid","renderRequirements","renderTransparency","renderFria","renderConformity","renderDpia","renderSecurity","renderRos","renderReview","renderCost","renderLicense","renderMigrate","renderAdr","renderSummary","renderPoc","renderUtredning","renderCompare"];
const rendererStubs = RENDERER_IDS.map(function (n) {
  return n + ": function (data, slot) { if (slot) slot.innerHTML = \"<div class=\\\"stub-\" + " + JSON.stringify(n) + " + \"\\\">\" + (data && data.title || \"stub\") + \"</div>\"; }";
}).join(", ");

const COMMANDS = [
  { id: "classify",     category: "regulatory",    label: "EU AI Act — Klassifisering",      description: "EU AI Act klass.", renderer: "renderAiActPyramid", produces_report: true, report_archetype: "aiact" },
  { id: "requirements", category: "regulatory",    label: "EU AI Act — Krav",                description: "Krav per risiko",  renderer: "renderRequirements", produces_report: true, report_archetype: "requirements-list" },
  { id: "transparency", category: "regulatory",    label: "Transparensnotis (Art. 13/50)",   description: "Art. 13/50",       renderer: "renderTransparency", produces_report: true, report_archetype: "text-document" },
  { id: "frimpact",     category: "regulatory",    label: "FRIA (Art. 27)",                   description: "FRIA",             renderer: "renderFria",         produces_report: true, report_archetype: "fria" },
  { id: "conformity",   category: "regulatory",    label: "Samsvarsvurdering (Art. 43)",      description: "Annex IV",         renderer: "renderConformity",   produces_report: true, report_archetype: "conformity-checklist" },
  { id: "dpia",         category: "regulatory",    label: "DPIA / PVK",                       description: "PVK",              renderer: "renderDpia",         produces_report: true, report_archetype: "matrix-risk" },
  { id: "security",     category: "security",      label: "Sikkerhetsvurdering (6×5)",        description: "6×5 scoring",      renderer: "renderSecurity",     produces_report: true, report_archetype: "matrix-risk-6x5" },
  { id: "ros",          category: "security",      label: "ROS-analyse",                      description: "NS 5814",          renderer: "renderRos",          produces_report: true, report_archetype: "matrix-risk" },
  { id: "review",       category: "security",      label: "Arkitekturgjennomgang",            description: "Digdir/NSM",       renderer: "renderReview",       produces_report: true, report_archetype: "findings" },
  { id: "cost",         category: "economy",       label: "Kostnadsestimat",                  description: "P10/P50/P90 NOK",  renderer: "renderCost",         produces_report: true, report_archetype: "cost-distribution" },
  { id: "license",      category: "economy",       label: "Lisenskartlegging",                description: "M365-lisenser",    renderer: "renderLicense",      produces_report: true, report_archetype: "scenario-comparison" },
  { id: "migrate",      category: "economy",       label: "Migrasjonsplan",                   description: "Fase-plan",        renderer: "renderMigrate",      produces_report: true, report_archetype: "phase-plan" },
  { id: "adr",          category: "documentation", label: "ADR",                              description: "MADR v3.0",        renderer: "renderAdr",          produces_report: true, report_archetype: "adr" },
  { id: "summary",      category: "documentation", label: "Beslutningsnotat",                 description: "Sammendrag",       renderer: "renderSummary",      produces_report: true, report_archetype: "verdict" },
  { id: "poc",          category: "documentation", label: "POC-plan",                         description: "Suksesskriterier", renderer: "renderPoc",          produces_report: true, report_archetype: "phase-plan" },
  { id: "utredning",    category: "documentation", label: "Utredning",                        description: "Utredningsinstr.", renderer: "renderUtredning",    produces_report: true, report_archetype: "utredning" },
  { id: "compare",      category: "documentation", label: "Plattformsammenligning",           description: "Plattformer",      renderer: "renderCompare",       produces_report: true, report_archetype: "scenario-comparison" }
];

// Demo state med 5 fylte artifacts + ui i forskjellige tilstander.
function buildDemoState(opts) {
  const o = opts || {};
  const now = "2026-05-15T10:00:00.000Z";
  return {
    dataVersion: 3,
    schemaVersion: 1,
    activeProjectId: "p1",
    projects: [{
      id: "p1",
      name: "Acme: Kunde-chatbot",
      description: "AI-system for objekt-deteksjon i sensordata.",
      createdAt: "2026-04-01T08:00:00.000Z",
      artifacts: {
        classify: {
          commandId: "classify",
          raw_markdown: "# EU AI Act — Klassifisering",
          parsed: { title: "Klassifisering", risk_level: "Høy", role: "Provider og Deployer" },
          verdict: "warning",
          keyStats: [{ label: "Risikonivå", value: "Høy" }],
          importedAt: now, updatedAt: now
        },
        ros: {
          commandId: "ros",
          raw_markdown: "# ROS-analyse",
          parsed: { title: "ROS", threats: [
            { id: "T1", description: "Modell-bias", severity: "Høy" },
            { id: "T2", description: "Privacy leak", severity: "Kritisk" },
            { id: "T3", description: "Hallusinerte fakta", severity: "Medium" }
          ]},
          verdict: "warning",
          keyStats: [],
          importedAt: now, updatedAt: now
        },
        security: {
          commandId: "security",
          raw_markdown: "# Sikkerhetsvurdering",
          parsed: { title: "Security", findings: [
            { id: "S1", finding: "Manglende DLP", severity: "Kritisk" },
            { id: "S2", finding: "Audit ufullstendig", severity: "Høy" }
          ]},
          verdict: "block",
          keyStats: [],
          importedAt: now, updatedAt: now
        },
        dpia: {
          commandId: "dpia",
          raw_markdown: "# DPIA",
          parsed: { title: "DPIA", threats: [] },
          verdict: "go-with-conditions",
          keyStats: [],
          importedAt: now, updatedAt: now
        },
        cost: {
          commandId: "cost",
          raw_markdown: "# Kostnadsestimat",
          parsed: { title: "Kostnad", p10: 78000, p50: 142000, p90: 285000 },
          verdict: "approved",
          keyStats: [{ label: "P50/mnd", value: "142 000 NOK" }],
          importedAt: now, updatedAt: now
        }
      },
      reports: {}
    }],
    ui: {
      projectView: {
        selectedArtifactId: o.selectedArtifactId === undefined ? null : o.selectedArtifactId,
        searchQuery: o.searchQuery || ""
      },
      importModal: {
        open: !!o.importOpen,
        prefillCommandId: o.prefillCommandId || "",
        prefillMarkdown: o.prefillMarkdown || ""
      }
    }
  };
}

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); }
  function renderPageShell(opts, body) {
    const t = (opts && opts.title) || "";
    const e = (opts && opts.eyebrow) || "";
    const v = (opts && opts.verdict) || "";
    return "<header class=\\"page__header\\" data-eyebrow=\\"" + escapeAttr(e) + "\\" data-verdict=\\"" + escapeAttr(v) + "\\"><h1>" + escapeHtml(t) + "</h1></header>" + (body || "");
  }
  function renderVerdictPill(v) {
    return "<span class=\\"verdict-pill\\" data-verdict=\\"" + escapeAttr(String(v || "").toLowerCase()) + "\\">" + escapeHtml(String(v || "").toUpperCase()) + "</span>";
  }
  function renderKeyStatsGrid(s) { return "<div class=\\"key-stats\\">" + (Array.isArray(s) ? s.length : 0) + "</div>"; }
  function inferVerdict() { return "n-a"; }
  function inferKeyStats() { return []; }
  const PARSERS = {};
  const RENDERERS = { ` + rendererStubs + ` };
  const CATALOG = { commands: ` + JSON.stringify(COMMANDS) + ` };
  const ACTIONS = {};
  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;
  }
  function scheduleRender() {}
`;

const wrapped = stubs + block + "\nreturn { renderProjectView, renderProjectHeader, renderArtifactNav, renderArtifactNavItem, renderProjectMain, renderProjectOverview, renderProjectArtifact, renderEmptyArtifactPrompt, renderImportModal, PROJECT_VIEW_CONFIG, setStoreState };";
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); }

// ---- API-eksponering ----
emit(typeof api.renderProjectView === "function", "renderProjectView er funksjon");
emit(typeof api.renderProjectOverview === "function", "renderProjectOverview er funksjon");
emit(typeof api.renderImportModal === "function", "renderImportModal er funksjon");
emit(typeof api.PROJECT_VIEW_CONFIG === "object" && api.PROJECT_VIEW_CONFIG !== null, "PROJECT_VIEW_CONFIG eksponert");

// ---- View 1: overview (selectedArtifactId null) ----
let demo = buildDemoState({});
api.setStoreState(demo);
let project = demo.projects[0];
let html = api.renderProjectView(project, api.PROJECT_VIEW_CONFIG);

emit(html.indexOf("class=\"project-view\"") !== -1 && html.indexOf("data-view=\"overview\"") !== -1,
     "overview: .project-view rot med data-view=\"overview\"");
emit(html.indexOf("Acme: Kunde-chatbot") !== -1,
     "overview: prosjekt-navn rendres i header");
emit(html.indexOf("data-action=\"import-open\"") !== -1,
     "overview: Importer-rapport-knapp finnes");
// Alle 4 kategori-grupper i sidebaren
emit(html.indexOf("Regulatorisk") !== -1 && html.indexOf("Risiko &amp; sikkerhet") !== -1 && html.indexOf("Økonomi") !== -1 && html.indexOf("Dokumentasjon") !== -1,
     "overview: alle 4 kategori-labels rendres i nav");
// Overview-tiles (verdict-grid)
emit(html.indexOf("project-overview__verdict-tile") !== -1,
     "overview: project-overview__verdict-tile finnes");
const tileCount = (html.match(/project-overview__verdict-tile/g) || []).length;
emit(tileCount >= 4, "overview: minst 4 verdict-tiles (got " + tileCount + ")");
// Top-risks (3 fra ros + 2 fra security = 5)
emit(html.indexOf("top-risks") !== -1 && html.indexOf("Privacy leak") !== -1,
     "overview: top-risks-listen inkluderer ROS-trussel");
// Next-actions / missing reports
emit(html.indexOf("project-overview__next-actions") !== -1 || html.indexOf("empty-hint") !== -1,
     "overview: next-actions-seksjon rendres");
emit(html.indexOf("project-overview__missing-reports") !== -1 || html.indexOf("Alle må-ha-rapporter er importert") !== -1,
     "overview: missing-reports-seksjon rendres");

// ---- View 2: artifact (filled) ----
demo = buildDemoState({ selectedArtifactId: "classify" });
api.setStoreState(demo);
project = demo.projects[0];
html = api.renderProjectView(project, api.PROJECT_VIEW_CONFIG);
emit(html.indexOf("data-view=\"artifact\"") !== -1,
     "artifact: data-view=\"artifact\"");
emit(html.indexOf("project-view__artifact") !== -1 && html.indexOf("data-artifact=\"classify\"") !== -1,
     "artifact: .project-view__artifact med data-artifact=\"classify\"");
emit(html.indexOf("project-view__artifact-title") !== -1 && html.indexOf("EU AI Act — Klassifisering") !== -1,
     "artifact: command-label vises i artifact-header");
emit(html.indexOf("data-action=\"artifact-reimport\"") !== -1 && html.indexOf("data-action=\"artifact-delete\"") !== -1,
     "artifact: reimport + delete-action-knapper finnes");

// ---- View 3: empty (sidebar-treff uten artifact) ----
demo = buildDemoState({ selectedArtifactId: "frimpact" });
api.setStoreState(demo);
project = demo.projects[0];
html = api.renderProjectView(project, api.PROJECT_VIEW_CONFIG);
emit(html.indexOf("data-view=\"empty\"") !== -1,
     "empty: data-view=\"empty\"");
emit(html.indexOf("empty-artifact-prompt") !== -1 && html.indexOf("data-command=\"frimpact\"") !== -1,
     "empty: empty-artifact-prompt for frimpact");
emit(html.indexOf("data-prefill-command=\"frimpact\"") !== -1,
     "empty: Importer-knapp har data-prefill-command=\"frimpact\"");

// ---- View 4: import-modal-open ----
demo = buildDemoState({ importOpen: true, prefillCommandId: "ros", prefillMarkdown: "# ROS-analyse\nDemo" });
api.setStoreState(demo);
project = demo.projects[0];
html = api.renderProjectView(project, api.PROJECT_VIEW_CONFIG);
emit(html.indexOf("data-import-modal") !== -1,
     "import-modal: [data-import-modal] rendres når open=true");
// Dropdown har 17 options + tom default = 18 <option>-tags
const optionMatches = html.match(/<option /g) || [];
emit(optionMatches.length >= 17,
     "import-modal: dropdown har 17+ options (got " + optionMatches.length + ")");
emit(html.indexOf("value=\"ros\" selected") !== -1 || html.indexOf("value=\"ros\"  selected") !== -1,
     "import-modal: prefillCommandId=\"ros\" gir selected option");
emit(html.indexOf("# ROS-analyse") !== -1 || html.indexOf("ROS-analyse") !== -1,
     "import-modal: prefillMarkdown rendres i textarea");

// ---- Modal IKKE rendret når open=false ----
demo = buildDemoState({});
api.setStoreState(demo);
project = demo.projects[0];
html = api.renderProjectView(project, api.PROJECT_VIEW_CONFIG);
emit(html.indexOf("data-import-modal") === -1,
     "import-modal: ikke rendret når importModal.open=false");

// ---- renderArtifactNav-søk filtrerer ----
demo = buildDemoState({ searchQuery: "ros" });
api.setStoreState(demo);
project = demo.projects[0];
const navHtml = api.renderArtifactNav(project, api.PROJECT_VIEW_CONFIG, null, "ros");
emit(navHtml.indexOf("data-artifact-id=\"ros\"") !== -1,
     "nav-filter: ROS-element finnes ved søk=\"ros\"");
emit(navHtml.indexOf("data-artifact-id=\"cost\"") === -1,
     "nav-filter: cost-element filtrert ut ved søk=\"ros\"");

// ---- renderProjectView med null project ----
emit(api.renderProjectView(null, api.PROJECT_VIEW_CONFIG).indexOf("Ingen prosjekt valgt") !== -1,
     "guard: null project → empty-hint");
' "$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
