/* globals Twitch */

import Service from 'ember-service';
import { test } from 'qunit';
import moduleForAcceptance from 'web-client/tests/helpers/module-for-acceptance';
import ChannelIndexPage from 'web-client/tests/pages/channel/index';
import channelScenario from 'web-client/mirage/scenarios/channel';
import { stubLogin, stubLogout } from '../../helpers/stub-login';
import { TIMINGS as MOCK_TIMINGS } from 'web-client/tests/helpers/mock-bits-constants';
import {
  LOCALSTORAGE_KEYS,
  TIMINGS,
  SEND_WITH_DELAY_MINIMUM,
  MAX_BITS_MESSAGE_LENGTH
} from 'web-client/utilities/bits/constants-config';
import { getBitsString } from 'web-client/tests/helpers/bits-string';
import MockGeoService from 'web-client/tests/helpers/mock-geo-service';
import RSVP from 'rsvp';
import { assign } from 'ember-platform';
import Mousetrap from 'mousetrap';
import { getProperties } from 'ember-metal/get';
import { FALLBACK_BITS_ACTIONS as ACTIONS_CONFIG } from 'web-client/utilities/bits/constants-config';

const {
  SEEN_PROMO_PREFIX,
  SEEN_ADS_PROMO_PREFIX,
  SEEN_ELIGIBLE_NOTIFICATION_PREFIX
} = LOCALSTORAGE_KEYS;

let recipientName = 'qa_bits_partner';
let senderName = 'bits_sender';
let page, originalTimings;
let userId;

function getPromoSeenKey() {
  return `${SEEN_PROMO_PREFIX}.${userId}`;
}
function getAdsPromoSeenKey() {
  return `${SEEN_ADS_PROMO_PREFIX}.${userId}`;
}
function getRecipientCanEnablePromoSeenKey() {
  return `${SEEN_ELIGIBLE_NOTIFICATION_PREFIX}.${userId}`;
}

function skipPromo() {
  let promoSeenKey = getPromoSeenKey();
  let adsPromoSeenKey = getAdsPromoSeenKey();
  let recipientCanEnablePromoSeenKey = getRecipientCanEnablePromoSeenKey();

  Twitch.storage.set(promoSeenKey, true);
  Twitch.storage.set(adsPromoSeenKey, true);
  Twitch.storage.set(recipientCanEnablePromoSeenKey, true);
}

moduleForAcceptance('Acceptance | Bits - Own Channel', {
  beforeEach() {
    this.owner.lookup('service:globals').set('isBitsEnabled', true);
    this.owner.lookup('service:bits').set('checkIsLoading', false);

    // To enable hashtags, we use a feature flag that accepts a list of channelIds.
    // These channelIds are computed to determine isTagEnabledChannel. When no channel
    // in production has hashtags, we set the feature flag to 0, but our channel tests
    // use 0 as the channelId, thus enabling hashtags. This manually disables hashtags.
    this.owner.lookup('service:bits-tags').set('isTagEnabledChannel', false);

    originalTimings = assign({}, TIMINGS);
    assign(TIMINGS, MOCK_TIMINGS);
    channelScenario(this.server, recipientName);

    this.signedInUser = stubLogin({
      login: recipientName,
      is_partner: true
    });

    userId = this.signedInUser.id;
    page = ChannelIndexPage.create({username: recipientName});
  },

  afterEach() {
    userId = null;
    assign(TIMINGS, originalTimings);
  }
});

test('Ineligible recipient goes to their own chat room', function (assert) {
  assert.expect(6);

  // Make the recipient ineligible but can enable bits
  let { bitsRecipientEligibilities, channels } = this.server.schema;
  let recipientChannel = channels.first({channelName: recipientName});
  let recipientEligibility = bitsRecipientEligibilities.first({channelId: recipientChannel.attrs.id});
  recipientEligibility.update({eligible: false});

  visit(page.url());
  andThen(() => {
    assert.elementCount('.js-bits-broadcaster-notification', 1, 'Recipient sees can-enable-bits FTUE');
    assert.elementCount('.js-bits-toggle', 1, 'Recipient sees bits gem in chat');
  });

  click('.js-bits-broadcaster-notification .bits-promo__close');
  andThen(() => {
    assert.elementCount('.js-bits-broadcaster-notification', 0, 'Recipient closed can-enable-bits FTUE');
    assert.elementCount('.js-bits-toggle', 0, 'Recipient no longer sees bits gem in chat');
  });

  visit(page.url());
  andThen(() => {
    assert.elementCount('.js-bits-broadcaster-notification', 0, 'can-enable-bits FTUE no longer shows up');
    assert.elementCount('.js-bits-toggle', 0, 'no bits gem in chat');
  });
});

