// eslint-disable-next-line @typescript-eslint/triple-slash-reference
/// <reference path="../../../../test/src/custom_typings/chai.d.ts" />
/* eslint-disable no-undef */
import { ZuiNotifier } from '@zywave/zui-notifier';
import type { ZuiNotifierType, ZuiNotifierTypeIcons } from '@zywave/zui-notifier';
import type { ZuiIcon } from '@zywave/zui-icons';
import { assert } from '@esm-bundle/chai';
import { sleep, awaitEvent } from '@zywave/../../test/src/util/helpers';

const supportedNotifierTypes: ZuiNotifierType[] = ['info', 'success', 'error', 'warning'];

const iconNameBasedOnType: ZuiNotifierTypeIcons = {
  info: 'zui-info',
  success: 'zui-success',
  error: 'zui-error',
  warning: 'zui-warning',
};

suite('zui-notifier', () => {
  let element: ZuiNotifier;

  setup(() => {
    element = document.createElement('zui-notifier') as ZuiNotifier;
    document.body.appendChild(element);
  });

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

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

  test('header attribute property renders text', async () => {
    const headerText = 'I am a header';
    element.header = headerText;
    await element.updateComplete;
    const shadowEl = element.shadowRoot?.querySelector('.notifier-header');
    assert.equal(shadowEl.textContent, headerText);
  });

  test('message attribute property renders text', async () => {
    const messageText = 'The message is the medium.';
    element.message = messageText;
    await element.updateComplete;
    const shadowEl = element.shadowRoot?.querySelector('.notifier-message');
    assert.equal(shadowEl.textContent, messageText);
  });

  test("after duration notifier has 'display: none' added", async () => {
    const duration = 10;
    element.duration = duration;
    await element.updateComplete;
    await sleep(duration);
    const shadowEl = element.shadowRoot?.querySelector('.notifier-container-outer');
    const elStyles = getComputedStyle(shadowEl);
    assert.equal(elStyles.getPropertyValue('display'), 'none');
  });

  for (const type of supportedNotifierTypes) {
    test(`ZuiNotifier.type = ${type} renders... ZuiIcon.icon = ${iconNameBasedOnType[type]}`, async () => {
      element.type = type as ZuiNotifierType;
      await element.updateComplete;
      const shadowEl: ZuiIcon = element.shadowRoot?.querySelector('.notifier-icon > zui-icon');
      assert.equal((shadowEl as ZuiIcon).icon, iconNameBasedOnType[type]);
    });
  }

  test('style positioning of zui-notifier is correct', async () => {
    element.show();
    const parentEl =
      (element.getRootNode() as HTMLElement).querySelector(element.parentSelector as string) || element.parentElement;
    const parentRect = parentEl.getBoundingClientRect();
    const notifierPose = {
      top: `${parentRect.top}px`,
      right: `${window.innerWidth - parentRect.right}px`,
    };
    await element.updateComplete;
    assert.equal(element.style.top, notifierPose.top);
    assert.equal(element.style.right, notifierPose.right);
  });

  test('action slotted element closes zui-notifier on click', async () => {
    const btn = document.createElement('button');
    const btnEl = (): HTMLElement => element.querySelector('[slot="action"]');
    btn.setAttribute('slot', 'action');
    element.appendChild(btn);
    element.show();
    await element.updateComplete;
    btnEl().click();
    await awaitEvent(element, 'close');
    await sleep(1);
    assert.equal(
      getComputedStyle(element.shadowRoot?.querySelector('.notifier-container-outer')).getPropertyValue('display'),
      'none'
    );
  });
});
