import { describe, expect, it } from "vitest";
import {
  readSessionExpiryEnabled,
  SESSION_RENEW_THRESHOLD_MS,
  shouldAttemptSlidingSessionRenew,
  shouldSuppressDevelopmentSessionRedirect,
  shouldAttemptUnlimitedSessionRenew,
  writeSessionExpiryEnabled,
} from "./sessionSliding";

function memoryStorage(initialValue: string | null = null) {
  let value = initialValue;
  return {
    getItem: (_key: string) => value,
    setItem: (_key: string, nextValue: string) => {
      value = nextValue;
    },
  };
}

describe("shouldAttemptSlidingSessionRenew", () => {
  const nowMs = 1_700_000_000_000;

  it("returns false when remaining time is above the 10 minute threshold", () => {
    expect(
      shouldAttemptSlidingSessionRenew({
        expiresAtSec: Math.floor(
          (nowMs + SESSION_RENEW_THRESHOLD_MS + 1_000) / 1000,
        ),
        nowMs,
        isEnabled: true,
        isAuthenticated: true,
        isLoading: false,
        isRenewInFlight: false,
        lastAttemptAtMs: 0,
      }),
    ).toBe(false);
  });

  it("returns true when remaining time is within the 10 minute threshold", () => {
    expect(
      shouldAttemptSlidingSessionRenew({
        expiresAtSec: Math.floor(
          (nowMs + SESSION_RENEW_THRESHOLD_MS - 1_000) / 1000,
        ),
        nowMs,
        isEnabled: true,
        isAuthenticated: true,
        isLoading: false,
        isRenewInFlight: false,
        lastAttemptAtMs: 0,
      }),
    ).toBe(true);
  });

  it("returns false when automatic renewal is disabled", () => {
    expect(
      shouldAttemptSlidingSessionRenew({
        expiresAtSec: Math.floor(
          (nowMs + SESSION_RENEW_THRESHOLD_MS - 1_000) / 1000,
        ),
        nowMs,
        isEnabled: false,
        isAuthenticated: true,
        isLoading: false,
        isRenewInFlight: false,
        lastAttemptAtMs: 0,
      }),
    ).toBe(false);
  });

  it("returns false when the last renew attempt is still within the throttle window", () => {
    expect(
      shouldAttemptSlidingSessionRenew({
        expiresAtSec: Math.floor(
          (nowMs + SESSION_RENEW_THRESHOLD_MS - 1_000) / 1000,
        ),
        nowMs,
        isEnabled: true,
        isAuthenticated: true,
        isLoading: false,
        isRenewInFlight: false,
        lastAttemptAtMs: nowMs - 10_000,
      }),
    ).toBe(false);
  });
});

describe("shouldAttemptUnlimitedSessionRenew", () => {
  const nowMs = 1_700_000_000_000;

  it("returns false when unlimited mode is not active", () => {
    expect(
      shouldAttemptUnlimitedSessionRenew({
        expiresAtSec: Math.floor(
          (nowMs + SESSION_RENEW_THRESHOLD_MS - 1_000) / 1000,
        ),
        nowMs,
        isEnabled: true,
        isAuthenticated: true,
        isLoading: false,
        isRenewInFlight: false,
        lastAttemptAtMs: 0,
      }),
    ).toBe(false);
  });

  it("returns true near expiry when session expiry management is disabled", () => {
    expect(
      shouldAttemptUnlimitedSessionRenew({
        expiresAtSec: Math.floor(
          (nowMs + SESSION_RENEW_THRESHOLD_MS - 1_000) / 1000,
        ),
        nowMs,
        isEnabled: false,
        isAuthenticated: true,
        isLoading: false,
        isRenewInFlight: false,
        lastAttemptAtMs: 0,
      }),
    ).toBe(true);
  });

  it("returns false when the token still has enough remaining lifetime", () => {
    expect(
      shouldAttemptUnlimitedSessionRenew({
        expiresAtSec: Math.floor(
          (nowMs + SESSION_RENEW_THRESHOLD_MS + 1_000) / 1000,
        ),
        nowMs,
        isEnabled: false,
        isAuthenticated: true,
        isLoading: false,
        isRenewInFlight: false,
        lastAttemptAtMs: 0,
      }),
    ).toBe(false);
  });
});

describe("session expiry development preference", () => {
  it("defaults session expiry management off in development when no preference is stored", () => {
    expect(
      readSessionExpiryEnabled({
        defaultEnabled: false,
        storage: memoryStorage(null),
      }),
    ).toBe(false);
  });

  it("keeps explicit stored preference over the development default", () => {
    const storage = memoryStorage(null);

    writeSessionExpiryEnabled(true, storage);

    expect(
      readSessionExpiryEnabled({
        defaultEnabled: false,
        storage,
      }),
    ).toBe(true);
  });

  it("suppresses login redirects only in development with disabled session expiry management", () => {
    expect(
      shouldSuppressDevelopmentSessionRedirect({
        appMode: "development",
        storage: memoryStorage(null),
      }),
    ).toBe(true);

    expect(
      shouldSuppressDevelopmentSessionRedirect({
        appMode: "production",
        storage: memoryStorage(null),
      }),
    ).toBe(false);
  });
});
