const assert = require("node:assert/strict");
const test = require("node:test");
const {
  authorizeCoachingRoute,
  clientAccessWhere,
  isAdministratorUser,
  isClientUser,
  isStaffUser,
  requireStaff,
} = require("../src/security/coachingAuthorization");

function user(role) {
  return { id: `${role}-id`, app_role: { name: role } };
}

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

test("role helpers classify workspace roles", () => {
  assert.equal(isAdministratorUser(user("Administrator")), true);
  assert.equal(isAdministratorUser(user("Workspace Owner")), true);
  assert.equal(isAdministratorUser(user("Coach")), false);
  assert.equal(isStaffUser(user("Coach")), true);
  assert.equal(isStaffUser(user("Assistant")), true);
  assert.equal(isClientUser(user("Client")), true);
});

test("client scope follows the deployment role policy", () => {
  assert.deepEqual(clientAccessWhere(user("Administrator")), {});
  assert.deepEqual(clientAccessWhere(user("Workspace Owner")), {});
  assert.deepEqual(clientAccessWhere(user("Coach")), { ownerId: "Coach-id" });
  assert.deepEqual(clientAccessWhere(user("Assistant")), { ownerId: "Assistant-id" });
  assert.deepEqual(clientAccessWhere(user("Client")), { id: null });
});

test("client is rejected from coach-only endpoints", () => {
  const res = response();
  let nextCalled = false;

  requireStaff({ currentUser: user("Client") }, res, () => {
    nextCalled = true;
  });

  assert.equal(nextCalled, false);
  assert.equal(res.statusCode, 403);
  assert.deepEqual(res.body, { error: "coach_only" });
});

test("staff is allowed through coach-only endpoints", () => {
  for (const role of ["Administrator", "Workspace Owner", "Coach", "Assistant"]) {
    const res = response();
    let nextCalled = false;

    requireStaff({ currentUser: user(role) }, res, () => {
      nextCalled = true;
    });

    assert.equal(nextCalled, true, role);
    assert.equal(res.statusCode, null, role);
  }
});

test("client can use only the client-portal coaching namespace", () => {
  for (const path of ["/client-portal/me", "/client-portal/client-id", "/client-portal/action-items/item-id"]) {
    const res = response();
    let nextCalled = false;

    authorizeCoachingRoute({ path, currentUser: user("Client") }, res, () => {
      nextCalled = true;
    });

    assert.equal(nextCalled, true, path);
  }

  for (const path of ["/clients", "/intake-leads", "/session-memory", "/sessions/session-id/audio"]) {
    const res = response();
    let nextCalled = false;

    authorizeCoachingRoute({ path, currentUser: user("Client") }, res, () => {
      nextCalled = true;
    });

    assert.equal(nextCalled, false, path);
    assert.equal(res.statusCode, 403, path);
  }
});
