/* @vitest-environment node */

import { describe, it, expect, vi, afterEach } from "vitest";
import { writeTextToClipboard } from "./clipboard.js";

function createDocumentStub({ copyResult = true } = {}) {
	const textarea = {
		value: "",
		style: {},
		setAttribute: vi.fn(),
		focus: vi.fn(),
		select: vi.fn(),
		setSelectionRange: vi.fn(),
		remove: vi.fn(),
	};

	const documentStub = {
		createElement: vi.fn().mockReturnValue(textarea),
		body: {
			appendChild: vi.fn(),
		},
		execCommand: vi.fn().mockReturnValue(copyResult),
	};

	return { documentStub, textarea };
}

describe("lib/frontend/ui/clipboard", () => {
	afterEach(() => {
		vi.unstubAllGlobals();
		vi.restoreAllMocks();
	});

	it("uses navigator.clipboard when available", async () => {
		const writeText = vi.fn().mockResolvedValue(undefined);
		vi.stubGlobal("navigator", {
			clipboard: { writeText },
		});

		const { documentStub } = createDocumentStub({ copyResult: true });
		vi.stubGlobal("document", documentStub);

		const result = await writeTextToClipboard("secret");

		expect(writeText).toHaveBeenCalledWith("secret");
		expect(documentStub.execCommand).not.toHaveBeenCalled();
		expect(result).toEqual({ ok: true, method: "clipboard" });
	});

	it("falls back to execCommand when Clipboard API is unavailable", async () => {
		vi.stubGlobal("navigator", {});
		const { documentStub, textarea } = createDocumentStub({ copyResult: true });
		vi.stubGlobal("document", documentStub);

		const result = await writeTextToClipboard("secret");

		expect(documentStub.createElement).toHaveBeenCalledWith("textarea");
		expect(documentStub.body.appendChild).toHaveBeenCalledWith(textarea);
		expect(documentStub.execCommand).toHaveBeenCalledWith("copy");
		expect(textarea.remove).toHaveBeenCalledTimes(1);
		expect(result).toEqual({ ok: true, method: "execCommand" });
	});

	it("falls back to execCommand when Clipboard API throws", async () => {
		const writeText = vi.fn().mockRejectedValue(new Error("not allowed"));
		vi.stubGlobal("navigator", {
			clipboard: { writeText },
		});

		const { documentStub } = createDocumentStub({ copyResult: true });
		vi.stubGlobal("document", documentStub);

		const result = await writeTextToClipboard("secret");

		expect(writeText).toHaveBeenCalledWith("secret");
		expect(documentStub.execCommand).toHaveBeenCalledWith("copy");
		expect(result).toEqual({ ok: true, method: "execCommand" });
	});

	it("returns ok=false when no copy mechanism is available", async () => {
		vi.stubGlobal("navigator", {});
		vi.stubGlobal("document", undefined);

		const result = await writeTextToClipboard("secret");

		expect(result).toEqual({ ok: false, method: null });
	});
});

