import { describe, expect, mock, test } from "bun:test";
import {
	getButtonOpeningTag,
	renderToolbarActionBoundary,
	registerAIToolbarMarkupHooks,
	renderToolbarMarkup,
} from "./helpers/ai-toolbar-test-helpers";

registerAIToolbarMarkupHooks();

const makeEvent = (id = "event-1") => ({
	id,
	title: "Event",
	start: "2026-04-22T09:00:00.000Z",
});

describe("AI toolbar state rendering", () => {
	test("unauthenticated users see the sign-in-required callout", async () => {
		const markup = await renderToolbarMarkup({ isAuthenticated: false });

		expect(markup).toContain("Sign in required to generate event drafts with AI");
		expect(markup).toContain(
			"Sign in to turn natural language or flyers into event drafts",
		);
	});

	test("admin-disabled state explains that AI is disabled by the administrator", async () => {
		const markup = await renderToolbarMarkup({
			adminAiEnabled: false,
			isAuthenticated: true,
		});

		expect(markup).toContain("AI integrations are unavailable");
		expect(markup).toContain(
			"AI integrations are currently disabled by the administrator.",
		);
	});

	test("browser-disabled state explains that AI was turned off from settings", async () => {
		const markup = await renderToolbarMarkup({
			adminAiEnabled: true,
			aiEnabled: false,
			isAuthenticated: true,
		});

		expect(markup).toContain("AI integrations are unavailable");
		expect(markup).toContain(
			"AI has been turned off in this browser from Settings.",
		);
	});

	test("summary panel renders the summary body, updated timestamp, and dismiss affordance", async () => {
		const markup = await renderToolbarMarkup({
			summary: "Three events need attention.",
			summaryUpdated: "Updated just now",
		});

		expect(markup).toContain("AI Summary");
		expect(markup).toContain("Three events need attention.");
		expect(markup).toContain("Updated just now");
		expect(markup).toContain("Dismiss AI summary");
	});

	test("pending state renders loading skeletons instead of the live composer", async () => {
		const markup = await renderToolbarMarkup({ isPending: true });

		expect(markup).toContain("h-[160px]");
		expect(markup).toContain("h-12");
		expect(markup).not.toContain("Type or paste event details...");
	});

	test("Summarize only appears when there are events to summarize", async () => {
		const emptyMarkup = await renderToolbarMarkup({ events: [] });
		const populatedMarkup = await renderToolbarMarkup({
			events: [makeEvent()],
		});

		expect(emptyMarkup).not.toContain("Summarize");
		expect(populatedMarkup).toContain("Summarize");
	});

	test("Generate event stays disabled while loading or when both prompt and images are absent", async () => {
		const emptyMarkup = await renderToolbarMarkup();
		const loadingMarkup = await renderToolbarMarkup({
			aiLoading: true,
			aiPrompt: "Draft a kickoff",
		});
		const promptMarkup = await renderToolbarMarkup({
			aiPrompt: "Draft a kickoff",
		});
		const imageMarkup = await renderToolbarMarkup({
			imagePreviews: ["blob:first"],
		});

		expect(getButtonOpeningTag(emptyMarkup, "Generate event")).toContain(
			' disabled=""',
		);
		expect(getButtonOpeningTag(loadingMarkup, "Generating...")).toContain(
			' disabled=""',
		);
		expect(getButtonOpeningTag(promptMarkup, "Generate event")).not.toContain(
			" disabled=",
		);
		expect(getButtonOpeningTag(imageMarkup, "Generate event")).not.toContain(
			" disabled=",
		);
	});

	test("Generate event button calls onAiCreate when the composer is actionable", async () => {
		const onAiCreate = mock();
		const actions = await renderToolbarActionBoundary({
			aiPrompt: "Draft a kickoff",
			onAiCreate,
		});

		actions.getButtonByLabel("Generate event").onClick?.({} as never);

		expect(onAiCreate).toHaveBeenCalledTimes(1);
	});

	test("AI unavailable state removes the composer so generate shortcuts are not exposed", async () => {
		const markup = await renderToolbarMarkup({ aiEnabled: false });

		expect(markup).toContain("AI integrations are unavailable");
		expect(markup).not.toContain("Type or paste event details...");
		expect(markup).not.toContain("Generate event");
	});

	test("example prompt buttons call onAiTemplateSelect with the selected prompt", async () => {
		const onAiTemplateSelectMock = mock();
		const actions = await renderToolbarActionBoundary({
			onAiTemplateSelect: onAiTemplateSelectMock,
		});
		const promptButton = actions.getButtonByLabel("Lunch with Maya next Thursday");

		promptButton.onClick?.({} as never);

		expect(onAiTemplateSelectMock).toHaveBeenCalledTimes(1);
		expect(onAiTemplateSelectMock).toHaveBeenCalledWith(
			"Lunch with Maya next Thursday at 12:30pm at Toma, remind me 30 minutes before.",
		);
	});

	test("Summarize button calls onAiSummarize when events are present", async () => {
		const onAiSummarizeMock = mock();
		const actions = await renderToolbarActionBoundary({
			events: [makeEvent()],
			onAiSummarize: onAiSummarizeMock,
		});

		actions
			.getButtonByLabel("Summarize")
			.onClick?.({} as never);

		expect(onAiSummarizeMock).toHaveBeenCalledTimes(1);
	});

	test("summary dismiss button calls onSummaryDismiss", async () => {
		const onSummaryDismissMock = mock();
		const actions = await renderToolbarActionBoundary({
			summary: "Three events need attention.",
			onSummaryDismiss: onSummaryDismissMock,
		});

		actions
			.getButtonByAriaLabel("Dismiss AI summary")
			.onClick?.({} as never);

		expect(onSummaryDismissMock).toHaveBeenCalledTimes(1);
	});

	test("remove image button calls onImageRemove with the preview index", async () => {
		const onImageRemoveMock = mock();
		const actions = await renderToolbarActionBoundary({
			imagePreviews: ["blob:first", "blob:second"],
			onImageRemove: onImageRemoveMock,
		});

		actions
			.getButtonByAriaLabel("Remove image 2")
			.onClick?.({} as never);

		expect(onImageRemoveMock).toHaveBeenCalledTimes(1);
		expect(onImageRemoveMock).toHaveBeenCalledWith(1);
	});
});
