import { getGlobal } from "../../../../source/types/global.mjs";
import * as chai from "chai";
import { chaiDom } from "../../../util/chai-dom.mjs";
import { initJSDOM } from "../../../util/jsdom.mjs";

let expect = chai.expect;
chai.use(chaiDom);

const global = getGlobal();

let html = `
	<monster-wizard id="wizard-under-test">
		<section
			data-monster-option-navigation-id="account-email"
			data-monster-option-navigation-label="Account"
			data-monster-option-navigation-sub-label="Email"
		>
			<input id="wizard-email" type="email" required>
		</section>
		<section
			data-monster-option-navigation-id="account-password"
			data-monster-option-navigation-label="Account"
			data-monster-option-navigation-sub-label="Password"
		>
			<input id="wizard-password" type="password" required>
		</section>
		<section
			data-monster-option-navigation-id="profile"
			data-monster-option-navigation-label="Profile"
		>
			<input id="wizard-name" type="text">
		</section>
	</monster-wizard>
`;

let Wizard;

describe("Wizard", function () {
	before(function (done) {
		initJSDOM().then(() => {
			import("element-internals-polyfill").catch((e) => done(e));

			let promises = [];

			if (!global.crypto) {
				promises.push(
					import("@peculiar/webcrypto").then((m) => {
						const Crypto = m.Crypto;
						global.crypto = new Crypto();
					}),
				);
			}

			promises.push(
				import("../../../../source/components/form/wizard.mjs").then((m) => {
					Wizard = m.Wizard;
				}),
			);

			Promise.all(promises)
				.then(() => done())
				.catch((e) => done(e));
		});
	});

	afterEach(() => {
		const mocks = document.getElementById("mocks");
		mocks.innerHTML = "";
	});

	it("should register monster-wizard", function () {
		expect(document.createElement("monster-wizard")).is.instanceof(Wizard);
	});

	it("should build grouped navigation from panel labels", async function () {
		const mocks = document.getElementById("mocks");
		mocks.innerHTML = html;

		await new Promise((resolve) => setTimeout(resolve, 30));

		const wizard = document.getElementById("wizard-under-test");
		expect(wizard.getCurrentIndex()).to.equal(0);

		const nav = wizard.shadowRoot.querySelector("monster-wizard-navigation");
		expect(nav).to.not.equal(null);

		const items = nav.querySelectorAll("ol.wizard-steps > li.step");
		expect(items.length).to.equal(2);
		expect(items[0].querySelectorAll("ul li").length).to.equal(2);
		expect(
			wizard.querySelector('[data-monster-option-navigation-id="account-email"]')
				.hidden,
		).to.equal(false);
		expect(
			wizard.querySelector(
				'[data-monster-option-navigation-id="account-password"]',
			).hidden,
		).to.equal(true);
	});

	it("should use panel-specific validation callbacks before moving forward", async function () {
		const mocks = document.getElementById("mocks");
		mocks.innerHTML = html;

		await new Promise((resolve) => setTimeout(resolve, 20));

		const wizard = document.getElementById("wizard-under-test");
		wizard.setOption("validation.native", false);
		wizard.setOption("validation.panels.account-email", () => false);

		const moved = await wizard.next();
		expect(moved).to.equal(false);
		expect(wizard.getCurrentIndex()).to.equal(0);

		wizard.setOption("validation.panels.account-email", () => true);
		const movedAfter = await wizard.next();
		expect(movedAfter).to.equal(true);
		expect(wizard.getCurrentIndex()).to.equal(1);
	});

	it("should block backward navigation when disabled", async function () {
		const mocks = document.getElementById("mocks");
		mocks.innerHTML = html;

		await new Promise((resolve) => setTimeout(resolve, 20));

		const wizard = document.getElementById("wizard-under-test");
		wizard.setOption("validation.native", false);
		await wizard.goTo(1, { force: true });
		wizard.setOption("features.allowBackNavigation", false);

		const moved = await wizard.previous();
		expect(moved).to.equal(false);
		expect(wizard.getCurrentIndex()).to.equal(1);
	});

	it("should complete navigation on submit", async function () {
		const mocks = document.getElementById("mocks");
		mocks.innerHTML = html;

		await new Promise((resolve) => setTimeout(resolve, 30));

		const wizard = document.getElementById("wizard-under-test");
		wizard.setOption("validation.native", false);
		await wizard.goTo(2, { force: true });

		const submitted = await wizard.submit();
		expect(submitted).to.equal(true);

		const navigation = wizard.shadowRoot.querySelector("monster-wizard-navigation");
		expect(navigation.getCurrentStepIndex()).to.equal(-1);
	});
});
