import * as chai from "chai";
import { initJSDOM } from "../../../util/jsdom.mjs";

const expect = chai.expect;

describe("ConfigManager storage adapter", function () {
	before(function (done) {
		initJSDOM().then(() => {
			import("../../../../source/components/host/config-manager.mjs")
				.then(() => {
					done();
				})
				.catch((e) => done(e));
		});
	});

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

	it("uses an external storage adapter for managed keys", function (done) {
		const config = document.createElement("monster-config-manager");
		const values = new Map();
		const calls = [];

		config.setStorageAdapter({
			managesConfigKey: (key) => key.startsWith("server_"),
			hasConfig: (key) => values.has(key),
			getConfig: (key) => values.get(key),
			setConfig: (key, value) => {
				calls.push(["set", key, value]);
				values.set(key, value);
			},
			deleteConfig: (key) => {
				calls.push(["delete", key]);
				values.delete(key);
			},
		});

		config.setOption("storage.serverAuthoritative", true);

		config
			.setConfig("server_table_filter", { visible: true })
			.then(() => config.hasConfig("server_table_filter"))
			.then((hasConfig) => {
				expect(hasConfig).to.equal(true);
				return config.getConfig("server_table_filter");
			})
			.then((value) => {
				expect(value).to.deep.equal({ visible: true });
				expect(calls).to.deep.equal([
					["set", "server_table_filter", { visible: true }],
				]);
				return config.deleteConfig("server_table_filter");
			})
			.then(() => {
				expect(values.has("server_table_filter")).to.equal(false);
				done();
			})
			.catch(done);
	});

	it("does not fall back to IndexedDB for server-authoritative adapter keys", function (done) {
		const config = document.createElement("monster-config-manager");

		config.setStorageAdapter({
			managesConfigKey: (key) => key === "server_key",
			setConfig: () => Promise.reject(new Error("server unavailable")),
		});
		config.setOption("storage.serverAuthoritative", true);
		config.setOption("indexDB.objectStore.name", "missing-store");

		config
			.setConfig("server_key", { value: 1 })
			.then(() => done(new Error("setConfig should reject")))
			.catch((error) => {
				try {
					expect(error.message).to.equal("server unavailable");
					done();
				} catch (e) {
					done(e);
				}
			});
	});
});
