const { ObjectId } = require('bson');

const ROLES = require('../constant/core/roles.constant');
const Family = require('../model/chemical/family');
const Helper = require('./permission.helper');

describe('Permission Helper', () => {
  const hannah = {
    userId: 'VUN8MDN8aGFwZXJlekB1Y2RhdmlzLmVkdQ',
    firstName: 'Hannah',
    lastName: 'Perez',
    tenantCode: 'UC',
    campusCode: '03',
    email: 'haperez@ucdavis.edu',
    roles: [
      { role: ROLES.RESPONSIBLE_PERSON, campusCode: '03' },
      { role: ROLES.CHEMICAL_INFORMATICS, campusCode: null },
      { role: ROLES.CONTROL_AREA_ADMIN, campusCode: '03' },
    ],
    groups: [
      {
        id: 'dee70836-ab40-4437-b055-2cfeaac666f1',
        name: 'Team Purple',
        owner: { userId: 'VUN8MDN8aGFwZXJlekB1Y2RhdmlzLmVkdQ', campusCode: '03' }, // Hannah
        roles: [ROLES.RESPONSIBLE_PERSON],
        colleagues: [{ id: 'a21307f6-c584-46af-aa30-bffa956f6bff' }],
      },
      {
        id: 'c9030912-0516-4963-abbb-b1276a418932',
        name: 'test group',
        owner: { userId: 'VUN8MDN8Y2NhcmNhbW9AdWNkYXZpcy5lZHU', campusCode: '03' }, // Carcamo
        roles: [ROLES.DELEGATE, ROLES.AUTHORIZED_USER],
        colleagues: [],
      },
      {
        id: '6e080815-10ea-487e-9c44-44356508fefc',
        name: 'IT Serv Developers',
        owner: { userId: 'VUN8MDN8cHJhZGVlcGhAdWNkYXZpcy5lZHU', campusCode: '03' }, // Pradeep
        roles: [ROLES.AUTHORIZED_USER, ROLES.LAB_MANAGER],
        colleagues: [],
      },
      {
        id: '18bcf5f2-efb5-4d23-8ff5-5969f0b538f4',
        name: 'Shaw Lab',
        owner: { userId: 'VUN8MDN8anRzaGF3QHVjZGF2aXMuZWR1', campusCode: '03' }, // Jared Shaw
        roles: [ROLES.DELEGATE, ROLES.AUTHORIZED_USER],
        colleagues: [],
      },
      {
        id: 'a21307f6-c584-46af-aa30-bffa956f6bff',
        name: 'Demo Lab',
        owner: {
          userId: 'VUN8MDN8aGFwZXJlekB1Y2RhdmlzLmVkdQ',
          firstName: 'Hannah',
          lastName: 'Perez',
          tenantCode: null,
          campusCode: '03',
        },
        roles: [ROLES.RESPONSIBLE_PERSON, ROLES.LAB_MANAGER, ROLES.DELEGATE],
      },
    ],
  };

  const inventory = {
    _id: new ObjectId('5adf97597ed8203054035908'),
    tenantCode: 'UC',
    campusCode: '03',
    colleagues: [
      {
        _id: new ObjectId('5adf975a7ed820305403590c'),
        tenantCode: 'UC',
        campusCode: null,
        name: 'test group',
      },
      {
        _id: new ObjectId('5adf975a7ed8203054035914'),
        tenantCode: 'UC',
        campusCode: null,
        name: "Sydney's Group",
      },
      {
        _id: new ObjectId('5adf975a7ed8203054035912'),
        tenantCode: 'UC',
        campusCode: '03',
        name: "Christine's Test Group",
      },
      {
        _id: new ObjectId('5adf975a7ed8203054035912'),
        tenantCode: 'UC',
        campusCode: '03',
        name: "Christine's Test Group",
      },
      {
        _id: new ObjectId('5adf975a7ed820305403590e'),
        tenantCode: null,
        campusCode: '03',
        name: "Ben's Test Group 2",
      },
      {
        _id: new ObjectId('5adf975a7ed820305403590e'),
        tenantCode: null,
        campusCode: '03',
        name: "Ben's Test Group 2",
      },
    ],
    groups: [
      {
        id: 'a21307f6-c584-46af-aa30-bffa956f6bff',
        name: 'Demo Lab',
        owner: {
          userId: 'VUN8MDN8aGFwZXJlekB1Y2RhdmlzLmVkdQ',
          firstName: 'Hannah',
          lastName: 'Perez',
          tenantCode: null,
          campusCode: '03',
        },
      },
    ],
    name: 'Demo Lab',
    owner: {
      userId: 'VUN8MDN8aGFwZXJlekB1Y2RhdmlzLmVkdQ',
      firstName: 'Hannah',
      lastName: 'Perez',
      tenantCode: null,
      campusCode: '03',
    },
    tags: [
      'ACS Grade',
      'Enzymes',
      'Antibiotic',
      'Chem 118',
      'Chem2B',
      'acid',
      'pyrophoric',
      'chem',
      "John's Chemicals",
      'carbon',
      "Diana's Chemicals",
      'Test',
      'awesome',
      'TEst 2',
    ],
  };

  const admin = {
    userId: 'TEST_ID',
    firstName: 'Chem',
    lastName: 'Admin',
    tenantCode: 'UC',
    campusCode: '03',
    email: 'chem_admin@ucdavis.edu',
    roles: [
      { role: ROLES.CHEMICAL_ADMIN, campusCode: '03' },
      { role: 'Safety Coordinator', campusCode: '03', groupIds: ['a21307f6-c584-46af-aa30-bffa956f6bff'] },
    ],
    groups: [],
  };

  const readOnlyUser = {
    userId: 'sc',
    firstName: 'safety',
    lastName: 'co',
    tenantCode: 'UC',
    campusCode: '03',
    email: 'safety_co@ucdavis.edu',
    roles: [{ role: 'Safety Coordinator', campusCode: '03', groupIds: ['a21307f6-c584-46af-aa30-bffa956f6bff'] }],
    groups: [],
  };

  it('should have read access to container if member of group', () => {
    const container = {
      inventory,
      isPrivate: false,
    };

    expect(Helper.hasReadAccessToContainer(container, { ...hannah, inventories: [inventory] })).toBeTruthy();
  });

  it('should have read access to container if colleagues of group', () => {
    const container = {
      inventory,
      isPrivate: false,
    };

    expect(Helper.hasReadAccessToContainer(container, { ...hannah, inventories: [inventory] })).toBeTruthy();
  });

  it('should not have read access to container if colleagues of group and container is private', () => {
    const container = {
      inventory: {
        _id: hannah.groups[0].colleagues[0].id,
        campusCode: '03',
      },
      isPrivate: true,
    };

    expect(Helper.hasReadAccessToContainer(container, hannah)).toBeFalsy();
  });

  it('should have read access if chemical admin and container belongs to the same campus', () => {
    const container = {
      inventory,
      isPrivate: false,
    };
    expect(Helper.hasReadAccessToContainer(container, { ...hannah, inventories: [inventory] })).toBeTruthy();
  });

  it('should not have read access if chemical admin and container belongs to a different campus', () => {
    const container = {
      inventory,
      isPrivate: false,
    };

    const user = {
      roles: [{ role: ROLES.CHEMICAL_ADMIN, campusCode: '06' }],
      groups: [],
    };
    expect(Helper.hasWriteAccessToContainer(container, { ...user, inventories: [] })).toBeFalsy();
  });

  it('should have write access to container is member of Inventory', () => {
    const container = {
      inventory,
      isPrivate: false,
    };

    expect(Helper.hasWriteAccessToContainer(container, { ...hannah, inventories: [inventory] })).toBeTruthy();
  });

  it('should not have write access to container is colleagues of Inventory', () => {
    const container = {
      inventory: { ...inventory, _id: 'nope' },
      isPrivate: false,
    };

    expect(Helper.hasWriteAccessToContainer(container, { ...hannah, inventories: [inventory] })).toBeFalsy();
  });

  it('should be member of Inventory', () => {
    expect(Helper.isMemberOfInventory(inventory, hannah)).toBeTruthy();
  });

  it('should be colleage of Inventory', () => {
    const colleague = { ...inventory, colleagues: [...inventory.colleagues, { _id: inventory._id }] };
    expect(Helper.isMemberOrColleagueOfInventory(colleague, { ...hannah, inventories: [inventory] })).toBeTruthy();
  });

  it('should have manage access to Inventory if Delegate of Inventory', () => {
    const user = {
      ...hannah,
      groups: [
        {
          id: 'a21307f6-c584-46af-aa30-bffa956f6bff',
          isDelegate: true,
        },
      ],
    };
    expect(Helper.isGroupDelegate(inventory, user)).toBeTruthy();
  });

  it('should have manage access to Inventory if Lab Manager of Inventory', () => {
    expect(Helper.hasManageAccessToInventory(inventory, hannah)).toBeTruthy();
  });

  it('should have manage access to Inventory if group owner', () => {
    const user = {
      ...hannah,
      groups: [
        {
          id: 'a21307f6-c584-46af-aa30-bffa956f6bff',
          name: 'Demo Lab',
          owner: {
            userId: 'VUN8MDN8aGFwZXJlekB1Y2RhdmlzLmVkdQ',
          },
        },
      ],
    };
    expect(Helper.isGroupOwner(inventory, user)).toBeTruthy();
  });

  it('should not allow chem admin from a different campus', () => {
    const marsAdmin = {
      tenantCode: 'MMM',
      campusCode: 'MARS',
      roles: [{ role: ROLES.CHEMICAL_ADMIN, tenantCode: 'MMM', campusCode: 'MARS' }],
      groups: [],
    };
    expect(Helper.hasReadAccessToInventory(inventory, marsAdmin)).toBeFalsy();
  });

  it('should have write access to family if family is owned by inventory', () => {
    const family = new Family({
      scope: 'INVENTORY',
      group: hannah.groups[0],
    });

    expect(Helper.hasWriteAccessToFamily(family, hannah)).toBeTruthy();
  });

  it('should not have write access to family if family is not novel', () => {
    const family = new Family();
    expect(Helper.hasWriteAccessToFamily(family, { ...hannah, roles: [] })).toEqual(false);
  });

  it('should have write access to family if Chem Info', () => {
    const family = new Family();
    const chemInfo = {
      userId: 'CHEMINFO',
      firstName: 'Chem',
      lastName: 'Info',
      campusCode: '03',
      email: 'chem_info@ucdavis.edu',
      roles: [{ role: ROLES.CHEMICAL_INFORMATICS, campusCode: null }],
      groups: [],
    };
    expect(Helper.hasWriteAccessToFamily(family, chemInfo)).toEqual(true);
  });

  it('should return true if Chem Admin for person campus', () => {
    expect(Helper.isChemAdmin(admin.campusCode, admin)).toBeTruthy();
  });

  it('should return false if not Chem Admin for person campus', () => {
    expect(Helper.isChemAdmin(hannah.campusCode, hannah)).toBeFalsy();
  });

  it('should return true if has read only role to inventory', () => {
    expect(Helper.hasRoleWithReadAccessToInventory(inventory, readOnlyUser)).toBeTruthy();
  });

  it('should return false if does not have read only role to inventory', () => {
    expect(Helper.hasRoleWithReadAccessToInventory(inventory, admin)).toBeFalsy();
  });

  it('should return true if has Read access to inventory', () => {
    expect(Helper.hasRoleWithReadAccessToInventory(inventory, readOnlyUser)).toBeTruthy();
  });

  it('should return false if a chem admin for a different campus than inventory', () => {
    const marsAdmin = {
      tenantCode: 'MMM',
      campusCode: 'MARS',
      roles: [{ role: ROLES.CHEMICAL_ADMIN, tenantCode: 'MMM', campusCode: 'MARS' }],
      groups: [],
    };
    expect(Helper.hasRoleWithReadAccessToInventory(inventory, marsAdmin)).toBeFalsy();
  });

  it('should return true if has role', () => {
    expect(Helper.hasRole(hannah, ROLES.RESPONSIBLE_PERSON)).toBeTruthy();
  });

  it('should return false if does not have role', () => {
    expect(Helper.hasRole(hannah, ROLES.PROCEDURES_ADMIN)).toBeFalsy();
  });

  it('should have read access to library if chem admin', () => {
    const user = {
      userId: 'userid',
      roles: [{ role: ROLES.CHEMICAL_ADMIN, tenantCode: null, campusCode: '03', types: null }],
      groups: [],
      campusCode: '03',
    };
    expect(Helper.hasReadAccessToLibrary(user)).toBeTruthy();
  });

  it('should have read access to library if control area admin', () => {
    const user = {
      userId: 'userid',
      roles: [{ role: ROLES.CONTROL_AREA_ADMIN, tenantCode: null, campusCode: '03', types: null }],
      groups: [],
      campusCode: '03',
    };
    expect(Helper.hasReadAccessToLibrary(user)).toBeTruthy();
  });

  it('should have read access to library', () => {
    expect(Helper.hasReadAccessToLibrary(hannah)).toBeTruthy();
  });

  it('should have write access to library', () => {
    expect(Helper.hasWriteAccessToLibrary(hannah)).toBeTruthy();
  });

  it('should have read access to control area', () => {
    const controlArea = {
      name: 'control area 1',
      campusCode: '03',
      tenantCode: 'UC',
    };
    expect(Helper.hasReadAccessToControlArea(hannah, controlArea)).toBeTruthy();
  });

  it('should have read access to control area as a Chem Admin', () => {
    const controlArea = {
      name: 'control area 1',
      campusCode: '03',
      tenantCode: 'UC',
    };
    expect(Helper.hasReadAccessToControlArea(admin, controlArea)).toBeTruthy();
  });

  it('should have write access to control area', () => {
    const controlArea = {
      name: 'control area 1',
      campusCode: '03',
      tenantCode: 'UC',
    };
    expect(Helper.hasWriteAccessToControlArea(hannah, controlArea)).toBeTruthy();
  });
});
