/**
 * Copyright (c) HashiCorp, Inc.
 * SPDX-License-Identifier: BUSL-1.1
 */
import { module, test } from 'qunit';
import sinon from 'sinon';
import { setupRenderingTest } from 'ember-qunit';
import { find, render, findAll } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
import { format, formatRFC3339, subMonths } from 'date-fns';
import timestamp from 'core/utils/timestamp';
module('Integration | Component | clients/line-chart', function (hooks) {
  setupRenderingTest(hooks);
  hooks.before(function () {
    sinon.stub(timestamp, 'now').callsFake(() => new Date('2018-04-03T14:15:30'));
  });
  hooks.beforeEach(function () {
    this.set('xKey', 'foo');
    this.set('yKey', 'bar');
    this.set('dataset', [
      {
        foo: '2018-04-03T14:15:30',
        bar: 4,
        expectedLabel: '4/18',
      },
      {
        foo: '2018-05-03T14:15:30',
        bar: 8,
        expectedLabel: '5/18',
      },
      {
        foo: '2018-06-03T14:15:30',
        bar: 14,
        expectedLabel: '6/18',
      },
      {
        foo: '2018-07-03T14:15:30',
        bar: 10,
        expectedLabel: '7/18',
      },
    ]);
  });
  hooks.after(function () {
    timestamp.now.restore();
  });
  test('it renders', async function (assert) {
    await render(hbs`
    
      
      
    `);
    assert.dom('[data-test-line-chart]').exists('Chart is rendered');
    assert
      .dom('[data-test-line-chart="plot-point"]')
      .exists({ count: this.dataset.length }, `renders ${this.dataset.length} plot points`);
    findAll('[data-test-x-axis] text').forEach((e, i) => {
      // For some reason the first axis label is not rendered
      assert
        .dom(e)
        .hasText(
          `${this.dataset[i].expectedLabel}`,
          `renders x-axis label: ${this.dataset[i].expectedLabel}`
        );
    });
    assert.dom('[data-test-y-axis] text').hasText('0', `y-axis starts at 0`);
  });
  test('it renders upgrade data', async function (assert) {
    const now = timestamp.now();
    this.set('dataset', [
      {
        foo: formatRFC3339(subMonths(now, 4)),
        bar: 4,
        month: format(subMonths(now, 4), 'M/yy'),
      },
      {
        foo: formatRFC3339(subMonths(now, 3)),
        bar: 8,
        month: format(subMonths(now, 3), 'M/yy'),
      },
      {
        foo: formatRFC3339(subMonths(now, 2)),
        bar: 14,
        month: format(subMonths(now, 2), 'M/yy'),
      },
      {
        foo: formatRFC3339(subMonths(now, 1)),
        bar: 10,
        month: format(subMonths(now, 1), 'M/yy'),
      },
    ]);
    this.set('upgradeData', [
      {
        id: '1.10.1',
        previousVersion: '1.9.2',
        timestampInstalled: formatRFC3339(subMonths(now, 2)),
      },
    ]);
    await render(hbs`
    
      
    
    `);
    assert.dom('[data-test-line-chart]').exists('Chart is rendered');
    assert
      .dom('[data-test-line-chart="plot-point"]')
      .exists({ count: this.dataset.length }, `renders ${this.dataset.length} plot points`);
    assert
      .dom(find(`[data-test-line-chart="upgrade-${this.dataset[2].month}"]`))
      .hasStyle(
        { fill: 'rgb(253, 238, 186)' },
        `upgrade data point ${this.dataset[2].month} has yellow highlight`
      );
  });
  test('it renders tooltip', async function (assert) {
    assert.expect(1);
    const now = timestamp.now();
    const tooltipData = [
      {
        month: format(subMonths(now, 4), 'M/yy'),
        timestamp: formatRFC3339(subMonths(now, 4)),
        clients: 4,
        new_clients: {
          clients: 0,
        },
      },
      {
        month: format(subMonths(now, 3), 'M/yy'),
        timestamp: formatRFC3339(subMonths(now, 3)),
        clients: 8,
        new_clients: {
          clients: 4,
        },
      },
      {
        month: format(subMonths(now, 2), 'M/yy'),
        timestamp: formatRFC3339(subMonths(now, 2)),
        clients: 14,
        new_clients: {
          clients: 6,
        },
      },
      {
        month: format(subMonths(now, 1), 'M/yy'),
        timestamp: formatRFC3339(subMonths(now, 1)),
        clients: 20,
        new_clients: {
          clients: 4,
        },
      },
    ];
    this.set('dataset', tooltipData);
    this.set('upgradeData', [
      {
        id: '1.10.1',
        previousVersion: '1.9.2',
        timestampInstalled: formatRFC3339(subMonths(now, 2)),
      },
    ]);
    await render(hbs`
    
      
    
    `);
    const tooltipHoverCircles = findAll('[data-test-hover-circle]');
    assert.strictEqual(tooltipHoverCircles.length, tooltipData.length, 'all data circles are rendered');
    // FLAKY after adding a11y testing, skip for now
    // for (const [i, bar] of tooltipHoverCircles.entries()) {
    //   await triggerEvent(bar, 'mouseover');
    //   const tooltip = document.querySelector('.ember-modal-dialog');
    //   const { month, clients, new_clients } = tooltipData[i];
    //   assert
    //     .dom(tooltip)
    //     .includesText(
    //       `${formatChartDate(month)} ${clients} total clients ${new_clients.clients} new clients`,
    //       `tooltip text is correct for ${month}`
    //     );
    // }
  });
  test('it fails gracefully when data is not formatted correctly', async function (assert) {
    this.set('dataset', [
      {
        foo: 1,
        bar: 4,
      },
      {
        foo: 2,
        bar: 8,
      },
      {
        foo: 3,
        bar: 14,
      },
      {
        foo: 4,
        bar: 10,
      },
    ]);
    await render(hbs`
    
      
    
    `);
    assert.dom('[data-test-line-chart]').doesNotExist('Chart is not rendered');
    assert
      .dom('[data-test-component="empty-state"]')
      .hasText('No data to display', 'Shows empty state when time date is not formatted correctly');
  });
  test('it fails gracefully when upgradeData is an object', async function (assert) {
    this.set('upgradeData', { some: 'object' });
    await render(hbs`
    
    
    
    `);
    assert
      .dom('[data-test-line-chart="plot-point"]')
      .exists({ count: this.dataset.length }, 'chart still renders when upgradeData is not an array');
  });
  test('it fails gracefully when upgradeData has incorrect key names', async function (assert) {
    this.set('upgradeData', [{ incorrect: 'key names' }]);
    await render(hbs`
    
    
    
    `);
    assert
      .dom('[data-test-line-chart="plot-point"]')
      .exists({ count: this.dataset.length }, 'chart still renders when upgradeData has incorrect keys');
  });
  test('it renders empty state when no dataset', async function (assert) {
    await render(hbs`
    
    
    
    `);
    assert.dom('[data-test-component="empty-state"]').exists('renders empty state when no data');
    assert
      .dom('[data-test-empty-state-subtext]')
      .hasText(
        `this is a custom message to explain why you're not seeing a line chart`,
        'custom message renders'
      );
  });
  test('it updates axis when dataset updates', async function (assert) {
    const datasets = {
      small: [
        {
          foo: '2020-04-01',
          bar: 4,
          month: '4/20',
        },
        {
          foo: '2020-05-01',
          bar: 8,
          month: '5/20',
        },
        {
          foo: '2020-06-01',
          bar: 1,
        },
        {
          foo: '2020-07-01',
          bar: 10,
        },
      ],
      large: [
        {
          foo: '2020-08-01',
          bar: 4586,
          month: '8/20',
        },
        {
          foo: '2020-09-01',
          bar: 8928,
          month: '9/20',
        },
        {
          foo: '2020-10-01',
          bar: 11948,
          month: '10/20',
        },
        {
          foo: '2020-11-01',
          bar: 16943,
          month: '11/20',
        },
      ],
      broken: [
        {
          foo: '2020-01-01',
          bar: null,
          month: '1/20',
        },
        {
          foo: '2020-02-01',
          bar: 0,
          month: '2/20',
        },
        {
          foo: '2020-03-01',
          bar: 22,
          month: '3/20',
        },
        {
          foo: '2020-04-01',
          bar: null,
          month: '4/20',
        },
        {
          foo: '2020-05-01',
          bar: 70,
          month: '5/20',
        },
        {
          foo: '2020-06-01',
          bar: 50,
          month: '6/20',
        },
      ],
    };
    this.set('dataset', datasets.small);
    await render(hbs`
    
      
    
    `);
    assert.dom('[data-test-y-axis]').hasText('0 2 4 6 8 10', 'y-axis renders correctly for small values');
    assert
      .dom('[data-test-x-axis]')
      .hasText('4/20 5/20 6/20 7/20', 'x-axis renders correctly for small values');
    // Update to large dataset
    this.set('dataset', datasets.large);
    assert.dom('[data-test-y-axis]').hasText('0 5k 10k 15k', 'y-axis renders correctly for new large values');
    assert
      .dom('[data-test-x-axis]')
      .hasText('8/20 9/20 10/20 11/20', 'x-axis renders correctly for small values');
    // Update to broken dataset
    this.set('dataset', datasets.broken);
    assert.dom('[data-test-y-axis]').hasText('0 20 40 60', 'y-axis renders correctly for new broken values');
    assert
      .dom('[data-test-x-axis]')
      .hasText('1/20 2/20 3/20 4/20 5/20 6/20', 'x-axis renders correctly for small values');
    assert.dom('[data-test-hover-circle]').exists({ count: 4 }, 'only render circles for non-null values');
    assert
      .dom('[data-test-hover-circle="1/20"]')
      .doesNotExist('first month dot does not exist because value is null');
    assert
      .dom('[data-test-hover-circle="4/20"]')
      .doesNotExist('other null count month dot also does not render');
    // Note: the line should also show a gap, but this is difficult to test for
  });
});