const assert = require("node:assert/strict");
const test = require("node:test");
const { enforceReadOnlyDemo } = require("../src/security/readOnlyDemo");

function response() {
  return {
    body: null,
    statusCode: null,
    status(code) {
      this.statusCode = code;
      return this;
    },
    send(body) {
      this.body = body;
      return this;
    },
  };
}

function run(request) {
  const res = response();
  let nextCalled = false;

  enforceReadOnlyDemo(request, res, () => {
    nextCalled = true;
  });

  return { nextCalled, res };
}

test("demo mode allows reads and login", () => {
  const previous = process.env.DEMO_MODE;
  process.env.DEMO_MODE = "true";

  try {
    assert.equal(run({ method: "GET", path: "/api/coaching/clients" }).nextCalled, true);
    assert.equal(run({ method: "POST", path: "/api/auth/signin/local" }).nextCalled, true);
    assert.equal(run({ method: "POST", path: "/api/auth/signin/demo" }).nextCalled, true);
  } finally {
    process.env.DEMO_MODE = previous;
  }
});

test("demo mode blocks persistent and costly operations", () => {
  const previous = process.env.DEMO_MODE;
  process.env.DEMO_MODE = "true";

  try {
    for (const request of [
      { method: "POST", path: "/api/coaching/clients" },
      { method: "PATCH", path: "/api/coaching/sessions/id/share" },
      { method: "DELETE", path: "/api/coaching/sessions/id" },
      { method: "POST", path: "/api/ai/response" },
      { method: "POST", path: "/api/coaching/session-memory/transcribe" },
      { method: "PUT", path: "/api/auth/password-update" },
    ]) {
      const result = run(request);
      assert.equal(result.nextCalled, false, `${request.method} ${request.path}`);
      assert.equal(result.res.statusCode, 403, `${request.method} ${request.path}`);
      assert.equal(result.res.body.error, "demo_read_only", `${request.method} ${request.path}`);
    }
  } finally {
    process.env.DEMO_MODE = previous;
  }
});

test("writes remain available outside demo mode", () => {
  const previous = process.env.DEMO_MODE;
  process.env.DEMO_MODE = "false";

  try {
    assert.equal(run({ method: "POST", path: "/api/coaching/clients" }).nextCalled, true);
  } finally {
    process.env.DEMO_MODE = previous;
  }
});
