/**
 * Copyright IBM Corp. 2016, 2025
 * SPDX-License-Identifier: BUSL-1.1
 */

import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { click, render, resetOnerror, setupOnerror } from '@ember/test-helpers';
import { GENERAL } from 'vault/tests/helpers/general-selectors';
import hbs from 'htmlbars-inline-precompile';
import sinon from 'sinon';

module('Integration | Component | download button', function (hooks) {
  setupRenderingTest(hooks);

  hooks.beforeEach(function () {
    const downloadService = this.owner.lookup('service:download');
    this.downloadSpy = sinon.stub(downloadService, 'miscExtension');

    this.data = 'my data to download';
    this.filename = 'my special file';
    this.extension = 'csv';
  });

  test('it renders', async function (assert) {
    await render(hbs`
     <DownloadButton /> `);
    assert.dom(GENERAL.icon('download')).exists('renders download icon');
    assert.dom(GENERAL.button('Download')).hasText('Download', 'renders default text');
  });

  test('it renders passed args', async function (assert) {
    await render(hbs`
     <DownloadButton @text="I do something" @hideIcon={{true}} /> `);
    assert.dom(GENERAL.icon('download')).doesNotExist('hides icon');
    assert.dom(GENERAL.button('Download')).hasText('I do something', 'renders passed text');
  });

  test('it downloads with defaults when only passed @data arg', async function (assert) {
    assert.expect(3);

    await render(hbs`
      <DownloadButton @data={{this.data}} />
    `);
    await click(GENERAL.button('Download'));
    const [filename, content, extension] = this.downloadSpy.getCall(0).args;
    assert.ok(filename.includes('Z'), 'filename defaults to ISO string');
    assert.strictEqual(content, this.data, 'called with correct data');
    assert.strictEqual(extension, 'txt', 'called with default extension');
  });

  test('it calls download service with passed in args', async function (assert) {
    assert.expect(3);

    await render(hbs`
      <DownloadButton
        @data={{this.data}}
        @filename={{this.filename}}
        @mime={{this.mime}}
        @extension={{this.extension}}
      />
    `);
    await click(GENERAL.button('Download'));
    const [filename, content, extension] = this.downloadSpy.getCall(0).args;
    assert.ok(filename.includes(`${this.filename}-`), 'filename added to ISO string');
    assert.strictEqual(content, this.data, 'called with correct data');
    assert.strictEqual(extension, this.extension, 'called with passed in extension');
  });

  test('it sets download content with arg passed to fetchData', async function (assert) {
    assert.expect(3);
    this.fetchData = () => 'this is fetched data from a parent function';
    await render(hbs`
      <DownloadButton @fetchData={{this.fetchData}} />
    `);

    await click(GENERAL.button('Download'));
    const [filename, content, extension] = this.downloadSpy.getCall(0).args;
    assert.ok(filename.includes('Z'), 'filename defaults to ISO string');
    assert.strictEqual(content, this.fetchData(), 'called with fetched data');
    assert.strictEqual(extension, 'txt', 'called with default extension');
  });

  test('it throws error when both data and fetchData are passed as args', async function (assert) {
    assert.expect(1);
    setupOnerror((error) => {
      assert.strictEqual(
        error.message,
        'Assertion Failed: Only pass either @data or @fetchData, passing both means @data will be overwritten by the return value of @fetchData',
        'throws error with incorrect args'
      );
    });
    this.fetchData = () => 'this is fetched data from a parent function';
    await render(hbs`
        <DownloadButton @data={{this.data}} @fetchData={{this.fetchData}} />
      `);
    resetOnerror();
  });
});
