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";
import { ResizeObserverMock } from "../../../util/resize-observer.mjs";

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

const global = getGlobal();

let ContextHelp;
let resolveClippingBoundaryElement;
let resolveParentPopperContentBoundary;

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

			if (!global.ResizeObserver) {
				global.ResizeObserver = ResizeObserverMock;
			}

			Promise.all([
				import("../../../../source/components/form/context-help.mjs"),
				import("../../../../source/components/form/util/floating-ui.mjs"),
			])
				.then(([contextHelpModule, floatingUiModule]) => {
					ContextHelp = contextHelpModule.ContextHelp;
					resolveClippingBoundaryElement =
						floatingUiModule.resolveClippingBoundaryElement;
					resolveParentPopperContentBoundary =
						floatingUiModule.resolveParentPopperContentBoundary;
					done();
				})
				.catch((e) => done(e));
		});
	});

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

	it("should resolve the nearest clipping parent across the shadow boundary", function (done) {
		let mocks = document.getElementById("mocks");
		const outer = document.createElement("div");
		const wrapper = document.createElement("div");
		const help = document.createElement("monster-context-help");

		outer.style.overflow = "visible";
		wrapper.style.overflow = "hidden";
		wrapper.appendChild(help);
		outer.appendChild(wrapper);
		mocks.appendChild(outer);
		help.innerHTML = "<p>Inline help</p>";

		setTimeout(() => {
			try {
				expect(help).to.be.instanceof(ContextHelp);

				const popper = help.shadowRoot.querySelector(
					'[data-monster-role="popper"]',
				);
				expect(popper).to.exist;
				expect(resolveClippingBoundaryElement(help, popper)).to.equal(wrapper);
				done();
			} catch (e) {
				done(e);
			}
		}, 0);
	});

	it("should default to visible content overflow", function (done) {
		let mocks = document.getElementById("mocks");
		const help = document.createElement("monster-context-help");
		help.innerHTML = "<p>Inline help</p>";
		mocks.appendChild(help);

		setTimeout(() => {
			try {
				const content = help.shadowRoot.querySelector('[part="content"]');
				expect(help.getOption("popper.contentOverflow")).to.equal("visible");
				expect(content.getAttribute("data-monster-overflow-mode")).to.equal(
					"visible",
				);
				done();
			} catch (e) {
				done(e);
			}
		}, 0);
	});

	it("should switch to fixed positioning inside a clipping container", function (done) {
		let mocks = document.getElementById("mocks");
		const wrapper = document.createElement("div");
		const help = document.createElement("monster-context-help");

		wrapper.style.overflow = "hidden";
		wrapper.appendChild(help);
		mocks.appendChild(wrapper);
		help.innerHTML = "<p>Inline help</p>";

		setTimeout(() => {
			try {
				help.showDialog();

				const popper = help.shadowRoot.querySelector(
					'[data-monster-role="popper"]',
				);
				expect(popper).to.exist;
				expect(popper.style.position).to.equal("fixed");
				done();
			} catch (e) {
				done(e);
			}
		}, 0);
	});

	it("should switch to fixed positioning inside a parent popper content wrapper with overflow both", function (done) {
		let mocks = document.getElementById("mocks");
		const host = document.createElement("div");
		const help = document.createElement("monster-context-help");

		mocks.appendChild(host);
		const shadowRoot = host.attachShadow({ mode: "open" });
		shadowRoot.innerHTML = `
			<div data-monster-role="popper">
				<div part="content"
					 data-monster-overflow-mode="both">
				</div>
			</div>
		`;
		shadowRoot.querySelector('[part="content"]').appendChild(help);
		help.innerHTML = "<p>Nested help</p>";

		setTimeout(() => {
			try {
				const control = help.shadowRoot.querySelector(
					'[data-monster-role="control"]',
				);
				const popper = help.shadowRoot.querySelector(
					'[data-monster-role="popper"]',
				);

				expect(
					resolveParentPopperContentBoundary(control, popper),
				).to.equal(shadowRoot.querySelector('[part="content"]'));

				const content = help.shadowRoot.querySelector('[part="content"]');
				expect(content.getAttribute("data-monster-overflow-mode")).to.equal(
					"both",
				);

				help.showDialog();
				expect(popper.style.position).to.equal("fixed");
				done();
			} catch (e) {
				done(e);
			}
		}, 0);
	});
});
