import {
	render,
	screen,
	fireEvent,
	waitFor,
	RenderResult,
} from "@testing-library/react";
import { vi } from "vitest";
import SignIn from "./sign-in.view";
import { ApiContext } from "../../context";
import { SignInPageApi } from "../../types/shared-types";

describe("SignIn", () => {
	const mockSignIn = vi.fn();
	const mockCancelSignIn = vi.fn();

	const mockApiContext: SignInPageApi = {
		signIn: mockSignIn,
		cancelSignIn: mockCancelSignIn,
		executeOnboardingStep: vi.fn(),
		colorize: vi.fn(),
		getOnboardingStepState: vi.fn(),
		getOnboardingStates: vi.fn(),
		startOnboarding: vi.fn(),
		completeOnboarding: vi.fn(),
		close: vi.fn(),
		needsSignIn: vi.fn(),
		needsOnboarding: vi.fn(),
	};

	beforeEach(() => {
		mockSignIn.mockReset();
		mockCancelSignIn.mockReset();
	});

	const renderSignIn = (): RenderResult => {
		return render(
			<ApiContext.Provider value={mockApiContext}>
				<SignIn
					themeType="dark"
					onSignInComplete={() => Promise.resolve()}
				/>
			</ApiContext.Provider>
		);
	};

	it("renders the sign in page with logo and sign in button", () => {
		renderSignIn();
		// Portal mode shows a single "Sign in" button
		expect(screen.getByRole("button", { name: /Sign in/i })).toBeInTheDocument();
		// Welcome message is shown
		expect(screen.getByText(/An agentic IDE that helps you do your best work/i)).toBeInTheDocument();
	});

	it("handles portal sign in flow successfully", async () => {
		mockSignIn.mockResolvedValueOnce(undefined);
		renderSignIn();

		const signInButton = screen.getByRole("button", { name: /Sign in/i });
		fireEvent.click(signInButton);

		// Should call signIn with portal auth method
		expect(mockSignIn).toHaveBeenCalledWith({ authMethod: "portal" });
	});

	it("handles sign in error state", async () => {
		mockSignIn.mockRejectedValueOnce(new Error("Auth failed"));
		renderSignIn();

		const signInButton = screen.getByRole("button", { name: /Sign in/i });
		fireEvent.click(signInButton);

		await waitFor(() => {
			expect(screen.getByText(/error/i)).toBeInTheDocument();
		});
	});

	it("prevents multiple sign in attempts while pending", () => {
		mockSignIn.mockImplementation(() => new Promise(() => {})); // Never resolves
		renderSignIn();

		const signInButton = screen.getByRole("button", { name: /Sign in/i });
		fireEvent.click(signInButton);
		fireEvent.click(signInButton); // Second click should be ignored

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

	it("shows cancel button during pending state", () => {
		mockSignIn.mockImplementation(() => new Promise(() => {})); // Never resolves
		renderSignIn();

		const signInButton = screen.getByRole("button", { name: /Sign in/i });
		fireEvent.click(signInButton);

		// Should show cancel button during pending
		expect(screen.getByRole("button", { name: /Cancel/i })).toBeInTheDocument();
	});

	it("calls cancelSignIn when cancel button is clicked", () => {
		mockSignIn.mockImplementation(() => new Promise(() => {})); // Never resolves
		renderSignIn();

		const signInButton = screen.getByRole("button", { name: /Sign in/i });
		fireEvent.click(signInButton);

		const cancelButton = screen.getByRole("button", { name: /Cancel/i });
		fireEvent.click(cancelButton);

		expect(mockCancelSignIn).toHaveBeenCalled();
	});
});
