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

import type { IAuthStorage } from "@/data/storage/auth";
import { LoginStatus } from "@/data/dto/auth";
import { Result } from "@/utils";

import { hasCompleteBusinessAuthSession } from "../auth_session";

function makeAuthStorageMock(input: {
  loginToken?: string | null;
  refreshToken?: string | null;
  refreshTokenError?: Error;
}): IAuthStorage {
  return {
    getLoginToken: vi.fn(async () => Result.ok(input.loginToken ?? null)),
    setLoginToken: vi.fn(async () => Result.ok(undefined)),
    hasLoginToken: vi.fn(async () => Result.ok(Boolean(input.loginToken))),
    clearLoginToken: vi.fn(async () => Result.ok(undefined)),
    getLoginProvider: vi.fn(async () => Result.ok(LoginStatus.Email)),
    setLoginProvider: vi.fn(async () => Result.ok(undefined)),
    clearLoginProvider: vi.fn(async () => Result.ok(undefined)),
    getGuestToken: vi.fn(async () => Result.ok(null)),
    setGuestToken: vi.fn(async () => Result.ok(undefined)),
    hasGuestToken: vi.fn(async () => Result.ok(false)),
    clearGuestToken: vi.fn(async () => Result.ok(undefined)),
    getDeviceId: vi.fn(async () => Result.ok(null)),
    setDeviceId: vi.fn(async () => Result.ok(undefined)),
    getRefreshToken: vi.fn(async () =>
      input.refreshTokenError
        ? Result.err(input.refreshTokenError)
        : Result.ok(input.refreshToken ?? null),
    ),
    setRefreshToken: vi.fn(async () => Result.ok(undefined)),
    clearRefreshToken: vi.fn(async () => Result.ok(undefined)),
    getFacebookId: vi.fn(async () => Result.ok(null)),
    setFacebookId: vi.fn(async () => Result.ok(undefined)),
    clearFacebookId: vi.fn(async () => Result.ok(undefined)),
    clearBusinessAuthData: vi.fn(async () => Result.ok(undefined)),
    clearAuthData: vi.fn(async () => Result.ok(undefined)),
  };
}

describe("auth session helpers", () => {
  it("treats a business session as complete when both tokens exist", async () => {
    await expect(
      hasCompleteBusinessAuthSession(
        makeAuthStorageMock({
          loginToken: "login-token",
          refreshToken: "refresh-token",
        }),
      ),
    ).resolves.toBe(true);
  });

  it("does not treat login token alone as a complete business session", async () => {
    await expect(
      hasCompleteBusinessAuthSession(
        makeAuthStorageMock({
          loginToken: "login-token",
          refreshToken: null,
        }),
      ),
    ).resolves.toBe(false);
  });

  it("does not restore a business session when refresh token cannot be read", async () => {
    await expect(
      hasCompleteBusinessAuthSession(
        makeAuthStorageMock({
          loginToken: "login-token",
          refreshTokenError: new Error("storage unavailable"),
        }),
      ),
    ).resolves.toBe(false);
  });
});