moduleForAcceptance('Acceptance | Bits Send', {
  beforeEach() {
    this.toggleIsBitsEnabled = (isEnabled) => {
      this.owner.lookup('service:globals').set('isBitsEnabled', isEnabled);
      this.owner.lookup('service:globals').set('bitsPromoEnabled', false);
    };

    this.owner.lookup('service:bits').set('checkIsLoading', false);

    // See explanation in `Own Channel` tests
    this.owner.lookup('service:bits-tags').set('isTagEnabledChannel', false);

    originalTimings = assign({}, TIMINGS);
    assign(TIMINGS, MOCK_TIMINGS);

    this.toggleIsBitsEnabled(true);

    channelScenario(this.server, recipientName);
    channelScenario(this.server, senderName);
    this.signedInUser = stubLogin({ login: senderName });
    userId = this.signedInUser.id;
    page = ChannelIndexPage.create({username: recipientName});
  },

  afterEach() {
    userId = null;
    assign(TIMINGS, originalTimings);
  }
});

test('Can see watch ad button in buy menu', function (assert) {
  assert.expect(1);
  this.owner.register('service:geo', MockGeoService);
  this.owner.lookup('service:globals').set('AdsForBits', true);
  this.experiments.use({'BITS_FOR_ADS': 'on'});

  skipPromo();
  visit(page.url());

  click('.js-bits-toggle');
  click('.js-buy-bits');

  andThen(() => {
    assert.elementCount('.bits-ads__desc', 1, 'Can see watch ads description');
  });
});

test('Watch ad modal is visible while in theatre mode', function (assert) {
  assert.expect(6);
  this.owner.register('service:geo', MockGeoService);
  this.owner.lookup('service:globals').set('AdsForBits', true);
  this.owner.register('service:player-remote-control', Service.extend({
    mute() {},
    unmute() {},
    attachPlayer() {}
  }));
  this.experiments.use({'BITS_FOR_ADS': 'on'});

  skipPromo();
  visit(page.url());

  andThen(() => {
    assert.equal($('#wormhole-overlays').is(':hidden'), false, 'user can see overlays');
    Mousetrap.trigger('alt+t');
  });

  andThen(() => {
    assert.elementCount('.theatre', 1, 'Theatre mode is on');
    assert.elementCount('.js-bits-toggle', 1, 'Bits toggle button');
    click('.js-bits-toggle');
  });

  andThen(() => {
    assert.elementCount('.js-buy-bits', 1, 'Buy bits button');
    click('.js-buy-bits');
  });

  andThen(() => {
    assert.elementCount('.js-bits-watch-ad-cta', 1, 'Watch ad component');
    click('.js-bits-watch-ad-cta .bits-buy--button');
  });

  andThen(() => {
    assert.equal($('#wormhole-overlays').is(':hidden'), false, 'user can still see overlays');
  });
});

test('No watch ad button because site option is turned off', function (assert) {
  assert.expect(1);
  this.owner.lookup('service:globals').set('AdsForBits', false);
  this.experiments.use({'BITS_FOR_ADS': 'on'});

  skipPromo();
  visit(page.url());

  click('.js-bits-toggle');
  click('.js-buy-bits');

  andThen(() => {
    assert.elementCount('.bits-ads__desc', 0, 'No watch ads description');
  });
});

test('No watch ad button because not in US', function (assert) {
  assert.expect(1);
  this.experiments.use({'BITS_FOR_ADS': 'on'});

  let geoMock = Service.extend({
    getGeo() {
      return RSVP.resolve({
        geo: 'CN'
      });
    }
  });

  this.owner.lookup('service:globals').set('AdsForBits', true);
  this.owner.register('service:geo', geoMock);

  skipPromo();
  visit(page.url());

  click('.js-bits-toggle');
  click('.js-buy-bits');

  andThen(() => {
    assert.elementCount('.bits-ads__desc', 0, 'No watch ads description');
  });
});

