import { computeUserScore } from './computeUserScore.js';

describe('computeUserScore', () => {
  const userSubmissionStatistics = [
    { itemTypeId: 'abc', numSubmissions: 92 },
    { itemTypeId: 'def', numSubmissions: 8 },
  ];

  const userActionStatistics = [
    // This action, policy pair was applied twice by user rules,
    // hence no item submission ids.
    {
      actionId: '1',
      policyId: '1',
      count: 2,
      itemSubmissionIds: [],
    },
  ];

  test('should count actions triggered by user rules', async () => {
    const sut = computeUserScore.bind(
      null,
      userSubmissionStatistics,
      userActionStatistics,
    );

    // should have two actions, with an effective 4 penalty points, out of 100
    // submissions, which is a 4.
    expect(
      await sut([{ policyId: '1', actionId: '1', penalties: [1, 3] }]),
    ).toBe(4);

    // ditto, but now 6 penalty points, which is a 3.
    expect(
      await sut([{ policyId: '1', actionId: '1', penalties: [2, 4] }]),
    ).toBe(3);
  });

  test('should apply only the most-severe penalty per item submission', async () => {
    const sut = computeUserScore.bind(null, userSubmissionStatistics, [
      { actionId: '1', policyId: '1', count: 1, itemSubmissionIds: ['a'] },
      { actionId: '2', policyId: '1', count: 1, itemSubmissionIds: ['a'] },
    ]);

    // should use penalty 4 for submission `a`, because that's the highest
    // first-strike penalty among the (action, policy) pairs that `a` matched.
    expect(
      await sut([
        { actionId: '1', policyId: '1', penalties: [2, 12] },
        { actionId: '2', policyId: '1', penalties: [4] },
      ]),
    ).toBe(4);
  });

  test('should return expected results', async () => {
    const sut = computeUserScore.bind(
      null,
      [
        { itemTypeId: 'abc', numSubmissions: 92 },
        { itemTypeId: 'def', numSubmissions: 8 },
      ],
      [
        {
          actionId: '1',
          policyId: '1',
          count: 2,
          itemSubmissionIds: ['a', 'b'],
        },
        { actionId: '2', policyId: '1', count: 1, itemSubmissionIds: ['c'] },
        { actionId: '1', policyId: '2', count: 1, itemSubmissionIds: ['d'] },
        {
          actionId: '2',
          policyId: '2',
          count: 6,
          itemSubmissionIds: ['e', 'f', 'g', 'h', 'i', 'j'],
        },
        // doesn't blow up on null policy id. and the penalty from (action,
        // policy) = (2, 2) above should apply to these repeat submission ids.
        {
          actionId: '2',
          policyId: null,
          count: 2,
          itemSubmissionIds: ['i', 'j'],
        },
      ],
    );

    // If no penalties are defined, the user should get a score of 5.
    expect(await sut([])).toBe(5);

    // if the penalties are all 1 (which should apply to all subsequent
    // "strikes"), then we have 10 violations out of 100 submissions, which
    // should be a 3.
    expect(
      await sut([
        { actionId: '1', policyId: '1', penalties: [1] },
        { actionId: '1', policyId: '2', penalties: [1] },
        { actionId: '2', policyId: '1', penalties: [1] },
        { actionId: '2', policyId: '2', penalties: [1] },
      ]),
    ).toBe(3);

    // If one penalty is 3, then we have 13 'effective' violations out of 100
    // submissions, which would be a 2.
    expect(
      await sut([
        { actionId: '1', policyId: '1', penalties: [1] },
        { actionId: '1', policyId: '2', penalties: [1] },
        { actionId: '2', policyId: '1', penalties: [3] },
        { actionId: '2', policyId: '2', penalties: [1] },
      ]),
    ).toBe(2);

    // One penalty at 3 for an one (action, penalty) pair that occurred twice,
    // plus one penatly at 9, means we have 28 effective violations out of 100,
    // which should be a 2.
    expect(
      await sut([
        { actionId: '1', policyId: '1', penalties: [3] },
        { actionId: '1', policyId: '2', penalties: [1] },
        { actionId: '2', policyId: '1', penalties: [9] },
        { actionId: '2', policyId: '2', penalties: [1] },
      ]),
    ).toBe(2);

    // it should support different penalties for the first, second, ..., nth
    // violation. (action 2, policy 2) has six occurrences, so this should lead
    // to 1 + 3 + 9 + 27 + 27 + 27 = 94 effective violations out of 100.
    expect(
      await sut([{ actionId: '2', policyId: '2', penalties: [1, 3, 9, 27] }]),
    ).toBe(1);
  });
});
