/**
 * @license
 * Copyright 2022 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

import {
  createAccountWithIdNameAndEmail,
  createChange,
  createRevisions,
} from '../../test/test-data-generators';
import {
  ChangeInfo,
  NumericChangeId,
  ChangeStatus,
  HttpMethod,
  SubmitRequirementStatus,
  AccountInfo,
  ReviewerState,
  AccountId,
} from '../../api/rest-api';
import {BulkActionsModel, LoadingState} from './bulk-actions-model';
import {getAppContext} from '../../services/app-context';
import '../../test/common-test-setup-karma';
import {stubRestApi, waitUntilObserved} from '../../test/test-utils';
import {mockPromise} from '../../test/test-utils';
import {SinonStubbedMember} from 'sinon';
import {RestApiService} from '../../services/gr-rest-api/gr-rest-api';
import {ReviewInput} from '../../types/common';

suite('bulk actions model test', () => {
  let bulkActionsModel: BulkActionsModel;
  setup(() => {
    bulkActionsModel = new BulkActionsModel(getAppContext().restApiService);
  });

  test('does not request detailed changes when no changes are synced', () => {
    const detailedActionsStub = stubRestApi('getDetailedChangesWithActions');

    bulkActionsModel.sync([]);

    assert.isTrue(detailedActionsStub.notCalled);
  });

  test('add changes before sync', () => {
    const c1 = createChange();
    c1._number = 1 as NumericChangeId;
    const c2 = createChange();
    c2._number = 2 as NumericChangeId;

    assert.isEmpty(bulkActionsModel.getState().selectedChangeNums);

    assert.throws(() => bulkActionsModel.addSelectedChangeNum(c1._number));
    assert.isEmpty(bulkActionsModel.getState().selectedChangeNums);

    bulkActionsModel.sync([c1, c2]);

    bulkActionsModel.addSelectedChangeNum(c2._number);
    assert.sameMembers(bulkActionsModel.getState().selectedChangeNums, [
      c2._number,
    ]);

    bulkActionsModel.removeSelectedChangeNum(c2._number);
    assert.isEmpty(bulkActionsModel.getState().selectedChangeNums);
  });

  test('add and remove selected changes', () => {
    const c1 = createChange();
    c1._number = 1 as NumericChangeId;
    const c2 = createChange();
    c2._number = 2 as NumericChangeId;
    bulkActionsModel.sync([c1, c2]);

    assert.isEmpty(bulkActionsModel.getState().selectedChangeNums);

    bulkActionsModel.addSelectedChangeNum(c1._number);
    assert.sameMembers(bulkActionsModel.getState().selectedChangeNums, [
      c1._number,
    ]);

    bulkActionsModel.addSelectedChangeNum(c2._number);
    assert.sameMembers(bulkActionsModel.getState().selectedChangeNums, [
      c1._number,
      c2._number,
    ]);

    bulkActionsModel.removeSelectedChangeNum(c1._number);
    assert.sameMembers(bulkActionsModel.getState().selectedChangeNums, [
      c2._number,
    ]);

    bulkActionsModel.removeSelectedChangeNum(c2._number);
    assert.isEmpty(bulkActionsModel.getState().selectedChangeNums);
  });

  test('clears selected change numbers', async () => {
    const c1 = createChange();
    c1._number = 1 as NumericChangeId;
    const c2 = createChange();
    c2._number = 2 as NumericChangeId;
    bulkActionsModel.sync([c1, c2]);
    bulkActionsModel.addSelectedChangeNum(c1._number);
    bulkActionsModel.addSelectedChangeNum(c2._number);
    let selectedChangeNums = await waitUntilObserved(
      bulkActionsModel!.selectedChangeNums$,
      s => s.length === 2
    );
    let totalChangeCount = await waitUntilObserved(
      bulkActionsModel.totalChangeCount$,
      totalChangeCount => totalChangeCount === 2
    );
    assert.sameMembers(selectedChangeNums, [c1._number, c2._number]);
    assert.equal(totalChangeCount, 2);

    bulkActionsModel.clearSelectedChangeNums();
    selectedChangeNums = await waitUntilObserved(
      bulkActionsModel!.selectedChangeNums$,
      s => s.length === 0
    );
    totalChangeCount = await waitUntilObserved(
      bulkActionsModel.totalChangeCount$,
      totalChangeCount => totalChangeCount === 2
    );

    assert.isEmpty(selectedChangeNums);
    assert.equal(totalChangeCount, 2);
  });

  test('selects all changes', async () => {
    const c1 = createChange();
    c1._number = 1 as NumericChangeId;
    const c2 = createChange();
    c2._number = 2 as NumericChangeId;
    bulkActionsModel.sync([c1, c2]);
    let selectedChangeNums = await waitUntilObserved(
      bulkActionsModel!.selectedChangeNums$,
      s => s.length === 0
    );
    let totalChangeCount = await waitUntilObserved(
      bulkActionsModel.totalChangeCount$,
      totalChangeCount => totalChangeCount === 2
    );
    assert.isEmpty(selectedChangeNums);
    assert.equal(totalChangeCount, 2);

    bulkActionsModel.selectAll();
    selectedChangeNums = await waitUntilObserved(
      bulkActionsModel!.selectedChangeNums$,
      s => s.length === 2
    );
    totalChangeCount = await waitUntilObserved(
      bulkActionsModel.totalChangeCount$,
      totalChangeCount => totalChangeCount === 2
    );

    assert.sameMembers(selectedChangeNums, [c1._number, c2._number]);
    assert.equal(totalChangeCount, 2);
  });

  suite('abandon changes', () => {
    let detailedActionsStub: SinonStubbedMember<
      RestApiService['getDetailedChangesWithActions']
    >;
    setup(async () => {
      detailedActionsStub = stubRestApi('getDetailedChangesWithActions');
      const c1 = createChange();
      c1._number = 1 as NumericChangeId;
      const c2 = createChange();
      c2._number = 2 as NumericChangeId;

      detailedActionsStub.returns(
        Promise.resolve([
          {...c1, actions: {abandon: {method: HttpMethod.POST}}},
          {...c2, status: ChangeStatus.ABANDONED},
        ])
      );

      bulkActionsModel.sync([c1, c2]);

      bulkActionsModel.addSelectedChangeNum(c1._number);
      bulkActionsModel.addSelectedChangeNum(c2._number);
    });

    test('already abandoned change does not call executeChangeAction', () => {
      const actionStub = stubRestApi('executeChangeAction');
      bulkActionsModel.abandonChanges();
      assert.equal(actionStub.callCount, 1);
      assert.deepEqual(actionStub.lastCall.args.slice(0, 5), [
        1 as NumericChangeId,
        HttpMethod.POST,
        '/abandon',
        undefined,
        {message: ''},
      ]);
    });
  });

  suite('add reviewers', () => {
    const accounts: AccountInfo[] = [
      createAccountWithIdNameAndEmail(0),
      createAccountWithIdNameAndEmail(1),
    ];
    const changes: ChangeInfo[] = [
      {
        ...createChange(),
        _number: 1 as NumericChangeId,
        subject: 'Subject 1',
        reviewers: {
          REVIEWER: [accounts[0]],
          CC: [accounts[1]],
        },
      },
      {
        ...createChange(),
        _number: 2 as NumericChangeId,
        subject: 'Subject 2',
      },
    ];
    let saveChangeReviewStub: sinon.SinonStub;

    setup(async () => {
      saveChangeReviewStub = stubRestApi('saveChangeReview').resolves(
        new Response()
      );
      stubRestApi('getDetailedChangesWithActions').resolves([
        {...changes[0], actions: {abandon: {method: HttpMethod.POST}}},
        {...changes[1], status: ChangeStatus.ABANDONED},
      ]);
      bulkActionsModel.sync(changes);
      bulkActionsModel.addSelectedChangeNum(changes[0]._number);
      bulkActionsModel.addSelectedChangeNum(changes[1]._number);
    });

    test('adds reviewers/cc only to changes that need it', async () => {
      bulkActionsModel.addReviewers(
        new Map([
          [ReviewerState.REVIEWER, [accounts[0]]],
          [ReviewerState.CC, [accounts[1]]],
        ]),
        '<GERRIT_ACCOUNT_12345> replied on the change'
      );

      // changes[0] is not updated since it already has the reviewer & CC
      assert.isTrue(saveChangeReviewStub.calledOnce);
      assert.sameDeepOrderedMembers(saveChangeReviewStub.firstCall.args, [
        changes[1]._number,
        'current',
        {
          reviewers: [
            {reviewer: accounts[0]._account_id, state: ReviewerState.REVIEWER},
            {reviewer: accounts[1]._account_id, state: ReviewerState.CC},
          ],
          ignore_automatic_attention_set_rules: true,
          add_to_attention_set: [
            {
              reason: '<GERRIT_ACCOUNT_12345> replied on the change',
              user: accounts[0]._account_id,
            },
          ],
        },
      ]);
    });
  });

  suite('voteChanges', () => {
    let detailedActionsStub: SinonStubbedMember<
      RestApiService['getDetailedChangesWithActions']
    >;
    setup(async () => {
      const c1 = {...createChange(), revisions: createRevisions(10)};
      c1._number = 1 as NumericChangeId;
      const c2 = {...createChange(), revisions: createRevisions(4)};
      c2._number = 2 as NumericChangeId;

      detailedActionsStub = stubRestApi('getDetailedChangesWithActions');
      detailedActionsStub.returns(
        Promise.resolve([
          {...c1, actions: {abandon: {method: HttpMethod.POST}}},
          {...c2, status: ChangeStatus.ABANDONED},
        ])
      );

      await bulkActionsModel.sync([c1, c2]);

      bulkActionsModel.addSelectedChangeNum(c1._number);
      bulkActionsModel.addSelectedChangeNum(c2._number);
    });

    test('vote changes', () => {
      const reviewStub = stubRestApi('saveChangeReview');
      const reviewInput: ReviewInput = {
        labels: {
          a: 1,
        },
      };
      bulkActionsModel.voteChanges(reviewInput);
      assert.equal(reviewStub.callCount, 2);
      assert.deepEqual(reviewStub.firstCall.args.slice(0, 3), [
        1 as NumericChangeId,
        'current',
        {
          labels: {
            a: 1,
          },
        },
      ]);

      assert.deepEqual(reviewStub.secondCall.args.slice(0, 3), [
        2 as NumericChangeId,
        'current',
        {
          labels: {
            a: 1,
          },
        },
      ]);
    });
  });

  test('stale changes are removed from the model', async () => {
    const c1 = createChange();
    c1._number = 1 as NumericChangeId;
    const c2 = createChange();
    c2._number = 2 as NumericChangeId;
    bulkActionsModel.sync([c1, c2]);

    bulkActionsModel.addSelectedChangeNum(c1._number);
    bulkActionsModel.addSelectedChangeNum(c2._number);

    let selectedChangeNums = await waitUntilObserved(
      bulkActionsModel!.selectedChangeNums$,
      s => s.length === 2
    );
    let totalChangeCount = await waitUntilObserved(
      bulkActionsModel.totalChangeCount$,
      totalChangeCount => totalChangeCount === 2
    );

    assert.sameMembers(selectedChangeNums, [c1._number, c2._number]);
    assert.equal(totalChangeCount, 2);

    bulkActionsModel.sync([c1]);
    selectedChangeNums = await waitUntilObserved(
      bulkActionsModel!.selectedChangeNums$,
      s => s.length === 1
    );
    totalChangeCount = await waitUntilObserved(
      bulkActionsModel.totalChangeCount$,
      totalChangeCount => totalChangeCount === 1
    );

    assert.sameMembers(selectedChangeNums, [c1._number]);
    assert.equal(totalChangeCount, 1);
  });

  test('sync fetches new changes', async () => {
    const c1 = createChange();
    c1._number = 1 as NumericChangeId;
    const c2 = createChange();
    c2._number = 2 as NumericChangeId;

    assert.equal(
      bulkActionsModel.getState().loadingState,
      LoadingState.NOT_SYNCED
    );

    bulkActionsModel.sync([c1, c2]);
    await waitUntilObserved(
      bulkActionsModel.loadingState$,
      s => s === LoadingState.LOADING
    );

    await waitUntilObserved(
      bulkActionsModel.loadingState$,
      s => s === LoadingState.LOADED
    );
    const model = bulkActionsModel.getState();

    assert.strictEqual(
      model.allChanges.get(1 as NumericChangeId)?.subject,
      'Subject 1'
    );
    assert.strictEqual(
      model.allChanges.get(2 as NumericChangeId)?.subject,
      'Subject 2'
    );
  });

  test('sync retains keys from original change including reviewers', async () => {
    const c1: ChangeInfo = {
      ...createChange(),
      _number: 1 as NumericChangeId,
      submit_requirements: [
        {
          name: 'a',
          status: SubmitRequirementStatus.FORCED,
          submittability_expression_result: {
            expression: 'b',
          },
        },
      ],
      reviewers: {
        REVIEWER: [{_account_id: 1 as AccountId, display_name: 'MyName'}],
      },
    };

    stubRestApi('getDetailedChangesWithActions').callsFake(() => {
      const change: ChangeInfo = {
        ...createChange(),
        _number: 1 as NumericChangeId,
        actions: {abandon: {}},
        // detailed data will be missing names
        reviewers: {REVIEWER: [createAccountWithIdNameAndEmail()]},
      };
      assert.isNotOk(change.submit_requirements);
      return Promise.resolve([change]);
    });

    bulkActionsModel.sync([c1]);

    await waitUntilObserved(
      bulkActionsModel.loadingState$,
      s => s === LoadingState.LOADED
    );

    const changeAfterSync = bulkActionsModel
      .getState()
      .allChanges.get(1 as NumericChangeId);
    assert.deepEqual(changeAfterSync!.submit_requirements, [
      {
        name: 'a',
        status: SubmitRequirementStatus.FORCED,
        submittability_expression_result: {
          expression: 'b',
        },
      },
    ]);
    assert.deepEqual(changeAfterSync!.actions, {abandon: {}});
    // original reviewers are kept, which includes more details than loaded ones
    assert.deepEqual(changeAfterSync!.reviewers, c1.reviewers);
  });

  test('sync ignores outdated fetch responses', async () => {
    const c1 = createChange();
    c1._number = 1 as NumericChangeId;
    const c2 = createChange();
    c2._number = 2 as NumericChangeId;

    const responsePromise1 = mockPromise<ChangeInfo[]>();
    let promise = responsePromise1;
    const getChangesStub = stubRestApi(
      'getDetailedChangesWithActions'
    ).callsFake(() => promise);
    bulkActionsModel.sync([c1, c2]);
    assert.strictEqual(getChangesStub.callCount, 1);
    await waitUntilObserved(
      bulkActionsModel.loadingState$,
      s => s === LoadingState.LOADING
    );
    const responsePromise2 = mockPromise<ChangeInfo[]>();

    promise = responsePromise2;
    bulkActionsModel.sync([c1, c2]);
    assert.strictEqual(getChangesStub.callCount, 2);

    responsePromise2.resolve([
      {...createChange(), _number: 1, subject: 'Subject 1'},
      {...createChange(), _number: 2, subject: 'Subject 2'},
    ] as ChangeInfo[]);

    await waitUntilObserved(
      bulkActionsModel.loadingState$,
      s => s === LoadingState.LOADED
    );
    const model = bulkActionsModel.getState();
    assert.strictEqual(
      model.allChanges.get(1 as NumericChangeId)?.subject,
      'Subject 1'
    );
    assert.strictEqual(
      model.allChanges.get(2 as NumericChangeId)?.subject,
      'Subject 2'
    );

    // Resolve the old promise.
    responsePromise1.resolve([
      {...createChange(), _number: 1, subject: 'Subject 1-old'},
      {...createChange(), _number: 2, subject: 'Subject 2-old'},
    ] as ChangeInfo[]);
    await flush();
    const model2 = bulkActionsModel.getState();

    // No change should happen.
    assert.strictEqual(
      model2.allChanges.get(1 as NumericChangeId)?.subject,
      'Subject 1'
    );
    assert.strictEqual(
      model2.allChanges.get(2 as NumericChangeId)?.subject,
      'Subject 2'
    );
  });
});