test('Can click through Bits Promo', function (assert) {
  assert.expect(5);
  visit(page.url());
  andThen(() => {
    assert.elementText('.bits-promo__header', 'promo_card_one_title', 'Initial page title correct');
  });
  click('.bits-promo__action button');
  andThen(() => {
    assert.elementText('.bits-promo__header', 'promo_card_two_title', 'Second page title changes');
    assert.elementText('.bits-promo__action button', 'promo_card_btn_next', 'Button contains "Next"');
  });

  click('.bits-promo__action button');
  andThen(() => {
    assert.elementText('.bits-promo__header', 'promo_card_three_title', 'Second page title changes');
    assert.elementText('.bits-promo__action button', 'promo_card_btn_complete', 'Button contains "Get Started"');
  });
});

test('Can close Bits Promo', function (assert) {
  assert.expect(2);
  visit(page.url());
  click('.bits-card--standard .bits-promo__close');
  andThen(() => {
    let key = getPromoSeenKey();
    assert.elementCount('.bits-card', 0, 'Tooltip is closed');
    assert.ok(Twitch.storage.get(key), 'Dismissed remembered in localstorage');
  });
});

test('Can send Bits', function (assert) {
  assert.expect(8);

  skipPromo();
  visit(page.url());

  andThen(() => {
    assert.equal(this.server.schema.bitsTransactions.all().models.length, 0, 'Bits transaction DB initially empty');
    assert.equal(currentURL(), `/${recipientName}`, 'Right URL');
  });

  fillIn('.js-chat_input', 'cheer1');
  andThen(() => {
    assert.elementVal('.js-chat_input', 'cheer1', 'Chat contains "cheer1" input');
    assert.elementText('.cheermote-with-amount__amount', '1', 'Tooltip displays 1 Bit being sent');
  });

  click('.qa-chat-buttons__submit');

  andThen(() => {
    assert.elementVal('.js-chat_input', '', 'Textarea emptied after send');
    let transaction = this.server.schema.bitsTransactions.first().attrs;
    let result = getProperties(transaction, 'amount', 'message', 'channel_id', 'user_id');
    let expected = {
      amount: 1,
      message: 'cheer1',
      channel_id: '0',
      user_id: '12345'
    };
    assert.equal(this.server.schema.bitsTransactions.all().models.length, 1, 'Bits transaction saved in DB');
    assert.deepEqual(result, expected, 'Saved transaction values correct');
    assert.equal(this.server.schema.bitsBalances.first({channelId: 1}).attrs.balance, 499, 'Balance updated after transaction');
  });
});

test('Can send Bits with cheer word', function (assert) {
  assert.expect(8);

  skipPromo();
  visit(page.url());

  andThen(() => {
    assert.equal(this.server.schema.bitsTransactions.all().models.length, 0, 'Bits transaction DB initially empty');
    assert.equal(currentURL(), `/${recipientName}`, 'Right URL');
  });

  fillIn('.js-chat_input', 'cheer1 cheer');
  andThen(() => {
    assert.elementVal('.js-chat_input', 'cheer1 cheer', 'Chat contains "cheer1 cheer" input');
    assert.elementText('.cheermote-with-amount__amount', '1', 'Tooltip displays 1 Bit being sent');
  });

  click('.qa-chat-buttons__submit');

  andThen(() => {
    assert.elementVal('.js-chat_input', '', 'Textarea emptied after send');
    let transaction = this.server.schema.bitsTransactions.first().attrs;
    let result = getProperties(transaction, 'amount', 'message', 'channel_id', 'user_id');
    let expected = {
      amount: 1,
      message: 'cheer1 cheer',
      channel_id: '0',
      user_id: '12345'
    };
    assert.equal(this.server.schema.bitsTransactions.all().models.length, 1, 'Bits transaction saved in DB');
    assert.deepEqual(result, expected, 'Saved transaction values correct');
    assert.equal(this.server.schema.bitsBalances.first({channelId: 1}).attrs.balance, 499, 'Balance updated after transaction');
  });
});

