import { beforeEach, describe, expect, it, vi } from "vitest";

const { mockOptima, mockRedirect } = vi.hoisted(() => ({
  mockOptima: {
    user: {
      awaitAuthCallback: vi.fn(),
    },
  },
  mockRedirect: vi.fn((status: number, location: string) => {
    throw { status, location };
  }),
}));

vi.mock("$lib", () => ({ optima: mockOptima }));
vi.mock("@sveltejs/kit", () => ({
  redirect: mockRedirect,
  // Actions type is needed
  Actions: {},
}));

import { actions } from "./+page.server";

describe("(auth)/login +page.server.ts", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe("login action", () => {
    it("sets cookies and redirects on successful auth callback", async () => {
      mockOptima.user.awaitAuthCallback.mockResolvedValueOnce({
        accessToken: "access-tok",
        refreshToken: "refresh-tok",
      });

      const setCookie = vi.fn();
      const formData = {
        get: vi.fn((key: string) => {
          if (key === "callbackKey") return "cb-123";
          return null;
        }),
      };

      await expect(
        actions.login({
          request: {
            formData: vi.fn().mockResolvedValue(formData),
          },
          cookies: {
            set: setCookie,
          },
        } as any),
      ).rejects.toEqual(
        expect.objectContaining({ status: 303, location: "/" }),
      );

      expect(mockOptima.user.awaitAuthCallback).toHaveBeenCalledWith("cb-123");
      expect(setCookie).toHaveBeenCalledWith("accessToken", "access-tok", {
        httpOnly: true,
        path: "/",
      });
      expect(setCookie).toHaveBeenCalledWith("refreshToken", "refresh-tok", {
        httpOnly: true,
        path: "/",
      });
    });

    it("propagates errors from awaitAuthCallback", async () => {
      mockOptima.user.awaitAuthCallback.mockRejectedValueOnce(
        new Error("Timed out"),
      );

      const formData = {
        get: vi.fn(() => "cb-123"),
      };

      await expect(
        actions.login({
          request: {
            formData: vi.fn().mockResolvedValue(formData),
          },
          cookies: { set: vi.fn() },
        } as any),
      ).rejects.toThrow("Timed out");
    });
  });
});
