import { describe, expect, it } from "vitest";
import { can, permissionsFor } from "@/lib/auth/permissions";

/** Role matrix expectations from SPEC 8 and SPEC 40. */
describe("role-based authorization", () => {
  it("viewer can read but cannot edit anything", () => {
    expect(can("VIEWER", "students.view")).toBe(true);
    expect(can("VIEWER", "curriculum.view")).toBe(true);
    expect(can("VIEWER", "reports.view")).toBe(true);
    expect(can("VIEWER", "students.edit")).toBe(false);
    expect(can("VIEWER", "students.create")).toBe(false);
    expect(can("VIEWER", "assessment.edit")).toBe(false);
    expect(can("VIEWER", "reports.export")).toBe(false);
  });

  it("encoder can encode assessments but cannot modify curriculum structure", () => {
    expect(can("ENCODER", "assessment.edit")).toBe(true);
    expect(can("ENCODER", "students.create")).toBe(true);
    expect(can("ENCODER", "students.import")).toBe(true);
    expect(can("ENCODER", "curriculum.edit_draft")).toBe(false);
    expect(can("ENCODER", "curriculum.edit_published")).toBe(false);
    expect(can("ENCODER", "curriculum.publish")).toBe(false);
    expect(can("ENCODER", "curriculum.import")).toBe(false);
    expect(can("ENCODER", "rules.manage")).toBe(false);
    expect(can("ENCODER", "users.manage")).toBe(false);
    expect(can("ENCODER", "settings.manage")).toBe(false);
    expect(can("ENCODER", "audit.view")).toBe(false);
    expect(can("ENCODER", "students.import.update_existing")).toBe(false);
  });

  it("dean admin can override curriculum assignment and publish", () => {
    expect(can("DEAN_ADMIN", "curriculum.override_assignment")).toBe(true);
    expect(can("DEAN_ADMIN", "curriculum.publish")).toBe(true);
    expect(can("DEAN_ADMIN", "curriculum.import")).toBe(true);
    expect(can("DEAN_ADMIN", "rules.manage")).toBe(true);
    expect(can("DEAN_ADMIN", "audit.view")).toBe(true);
    expect(can("DEAN_ADMIN", "assessment.approve_equivalency")).toBe(true);
  });

  it("only SUPER_ADMIN may edit a published curriculum or manage users", () => {
    expect(can("SUPER_ADMIN", "curriculum.edit_published")).toBe(true);
    expect(can("DEAN_ADMIN", "curriculum.edit_published")).toBe(false);
    expect(can("SUPER_ADMIN", "users.manage")).toBe(true);
    expect(can("DEAN_ADMIN", "users.manage")).toBe(false);
    expect(can("SUPER_ADMIN", "settings.manage")).toBe(true);
    expect(can("DEAN_ADMIN", "settings.manage")).toBe(false);
  });

  it("permissions are strictly cumulative up the role hierarchy", () => {
    const viewer = new Set(permissionsFor("VIEWER"));
    const encoder = new Set(permissionsFor("ENCODER"));
    const dean = new Set(permissionsFor("DEAN_ADMIN"));
    const superAdmin = new Set(permissionsFor("SUPER_ADMIN"));
    for (const p of viewer) expect(encoder.has(p)).toBe(true);
    for (const p of encoder) expect(dean.has(p)).toBe(true);
    for (const p of dean) expect(superAdmin.has(p)).toBe(true);
  });

  it("denies everything for a missing role", () => {
    expect(can(null, "students.view")).toBe(false);
    expect(can(undefined, "students.view")).toBe(false);
  });
});