test('Can send Bits mixed-case', function (assert) {
  assert.expect(8);

  skipPromo();
  visit(page.url());

  andThen(() => {
    assert.equal(this.server.schema.bitsTransactions.all().models.length, 0, 'Bits transaction DB initially empty');
    assert.equal(currentURL(), `/${recipientName}`, 'Right URL');
  });

  fillIn('.js-chat_input', 'chEEr1');
  andThen(() => {
    assert.elementVal('.js-chat_input', 'chEEr1', 'Chat contains "chEEr1" input');
    assert.elementText('.cheermote-with-amount__amount', '1', 'Tooltip displays 1 Bit being sent');
  });

  click('.qa-chat-buttons__submit');

  andThen(() => {
    assert.elementVal('.js-chat_input', '', 'Textarea emptied after send');
    let transaction = this.server.schema.bitsTransactions.first().attrs;
    let result = getProperties(transaction, 'amount', 'message', 'channel_id', 'user_id');
    let expected = {
      amount: 1,
      message: 'chEEr1',
      channel_id: '0',
      user_id: '12345'
    };
    assert.equal(this.server.schema.bitsTransactions.all().models.length, 1, 'Bits transaction saved in DB');
    assert.deepEqual(result, expected, 'Saved transaction values correct');
    assert.equal(this.server.schema.bitsBalances.first({channelId: 1}).attrs.balance, 499, 'Balance updated after transaction');
  });
});

test('Bits send greater than 1000 triggers delayed send', function (assert) {
  assert.expect(1);

  // Provide additional Bits to the sender so we can actually send 1000
  let { bitsBalances, channels } = this.server.schema;
  let senderChannel = channels.first({channelName: senderName});
  let senderBitsBalance = bitsBalances.first({channelId: senderChannel.attrs.id});
  let { UNDO_PROMPT_DURATION } = TIMINGS;
  senderBitsBalance.update({balance: SEND_WITH_DELAY_MINIMUM});

  let startTime;
  skipPromo();
  visit(page.url());
  fillIn('.js-chat_input', 'cheer1000');
  andThen(() => {
    startTime = new Date().getTime();
  });

  click('.qa-chat-buttons__submit');

  andThen(() => {
    let endTime = new Date().getTime();
    assert.ok((endTime - startTime) > UNDO_PROMPT_DURATION, 'Bits send delayed');
  });
});

test('Shows prompt on cheer0 and prevents send', function (assert) {
  assert.expect(3);
  skipPromo();
  visit(page.url());
  fillIn('.js-chat_input', 'cheer0');
  andThen(() => {
    assert.elementVal('.js-chat_input', 'cheer0', 'Chat input contains cheer0');
    assert.elementText('.js-bits-cheermote-spotlight section', getBitsString('zero'), 'cheer0 error message is shown to user');
  });

  click('.qa-chat-buttons__submit');

  andThen(() => {
    let transactions = this.server.schema.bitsTransactions.all().models;
    assert.equal(transactions.length, 0, 'No transactions were made');
  });
});

test('Shows prompt on cheer10001 and prevents send', function (assert) {
  assert.expect(3);

  // Provide additional Bits to the sender so we can actually send >10000
  let { bitsBalances, channels } = this.server.schema;
  let senderChannel = channels.first({channelName: senderName});
  let senderBitsBalance = bitsBalances.first({channelId: senderChannel.attrs.id});
  senderBitsBalance.update({balance: 20000});

  skipPromo();
  visit(page.url());
  fillIn('.js-chat_input', 'cheer10001');
  andThen(() => {
    assert.equal($('.js-chat_input').val().trim(), 'cheer10001', 'Chat input contains cheer10001');
    assert.equal($('.js-bits-cheermote-spotlight section').text().trim(), getBitsString('above_max'), 'Above maximum cheer emote error message is shown to user');
  });
  click('.chat-buttons-container .js-chat-buttons__submit');
  andThen(() => {
    let transactions = this.server.schema.bitsTransactions.all().models;
    assert.equal(transactions.length, 0, 'No transactions were made');
  });
});

test(`Show error message and prevent send if user's current cheer is above their balance`, function (assert) {
  assert.expect(2);

  // Set user's balance to 100 and cheer greater than that
  let { bitsBalances, channels } = this.server.schema;
  let senderChannel = channels.first({channelName: senderName});
  let senderBitsBalance = bitsBalances.first({channelId: senderChannel.attrs.id});
  senderBitsBalance.update({ balance: 99 });

  skipPromo();
  visit(page.url());

  fillIn('.js-chat_input', 'cheer100');
  andThen(() => {
    assert.elementText('.js-bits-cheermote-spotlight section p:first',
      getBitsString('balance_exceeded', '', { requiredBalance: 1 }));
  });

  click('.qa-chat-buttons__submit');
  andThen(() => {
    let transactions = this.server.schema.bitsTransactions.all().models;
    assert.equal(transactions.length, 0, 'No transactions made on send attempts because cheer exceeds their balance');
  });
});

