const assert = require("assert");
const fs = require("fs");
const path = require("path");
const { createAssistantPanelManager } = require("../src/web/public/assistant-panels");

async function run() {
  verifySlotPlacement();
  await verifyDynamicLifecycle();
  console.log("Assistant panel verification passed.");
}

function verifySlotPlacement() {
  const layout = fs.readFileSync(
    path.join(__dirname, "..", "src", "web", "views", "partials", "layout-top.ejs"),
    "utf8"
  );
  const nav = layout.indexOf('<nav class="sidebar-nav">');
  const slot = layout.indexOf("data-assistant-panel-slot");
  const footer = layout.indexOf('<div class="sidebar-footer">');
  assert(nav >= 0 && slot > nav && footer > slot, "Assistant slot must be between nav and footer.");
  assert.equal(layout.includes("include(panel.view"), false, "Assistant panels must not be server-rendered into navigation.");
  const server = fs.readFileSync(
    path.join(__dirname, "..", "src", "web", "server.js"),
    "utf8"
  );
  assert(server.includes('app.get("/api/assistant-panels"'), "Assistant availability endpoint must exist.");
  assert(server.includes("if (!req.session.user)"), "Assistant endpoint must reject anonymous visibility.");
  assert(server.includes('typeof panel.canAccess === "function"'), "Assistant endpoint must honor plugin permission resolvers.");
  assert(server.includes("render_error:"), "Assistant endpoint must return structured render failures.");
  const plugin = fs.readFileSync(
    path.join(__dirname, "..", "plugins", "lumi_ai", "index.js"),
    "utf8"
  );
  assert(plugin.includes("canAccess: (user) => canUseAssistant"), "Lumi AI panel must use the shared permission resolver.");
  assert.equal(plugin.includes('role: "user",\n        version:'), false, "Lumi AI panel must not use unsupported core user RBAC.");
}

async function verifyDynamicLifecycle() {
  const roots = [];
  const diagnosticReports = [];
  const slot = {
    appendChild(root) {
      roots.push(root);
      root.parent = this;
      root.isConnected = true;
    }
  };
  const document = {
    hidden: false,
    head: {
      appendChild(element) {
        element.onload?.();
      }
    },
    querySelector(selector) {
      return selector === "[data-assistant-panel-slot]" ? slot : null;
    },
    createElement(tag) {
      if (tag === "template") {
        const template = { content: { firstElementChild: null } };
        Object.defineProperty(template, "innerHTML", {
          set() {
            const root = {
              dataset: {},
              isConnected: false,
              remove() {
                const index = roots.indexOf(this);
                if (index >= 0) roots.splice(index, 1);
                this.isConnected = false;
              }
            };
            template.content.firstElementChild = root;
          }
        });
        return template;
      }
      return {};
    },
    addEventListener() {},
    removeEventListener() {}
  };
  const manager = createAssistantPanelManager({
    document,
    fetch: async (url, options = {}) => {
      if (String(url).includes("visibility-debug")) {
        diagnosticReports.push(JSON.parse(options.body));
        return { ok: true, status: 200, json: async () => ({ success: true }) };
      }
      return { ok: true, status: 200, json: async () => ({ panels: [] }) };
    },
    setInterval: () => 1,
    clearInterval() {}
  });
  let mounts = 0;
  let unmounts = 0;
  manager.register("lumi_ai", {
    mount() { mounts += 1; },
    unmount() { unmounts += 1; }
  });
  const available = {
    panels: [{
      available: true,
      panel_id: "lumi_ai",
      version: "1",
      html: '<div data-assistant-panel-id="lumi_ai"></div>'
    }]
  };
  await manager.reconcile(available);
  await manager.reconcile(available);
  assert.equal(roots.length, 1, "Repeated availability must not duplicate the panel.");
  assert.equal(mounts, 1, "Repeated availability must not duplicate initialization.");

  await manager.reconcile({
    panels: [{ ...available.panels[0], version: "2" }]
  });
  assert.equal(roots.length, 1, "Version changes must replace rather than duplicate the panel.");
  assert.equal(mounts, 2);
  assert.equal(unmounts, 1);

  await manager.reconcile({
    panels: [{ available: false, panel_id: "lumi_ai", status: "offline" }]
  });
  assert.equal(roots.length, 0, "Unavailable panels must be removed.");
  assert.equal(unmounts, 2, "Removal must invoke plugin cleanup.");
  await manager.reconcile({
    panels: [{ available: true, panel_id: "lumi_ai", version: "3", html: "" }]
  });
  assert.equal(roots.length, 0, "Empty panel HTML must not mount.");
  assert(diagnosticReports.some((report) => report.mount_error?.includes("empty HTML")));
  manager.destroy();
}

run().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});
