import "@testing-library/jest-dom/vitest";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { MemoryRouter } from "react-router-dom";
import { beforeEach, describe, expect, it, vi } from "vitest";

import { HomePage } from "./DashboardPage";
import { SessionsProvider } from "../state/sessions";

const mockDashboard = vi.fn();
const mockSessions = vi.fn();
const mockProjects = vi.fn();
const mockRepos = vi.fn();

vi.mock("../api/dashboard", () => ({
	getDashboardSummary: (...args: unknown[]) => mockDashboard(...args),
}));

vi.mock("../api/sessions", () => ({
	getUserSessions: (...args: unknown[]) => mockSessions(...args),
	createInstance: vi.fn(),
	startInstance: vi.fn(),
	stopInstance: vi.fn(),
	deleteInstance: vi.fn(),
	recreateInstanceTunnel: vi.fn(),
}));

vi.mock("../api/projects", () => ({
	listProjects: (...args: unknown[]) => mockProjects(...args),
}));

vi.mock("../api/git-repositories", () => ({
	listRepositories: (...args: unknown[]) => mockRepos(...args),
}));

vi.mock("../api/tool-types", () => ({
	listToolTypes: vi.fn().mockResolvedValue([]),
}));

describe("HomePage", () => {
	beforeEach(() => {
		mockDashboard.mockReset();
		mockSessions.mockReset();
		mockProjects.mockReset();
		mockRepos.mockReset();
	});

	it("shows overview sections", async () => {
		mockDashboard.mockResolvedValue({
			projects: 1,
			repositories: 2,
			sshKeys: 3,
			recentActivity: [],
		});
		mockSessions.mockResolvedValue([]);
		mockProjects.mockResolvedValue([]);
		mockRepos.mockResolvedValue([]);

		render(
			<MemoryRouter>
				<SessionsProvider>
					<HomePage />
				</SessionsProvider>
			</MemoryRouter>,
		);

		expect(screen.getByText("Loading overview...")).toBeInTheDocument();
		await waitFor(() => {
			expect(screen.getAllByText("Open sessions").length).toBeGreaterThan(0);
			expect(screen.getByText("Workspaces")).toBeInTheDocument();
		});
	});

	it("shows retry action when home load fails", async () => {
		mockDashboard.mockRejectedValueOnce(new Error("failed"));
		mockSessions.mockRejectedValueOnce(new Error("failed"));
		mockProjects.mockRejectedValueOnce(new Error("failed"));

		render(
			<MemoryRouter>
				<SessionsProvider>
					<HomePage />
				</SessionsProvider>
			</MemoryRouter>,
		);

		await waitFor(() => {
			expect(
				screen.getByText("Unable to load your workspace overview."),
			).toBeInTheDocument();
		});

		fireEvent.click(screen.getAllByRole("button", { name: "Retry" })[0]);
	});
});