test(`Show error message and prevent send if user's current cheer message length exceeds the max`, function (assert) {
  assert.expect(2);

  // Set user's balance to a ridiculously huge number
  let { bitsBalances, channels } = this.server.schema;
  let senderChannel = channels.first({channelName: senderName});
  let senderBitsBalance = bitsBalances.first({channelId: senderChannel.attrs.id});
  senderBitsBalance.update({ balance: 9999999 });

  skipPromo();
  visit(page.url());

  let currentCheer = 'cheer1';
  while (currentCheer.length < MAX_BITS_MESSAGE_LENGTH) {
    currentCheer += ` cheer1`;
  }

  fillIn('.js-chat_input', currentCheer);
  andThen(() => {
    assert.elementText('.js-bits-cheermote-spotlight section',
      getBitsString('max_length_exceeded'));
  });

  click('.qa-chat-buttons__submit');
  andThen(() => {
    let transactions = this.server.schema.bitsTransactions.all().models;
    assert.equal(transactions.length, 0, 'No transactions made on send attempts cheer message length exceeds the max');
  });
});

test('Shows prompt when a cheermote is below min cheermote and prevents send until min cheermote is reached', function (assert) {
  assert.expect(4);
  skipPromo();

  // Make the recipient have min cheer emote
  let { bitsRecipientEligibilities, channels } = this.server.schema;
  let recipientChannel = channels.first({channelName: recipientName});
  let recipientEligibility = bitsRecipientEligibilities.first({channelId: recipientChannel.attrs.id});
  recipientEligibility.update({ min_bits_emote: 15 });

  visit(page.url());

  fillIn('.js-chat_input', 'cheer14');
  andThen(() => {
    assert.elementText('.js-bits-cheermote-spotlight section',
      getBitsString('min_bits_emotes', '', { minBitsEmote: 15 }));
  });
  click('.qa-chat-buttons__submit');

  fillIn('.js-chat_input', 'cheer15 cheer1');
  andThen(() => {
    assert.elementText('.js-bits-cheermote-spotlight section',
      getBitsString('min_bits_emotes', '', { minBitsEmote: 15 }));
  });
  click('.qa-chat-buttons__submit');

  andThen(() => {
    let transactions = this.server.schema.bitsTransactions.all().models;
    assert.equal(transactions.length, 0, 'No transactions made on send attempts because below min bits');
  });

  fillIn('.js-chat_input', 'cheer15 cheer15 cheer15');
  click('.qa-chat-buttons__submit');

  andThen(() => {
    let transactions = this.server.schema.bitsTransactions.all().models;
    assert.equal(transactions.length, 1, '1 Transaction was made after reaching min cheermote');
  });
});

test('Shows prompt when total cheer value is below the channel min and prevents send until min is reached', function (assert) {
  assert.expect(4);
  skipPromo();

  // Make the recipient have min bits
  let { bitsRecipientEligibilities, channels } = this.server.schema;
  let recipientChannel = channels.first({channelName: recipientName});
  let recipientEligibility = bitsRecipientEligibilities.first({channelId: recipientChannel.attrs.id});
  recipientEligibility.update({min_bits: 15});

  visit(page.url());

  fillIn('.js-chat_input', 'cheer5');
  andThen(() => {
    assert.elementText('.js-bits-cheermote-spotlight section',
      getBitsString('num_bits_to_min', '', { numBitsToMin: 10 }));
  });
  click('.qa-chat-buttons__submit');

  fillIn('.js-chat_input', 'cheer5 cheer5');
  andThen(() => {
    assert.elementText('.js-bits-cheermote-spotlight section',
      getBitsString('num_bits_to_min', '', { numBitsToMin: 5 }));
  });
  click('.qa-chat-buttons__submit');

  andThen(() => {
    let transactions = this.server.schema.bitsTransactions.all().models;
    assert.equal(transactions.length, 0, 'No transactions made on send attempts because below min bits');
  });

  fillIn('.js-chat_input', 'cheer5 cheer5 cheer5');
  click('.qa-chat-buttons__submit');

  andThen(() => {
    let transactions = this.server.schema.bitsTransactions.all().models;
    assert.equal(transactions.length, 1, '1 Transaction was made after reaching min bits');
  });
});

