// eslint-disable-next-line @typescript-eslint/triple-slash-reference
/// <reference path="../../../../test/src/custom_typings/chai.d.ts" />
/* eslint-disable no-undef */
import { ZuiProgress } from '@zywave/zui-progress';
import { assert } from '@esm-bundle/chai';
import { conditionalTest } from '../../../../test/src/util/mocha-helpers';

const SUPPORTS_INTERNAL_STATE = (() => {
  let supportsInternalStates = false;
  customElements.define(
    'internals-test',
    class extends HTMLElement {
      constructor() {
        super();

        this.attachShadow({ mode: 'open' });

        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        supportsInternalStates = !!(this as any).attachInternals()?.states;
      }
    }
  );

  document.createElement('internals-test');
  return supportsInternalStates;
})();

suite('zui-progress', () => {
  let element: ZuiProgress;

  setup(() => {
    element = document.createElement('zui-progress') as ZuiProgress;

    document.body.appendChild(element);
  });

  teardown(() => {
    document.body.removeChild(element);
  });

  test('initializes as a ZuiProgress', () => {
    assert.instanceOf(element, ZuiProgress);
  });

  test('aria attributes properly applied - determinate', async () => {
    const progress = Math.random();
    element.setAttribute('progress', progress.toString());

    await element.updateComplete;

    assert.equal(element.getAttribute('role'), 'progressbar');
    assert.equal(element.getAttribute('aria-valuemin'), '0');
    assert.equal(element.getAttribute('aria-valuemax'), '100');
    assert.equal(element.getAttribute('aria-valuenow'), progress.toString());
  });

  test('aria attributes properly applied - indeterminate', async () => {
    element.setAttribute('indeterminate', '');

    await element.updateComplete;

    assert.equal(element.getAttribute('role'), 'progressbar');
    assert.equal(element.getAttribute('aria-valuemin'), '0');
    assert.equal(element.getAttribute('aria-valuemax'), '100');
    assert.notExists(element.getAttribute('aria-valuenow'));
  });

  test('aria attributes properly applied - indeterminate removed after update', async () => {
    const progress = Math.random();
    element.setAttribute('progress', progress.toString());

    await element.updateComplete;

    assert.equal(element.getAttribute('role'), 'progressbar');
    assert.equal(element.getAttribute('aria-valuemin'), '0');
    assert.equal(element.getAttribute('aria-valuemax'), '100');
    assert.equal(element.getAttribute('aria-valuenow'), progress.toString());

    element.setAttribute('indeterminate', '');

    await element.updateComplete;

    assert.equal(element.getAttribute('role'), 'progressbar');
    assert.equal(element.getAttribute('aria-valuemin'), '0');
    assert.equal(element.getAttribute('aria-valuemax'), '100');
    assert.notExists(element.getAttribute('aria-valuenow'));
  });

  test('progress is capped at 100', async () => {
    const progress = 1000;
    element.setAttribute('progress', progress.toString());

    await element.updateComplete;

    assert.equal(element.getAttribute('aria-valuenow'), '100');
  });

  conditionalTest(SUPPORTS_INTERNAL_STATE, 'sets internal indeterminate state', async () => {
    element.setAttribute('indeterminate', '');

    await element.updateComplete;

    assert.isTrue(element.matches(':state(indeterminate)'));
  });
});
