import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest";
import { ApiError } from "@/lib/api";
import { LinkForm } from "./LinkForm";

const link = vi.fn();
vi.mock("@/lib/api", async () => {
    const actual = await vi.importActual<typeof import("@/lib/api")>("@/lib/api");
    return { ...actual, api: { ...actual.api, link: (...a: unknown[]) => link(...a) } };
});

const VALID = "6a0fe3f0-49d2-4aa1-967c-a3094b200b5d";

describe("LinkForm", () => {
    it("catches a malformed id before asking the server", async () => {
        render(<LinkForm onLinked={vi.fn()} />);
        await userEvent.type(screen.getByLabelText(/instance id/i), "not-a-uuid");
        await userEvent.click(screen.getByRole("button", { name: /link and issue/i }));

        expect(screen.getByText(/does not look like an instance id/i)).toBeInTheDocument();
        expect(link).not.toHaveBeenCalled();
    });

    it("lands the customer on their licence on success", async () => {
        const onLinked = vi.fn();
        link.mockResolvedValue({ instance_id: VALID });
        render(<LinkForm onLinked={onLinked} />);
        await userEvent.type(screen.getByLabelText(/instance id/i), VALID);
        await userEvent.click(screen.getByRole("button", { name: /link and issue/i }));

        await waitFor(() => expect(onLinked).toHaveBeenCalledWith(VALID));
    });

    it("shows the server's own message when the id is already linked", async () => {
        link.mockRejectedValue(
            new ApiError(409, "that instance ID is already linked to an account"),
        );
        render(<LinkForm onLinked={vi.fn()} />);
        await userEvent.type(screen.getByLabelText(/instance id/i), VALID);
        await userEvent.click(screen.getByRole("button", { name: /link and issue/i }));

        expect(await screen.findByText(/already linked to an account/i)).toBeInTheDocument();
    });
});