test('Sender ineligibility prevents user send', function (assert) {
  assert.expect(2);
  skipPromo();

  // Make the sender ineligible
  let { bitsSenderEligibilities, channels } = this.server.schema;
  let senderChannel = channels.first({channelName: senderName});
  let senderEligibility = bitsSenderEligibilities.first({channelId: senderChannel.attrs.id});
  senderEligibility.update({eligible: false});

  visit(page.url());
  fillIn('.js-chat_input', 'cheer100');
  andThen(() => {
    assert.elementText('.bits-hint--error',
      getBitsString('ineligible_sender'),
      'Shows error message for sender to contact support');
  });

  click('.qa-chat-buttons__submit');

  andThen(() => {
    let transactions = this.server.schema.bitsTransactions.all().models;
    assert.equal(transactions.length, 0, 'No transactions made on send attempt');
  });
});

test('Recipient Ineligibility prevents user send', function (assert) {
  assert.expect(2);
  skipPromo();

  // Make the recipient ineligible
  let { bitsRecipientEligibilities, channels } = this.server.schema;
  let recipientChannel = channels.first({channelName: recipientName});
  let recipientEligibility = bitsRecipientEligibilities.first({channelId: recipientChannel.attrs.id});
  recipientEligibility.update({eligible: false});

  visit(page.url());
  fillIn('.js-chat_input', 'cheer100');
  andThen(() => {
    assert.elementText('.bits-hint--error',
      getBitsString('ineligible_recipient'),
      'Shows error message stating recipient cannot receive Bits');
  });

  click('.qa-chat-buttons__submit');

  andThen(() => {
    let transactions = this.server.schema.bitsTransactions.all().models;
    assert.equal(transactions.length, 0, 'No transactions made on send attempt');
  });
});

test('Bits toggle opens up a prompt', function (assert) {
  assert.expect(4);

  skipPromo();
  visit(page.url());
  andThen(() => {
    assert.elementCount('.bits-card', 0, 'No Tooltip open');
  });

  click('.js-bits-toggle');
  andThen(() => {
    assert.elementCount('.bits-card', 1, 'Tooltip was opened');
    assert.elementCount('.bits-card .js-bits-emotes-intro', 1, 'Emotes intro is visible');
  });

  click('.bits-card__close');
  andThen(() => {
    assert.elementCount('.bits-card', 0, 'Tooltip was closed');
  });
});

test('can close buy bits tooltip clicking bits toggle', function (assert) {
  this.server.createList('price', 2);
  assert.expect(2);

  skipPromo();
  visit(page.url());
  click('.js-bits-toggle');
  click('.js-buy-bits');

  andThen(() => {
    assert.elementCount('.bits-purchase', 1);
  });

  click('.js-bits-toggle');

  andThen(() => {
    assert.elementCount('.bits-purchase', 0);
  });
});

test('can close buy bits tooltip and keep bit tooltip open with a cheer in the chat text box', function (assert){
  this.server.createList('price', 2);
  assert.expect(3);

  skipPromo();
  visit(page.url());
  fillIn('.js-chat_input', 'cheer20');

  andThen(() => {
    assert.elementCount('.bits-card', 1);
  });

  click('.js-buy-bits');
  click('.js-bits-toggle');

  andThen(() => {
    assert.elementCount('.bits-purchase', 0, 'Bits products not visible');
    assert.elementCount('.bits-card .js-bits-cheermote-spotlight', 1, 'Cheermote spotlight is visible');
  });
});

test('No Bits prompts when feature flag is disabled', function (assert) {
  assert.expect(2);

  this.toggleIsBitsEnabled(false);

  visit(page.url());

  andThen(() => {
    assert.elementCount('.bits-card', 0, 'No Promo open');
  });

  skipPromo();
  visit(page.url());
  fillIn('.js-chat_input', 'cheer100');

  andThen(() => {
    assert.elementCount('.bits-card', 0, 'Still no Bits prompt');
  });
});

