/**
 * @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../../../test/common-test-setup';
import './gr-account-list';
import {GrAccountList} from './gr-account-list';
import {
  AccountId,
  AccountInfo,
  EmailAddress,
  GroupBaseInfo,
  GroupId,
  GroupName,
  SuggestedReviewerInfo,
  Suggestion,
} from '../../../types/common';
import {
  pressKey,
  queryAll,
  queryAndAssert,
  waitUntil,
} from '../../../test/test-utils';
import {ReviewerSuggestionsProvider} from '../../../scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider';
import {
  AutocompleteSuggestion,
  GrAutocomplete,
} from '../gr-autocomplete/gr-autocomplete';
import {GrAccountEntry} from '../gr-account-entry/gr-account-entry';
import {createChange} from '../../../test/test-data-generators';
import {ReviewerState} from '../../../api/rest-api';
import {fixture, html, assert} from '@open-wc/testing';
import {EventType} from '../../../types/events';
import {AccountInfoInput, RawAccountInput} from '../../../utils/account-util';

class MockSuggestionsProvider implements ReviewerSuggestionsProvider {
  init() {}

  getSuggestions(_: string): Promise<Suggestion[]> {
    return Promise.resolve([]);
  }

  makeSuggestionItem(
    _: Suggestion
  ): AutocompleteSuggestion<SuggestedReviewerInfo> {
    return {
      name: 'test',
      value: {
        account: {
          _account_id: 1 as AccountId,
        } as AccountInfo,
        count: 1,
      },
    };
  }
}

suite('gr-account-list tests', () => {
  let _nextAccountId = 0;
  const makeAccount: () => AccountInfo = function () {
    const accountId = ++_nextAccountId;
    return {
      _account_id: accountId as AccountId,
    };
  };
  const makeGroup: () => GroupBaseInfo = function () {
    const groupId = `group${++_nextAccountId}`;
    return {
      id: groupId as GroupId,
      name: 'abcd' as GroupName,
    };
  };

  let existingAccount1: AccountInfo;
  let existingAccount2: AccountInfo;

  let element: GrAccountList;
  let suggestionsProvider: MockSuggestionsProvider;

  function getChips() {
    return queryAll(element, 'gr-account-chip');
  }

  function handleAdd(value: RawAccountInput) {
    element.handleAdd(
      new CustomEvent<{value: string}>('add', {
        detail: {value: value as unknown as string},
      })
    );
  }

  setup(async () => {
    existingAccount1 = makeAccount();
    existingAccount2 = makeAccount();

    element = await fixture(html`<gr-account-list></gr-account-list>`);
    element.accounts = [existingAccount1, existingAccount2];
    element.reviewerState = ReviewerState.REVIEWER;
    element.change = {...createChange()};
    element.change.reviewers[ReviewerState.REVIEWER] = [...element.accounts];
    suggestionsProvider = new MockSuggestionsProvider();
    element.suggestionsProvider = suggestionsProvider;
    await element.updateComplete;
  });

  test('renders', () => {
    assert.shadowDom.equal(
      element,
      /* HTML */
      `<div class="list">
          <gr-account-chip removable="" tabindex="-1"> </gr-account-chip>
          <gr-account-chip removable="" tabindex="-1"> </gr-account-chip>
        </div>
        <gr-account-entry borderless="" id="entry"></gr-account-entry>
        <slot></slot>`
    );
  });

  test('account entry only appears when editable', async () => {
    element.readonly = false;
    await element.updateComplete;
    assert.isFalse(
      queryAndAssert<GrAccountEntry>(element, '#entry').hasAttribute('hidden')
    );
    element.readonly = true;
    await element.updateComplete;
    assert.isTrue(
      queryAndAssert<GrAccountEntry>(element, '#entry').hasAttribute('hidden')
    );
  });

  test('addition and removal of account/group chips', async () => {
    await element.updateComplete;
    sinon.stub(element, 'computeRemovable').returns(true);
    // Existing accounts are listed.
    let chips = getChips();
    assert.equal(chips.length, 2);
    assert.isFalse(chips[0].classList.contains('newlyAdded'));
    assert.isFalse(chips[1].classList.contains('newlyAdded'));

    // New accounts are added to end with newlyAdded class.
    const newAccount = makeAccount();
    handleAdd({account: newAccount, count: 1});
    await element.updateComplete;
    chips = getChips();
    assert.equal(chips.length, 3);
    assert.isFalse(chips[0].classList.contains('newlyAdded'));
    assert.isFalse(chips[1].classList.contains('newlyAdded'));
    assert.isTrue(chips[2].classList.contains('newlyAdded'));

    // Removed accounts are taken out of the list.
    element.dispatchEvent(
      new CustomEvent('remove', {
        detail: {account: existingAccount1},
        composed: true,
        bubbles: true,
      })
    );
    await element.updateComplete;
    chips = getChips();
    assert.equal(chips.length, 2);
    assert.isFalse(chips[0].classList.contains('newlyAdded'));
    assert.isTrue(chips[1].classList.contains('newlyAdded'));

    // Invalid remove is ignored.
    element.dispatchEvent(
      new CustomEvent('remove', {
        detail: {account: existingAccount1},
        composed: true,
        bubbles: true,
      })
    );
    element.dispatchEvent(
      new CustomEvent('remove', {
        detail: {account: newAccount},
        composed: true,
        bubbles: true,
      })
    );
    await element.updateComplete;
    chips = getChips();
    assert.equal(chips.length, 1);
    assert.isFalse(chips[0].classList.contains('newlyAdded'));

    // New groups are added to end with newlyAdded and group classes.
    const newGroup = makeGroup();
    handleAdd({group: newGroup, confirm: false, count: 1});
    await element.updateComplete;
    chips = getChips();
    assert.equal(chips.length, 2);
    assert.isTrue(chips[1].classList.contains('group'));
    assert.isTrue(chips[1].classList.contains('newlyAdded'));

    // Removed groups are taken out of the list.
    element.dispatchEvent(
      new CustomEvent('remove', {
        detail: {account: newGroup},
        composed: true,
        bubbles: true,
      })
    );
    await element.updateComplete;
    chips = getChips();
    assert.equal(chips.length, 1);
    assert.isFalse(chips[0].classList.contains('newlyAdded'));
  });

  test('getSuggestions uses filter correctly', () => {
    const originalSuggestions: Suggestion[] = [
      {
        email: 'abc@example.com' as EmailAddress,
        text: 'abcd',
        _account_id: 3 as AccountId,
      } as AccountInfo,
      {
        email: 'qwe@example.com' as EmailAddress,
        text: 'qwer',
        _account_id: 1 as AccountId,
      } as AccountInfo,
      {
        email: 'xyz@example.com' as EmailAddress,
        text: 'aaaaa',
        _account_id: 25 as AccountId,
      } as AccountInfo,
    ];
    sinon
      .stub(suggestionsProvider, 'getSuggestions')
      .returns(Promise.resolve(originalSuggestions));
    sinon
      .stub(suggestionsProvider, 'makeSuggestionItem')
      .callsFake(suggestion => {
        return {
          name: ((suggestion as AccountInfo).email as string) ?? '',
          value: {
            account: suggestion as AccountInfo,
            count: 1,
          },
        };
      });

    return element
      .getSuggestions('')
      .then(suggestions => {
        // Default is no filtering.
        assert.equal(suggestions.length, 3);

        // Set up filter that only accepts suggestion1.
        const accountId = (originalSuggestions[0] as AccountInfo)._account_id;
        element.filter = function (suggestion) {
          return (suggestion as AccountInfo)._account_id === accountId;
        };

        return element.getSuggestions('');
      })
      .then(suggestions => {
        assert.deepEqual(suggestions, [
          {
            name: (originalSuggestions[0] as AccountInfo).email as string,
            value: {
              account: originalSuggestions[0] as AccountInfo,
              count: 1,
            },
          },
        ]);
      });
  });

  test('computeRemovable', async () => {
    const newAccount = makeAccount() as AccountInfoInput;
    element.readonly = false;
    element.removableValues = [];
    element.updateComplete;
    assert.isFalse(element.computeRemovable(existingAccount1));
    assert.isTrue(element.computeRemovable(newAccount));

    element.removableValues = [existingAccount1];
    element.updateComplete;
    assert.isTrue(element.computeRemovable(existingAccount1));
    assert.isTrue(element.computeRemovable(newAccount));
    assert.isFalse(element.computeRemovable(existingAccount2));

    element.readonly = true;
    element.updateComplete;
    assert.isFalse(element.computeRemovable(existingAccount1));
    assert.isFalse(element.computeRemovable(newAccount));
  });

  test('addAccountItem with invalid item', () => {
    const toastHandler = sinon.stub();
    element.allowAnyInput = false;
    element.addEventListener(EventType.SHOW_ALERT, toastHandler);
    const result = element.addAccountItem('test');
    assert.isFalse(result);
    assert.isTrue(toastHandler.called);
  });

  test('submitEntryText', async () => {
    element.allowAnyInput = true;
    await element.updateComplete;

    const getTextStub = sinon.stub(
      queryAndAssert<GrAccountEntry>(element, '#entry'),
      'getText'
    );
    getTextStub.onFirstCall().returns('');
    getTextStub.onSecondCall().returns('test');
    getTextStub.onThirdCall().returns('test@test');

    // When entry is empty, return true.
    const clearStub = sinon.stub(
      queryAndAssert<GrAccountEntry>(element, '#entry'),
      'clear'
    );
    assert.isTrue(element.submitEntryText());
    assert.isFalse(clearStub.called);

    // When entry is invalid, return false.
    assert.isFalse(element.submitEntryText());
    assert.isFalse(clearStub.called);

    // When entry is valid, return true and clear text.
    assert.isTrue(element.submitEntryText());
    assert.isTrue(clearStub.called);
    assert.equal(
      (element.additions()[0] as AccountInfo)?.email,
      'test@test' as EmailAddress
    );
  });

  test('additions returns sanitized new accounts and groups', () => {
    assert.equal(element.additions().length, 0);

    const newAccount = makeAccount();
    handleAdd({account: newAccount, count: 1});
    const newGroup = makeGroup();
    handleAdd({group: newGroup, confirm: false, count: 1});

    assert.deepEqual(element.additions(), [
      {
        _account_id: newAccount._account_id,
      },
      {
        id: newGroup.id,
        name: 'abcd' as GroupName,
      },
    ]);
  });

  test('large group confirmations', () => {
    assert.isNull(element.pendingConfirmation);
    assert.deepEqual(element.additions(), []);

    const group = makeGroup();
    const reviewer: RawAccountInput = {
      group,
      count: 10,
      confirm: true,
    };
    handleAdd(reviewer);

    assert.deepEqual(element.pendingConfirmation, reviewer);
    assert.deepEqual(element.additions(), []);

    element.confirmGroup(group);
    assert.isNull(element.pendingConfirmation);
    assert.deepEqual(element.additions(), [
      {
        id: group.id,
        name: 'abcd' as GroupName,
        confirmed: true,
      },
    ]);
  });

  test('removeAccount fails if account is not removable', () => {
    element.readonly = true;
    const acct = makeAccount();
    element.accounts = [acct];
    element.removeAccount(acct);
    assert.equal(element.accounts.length, 1);
  });

  test('enter text calls suggestions provider', async () => {
    const suggestions: Suggestion[] = [
      {
        email: 'abc@example.com' as EmailAddress,
        text: 'abcd',
      } as AccountInfo,
      {
        email: 'qwe@example.com' as EmailAddress,
        text: 'qwer',
      } as AccountInfo,
    ];
    const getSuggestionsStub = sinon
      .stub(suggestionsProvider, 'getSuggestions')
      .returns(Promise.resolve(suggestions));

    const makeSuggestionItemSpy = sinon.spy(
      suggestionsProvider,
      'makeSuggestionItem'
    );

    const input = queryAndAssert<GrAutocomplete>(
      queryAndAssert<GrAccountEntry>(element, '#entry'),
      '#input'
    );
    input.text = 'newTest';
    input.input!.focus();
    input.noDebounce = true;
    await element.updateComplete;
    assert.isTrue(getSuggestionsStub.calledOnce);
    assert.equal(getSuggestionsStub.lastCall.args[0], 'newTest');
    await waitUntil(() => makeSuggestionItemSpy.getCalls().length === 2);
  });

  suite('allowAnyInput', () => {
    setup(() => {
      element.allowAnyInput = true;
    });

    test('adds emails', () => {
      const accountLen = element.accounts.length;
      handleAdd('test@test');
      assert.equal(element.accounts.length, accountLen + 1);
      assert.equal(
        (element.accounts[accountLen] as AccountInfoInput).email,
        'test@test' as EmailAddress
      );
    });

    test('toasts on invalid email', () => {
      const toastHandler = sinon.stub();
      element.addEventListener(EventType.SHOW_ALERT, toastHandler);
      handleAdd('test');
      assert.isTrue(toastHandler.called);
    });
  });

  suite('keyboard interactions', () => {
    test('backspace at text input start removes last account', async () => {
      const input = queryAndAssert<GrAutocomplete>(
        queryAndAssert<GrAccountEntry>(element, '#entry'),
        '#input'
      );
      sinon.stub(input, 'updateSuggestions');
      sinon.stub(element, 'computeRemovable').returns(true);
      await element.updateComplete;
      // Next line is a workaround for Firefox not moving cursor
      // on input field update
      assert.equal(element.getOwnNativeInput(input.input!).selectionStart, 0);
      input.text = 'test';
      input.input!.focus();
      await element.updateComplete;
      assert.equal(element.accounts.length, 2);
      pressKey(element.getOwnNativeInput(input.input!), 'Backspace');
      await waitUntil(() => element.accounts.length === 2);
      input.text = '';
      await input.updateComplete;
      pressKey(element.getOwnNativeInput(input.input!), 'Backspace');
      await waitUntil(() => element.accounts.length === 1);
    });

    test('arrow key navigation', async () => {
      const input = queryAndAssert<GrAutocomplete>(
        queryAndAssert<GrAccountEntry>(element, '#entry'),
        '#input'
      );
      input.text = '';
      element.accounts = [makeAccount(), makeAccount()];
      await element.updateComplete;
      input.input!.focus();
      await element.updateComplete;
      const chips = element.accountChips;
      const chipsOneSpy = sinon.spy(chips[1], 'focus');
      pressKey(input.input!, 'ArrowLeft');
      assert.isTrue(chipsOneSpy.called);
      const chipsZeroSpy = sinon.spy(chips[0], 'focus');
      pressKey(chips[1], 'ArrowLeft');
      assert.isTrue(chipsZeroSpy.called);
      pressKey(chips[0], 'ArrowLeft');
      assert.isTrue(chipsZeroSpy.calledOnce);
      pressKey(chips[0], 'ArrowRight');
      assert.isTrue(chipsOneSpy.calledTwice);
    });

    test('delete', async () => {
      element.accounts = [makeAccount(), makeAccount()];
      await element.updateComplete;
      const focusSpy = sinon.spy(element.accountChips[1], 'focus');
      const removeSpy = sinon.spy(element, 'removeAccount');
      pressKey(element.accountChips[0], 'Backspace');
      assert.isTrue(focusSpy.called);
      assert.isTrue(removeSpy.calledOnce);

      pressKey(element.accountChips[0], 'Delete');
      assert.isTrue(removeSpy.calledTwice);
    });
  });
});