test('User explores chat tooltip and sends a cheer using only their mouse', function (assert) {
  assert.expect(13);

  let config = ACTIONS_CONFIG;
  let discoverableEmotes = config.actions.filter((action) => {
    return action.prefix !== 'Muxy' && action.prefix !== 'Streamlabs';
  });
  let firstDiscoverableEmote = discoverableEmotes[0];
  let firstDiscoverableEmoteTier = firstDiscoverableEmote.tiers[0];

  let numDiscoverableEmotes = discoverableEmotes.length;
  let numTiersFirstEmote = firstDiscoverableEmote.tiers.length;

  skipPromo();
  visit(page.url());

  // open the tooltip
  click('.js-bits-toggle');
  andThen(() => {
    assert.elementCount('.js-bits-emotes-intro', 1, 'Emotes intro when opening tooltip');
  });

  // click on 'How do I cheer?' to view the tutorial
  click('.js-bits-emotes-intro a');
  andThen(() => {
    assert.elementCount('.js-bits-cheering-tutorial', 1, `Tutorial after clicking 'How do I cheer?'`);
    assert.elementCount('.js-bits-animated-emote-landing .bits-card__back', 1, `Back button visible after clicking 'How do I cheer?'`);
  });

  // click back to go back to the landing
  click('.js-bits-animated-emote-landing .bits-card__back');
  andThen(() => {
    assert.elementCount('.js-bits-emotes-intro', 1, 'Emotes intro when going back from tutorial');
    assert.elementCount('.js-bits-animated-emote-selector .js-bits-interactive-cheermote', numDiscoverableEmotes, `Selector shows the correct number of discoverable emotes (${numDiscoverableEmotes})`);
  });

  // click on the first emote
  click('.js-bits-animated-emote-selector .js-bits-interactive-cheermote:first');
  andThen(() => {
    assert.elementCount('.js-bits-emote-tiers-intro', 1, 'Emote tiers intro after clicking an emote');
    assert.elementCount('.js-bits-animated-emote-tiers .js-bits-interactive-cheermote', numTiersFirstEmote, `Emote tiers selector with the correct number of tiers is visible (${numTiersFirstEmote})`);
    assert.elementCount('.js-bits-animated-emote-landing .bits-card__back', 1, 'Back button is visible when viewing emote tiers');
  });

  // click on back button to return to the emotes intro (initial state)
  click('.js-bits-animated-emote-landing .bits-card__back');
  andThen(() => {
    assert.elementCount('.js-bits-emotes-intro', 1, 'Emotes intro when going back from showing tiers');
  });

  // click on the first emote's tier
  click('.js-bits-animated-emote-selector .js-bits-interactive-cheermote:first');
  click('.js-bits-animated-emote-tiers .js-bits-interactive-cheermote:first');
  andThen(() => {
    assert.elementVal('.js-chat_input', `${firstDiscoverableEmote.prefix}${firstDiscoverableEmoteTier.min_bits}`, `Chat input contains now has a cheer message using the first discoverable emote's tier`);
    assert.elementCount('.js-bits-cheermote-spotlight', 1, `User's cheer is highlighted`);
    assert.elementCount('.js-bits-animated-emote-landing .bits-card__close', 0, 'No close button');
  });

  click('.qa-chat-buttons__submit');
  andThen(() => {
    let transactions = this.server.schema.bitsTransactions.all().models;
    assert.equal(transactions.length, 1, 'Transaction was made using the UI only (mouse only, no keyboard)');
  });
});

moduleForAcceptance('Acceptance | Bits - Not Logged In', {
  beforeEach() {
    this.owner.lookup('service:globals').set('isBitsEnabled', true);
    this.owner.lookup('service:bits').set('checkIsLoading', false);

    // See explanation in `Own Channel` tests
    this.owner.lookup('service:bits-tags').set('isTagEnabledChannel', false);

    originalTimings = assign({}, TIMINGS);
    assign(TIMINGS, MOCK_TIMINGS);
    channelScenario(this.server, recipientName);

    stubLogout();
    page = ChannelIndexPage.create({username: recipientName});
  },

  afterEach() {
    assign(TIMINGS, originalTimings);
  }
});

test('Not Logged In - no bits gem', function (assert) {
  assert.expect(2);

  visit(page.url());
  andThen(() => {
    assert.elementCount('.js-bits-toggle', 0, 'bits toggle isnt visible');
    assert.elementCount('.js-bits-tooltip-wrapper', 0, 'bits tooltip isnt automatically shown (no FTUE)');
  });
});
