import { beforeEach, describe, expect, it, vi } from "vitest";
import { __featureFlagTesting } from "./splitio-react-replacement";

const {
  createFeatureFlagClient,
  getNextScheduleRefreshDelay,
  getLocalStorageKey,
  isFeatureFlagChangeRelevant,
  normalizeFlagValue,
  readCachedFeatureFlags,
  writeCachedFeatureFlags
} = __featureFlagTesting;

beforeEach(() => {
  window.localStorage.clear();
  vi.useRealTimers();
});

describe("splitio-react-replacement feature flag normalization", () => {
  it("returns off for unknown or null values", () => {
    expect(normalizeFlagValue(null)).toEqual({ treatment: "off", config: null });
    expect(normalizeFlagValue(undefined)).toEqual({ treatment: "off", config: null });
  });

  it("normalizes primitive values into Split-like treatments", () => {
    expect(normalizeFlagValue(true)).toEqual({ treatment: "on", config: null });
    expect(normalizeFlagValue(false)).toEqual({ treatment: "off", config: null });
    expect(normalizeFlagValue(1)).toEqual({ treatment: "on", config: null });
    expect(normalizeFlagValue(0)).toEqual({ treatment: "off", config: null });
    expect(normalizeFlagValue("true")).toEqual({ treatment: "on", config: null });
    expect(normalizeFlagValue("false")).toEqual({ treatment: "off", config: null });
    expect(normalizeFlagValue("variant-a")).toEqual({ treatment: "variant-a", config: null });
  });

  it("preserves custom treatments and parses JSON config strings", () => {
    expect(
      normalizeFlagValue({
        treatment: "demo",
        config: "{\"limit\":25}"
      })
    ).toEqual({
      treatment: "demo",
      config: { limit: 25 }
    });
  });

  it("respects activeDate and deactiveDate windows", () => {
    vi.useFakeTimers();
    vi.setSystemTime(new Date("2026-05-19T15:00:00.000Z"));

    expect(
      normalizeFlagValue({
        treatment: "on",
        activeDate: "2026-05-19T14:59:00.000Z",
        deactiveDate: "2026-05-19T15:01:00.000Z"
      })
    ).toEqual({ treatment: "on", config: null });

    expect(
      normalizeFlagValue({
        treatment: "on",
        activeDate: "2026-05-19T15:01:00.000Z"
      })
    ).toEqual({ treatment: "off", config: null });

    expect(
      normalizeFlagValue({
        treatment: "on",
        deactiveDate: "2026-05-19T15:00:00.000Z"
      })
    ).toEqual({ treatment: "off", config: null });

    vi.useRealTimers();
  });
});

describe("splitio-react-replacement feature flag client", () => {
  it("uses backend flags", () => {
    const client = createFeatureFlagClient({
      bodyshop: {
        imexshopid: "APPLE"
      },
      backendFlags: {
        Enhanced_Payroll: { treatment: "on" }
      }
    });

    expect(client.getTreatment("Enhanced_Payroll")).toBe("on");
  });

  it("ignores old bodyshop feature JSON fallback values", () => {
    const client = createFeatureFlagClient({
      bodyshop: {
        imexshopid: "APPLE",
        features: {
          featureFlags: {
            Enhanced_Payroll: { treatment: "on" }
          }
        }
      },
      backendFlags: {}
    });

    expect(client.getTreatment("Enhanced_Payroll")).toBe("off");
  });

  it("returns off for flags that are not present in any source", () => {
    const client = createFeatureFlagClient({
      bodyshop: { imexshopid: "APPLE", features: {} },
      backendFlags: {}
    });

    expect(client.getTreatment("Missing_Flag")).toBe("off");
  });

  it("uses a bodyshop-scoped browser cache key", () => {
    expect(getLocalStorageKey("shop-1")).toBe("bodyshop-feature-flags:shop-1");
  });

  it("stores and reads last-known backend flags from browser storage", () => {
    vi.useFakeTimers();
    vi.setSystemTime(new Date("2026-05-19T15:00:00.000Z"));

    writeCachedFeatureFlags("shop-1", {
      Enhanced_Payroll: { treatment: "on", config: null }
    });

    expect(readCachedFeatureFlags("shop-1")).toEqual({
      Enhanced_Payroll: { treatment: "on", config: null }
    });
  });

  it("ignores expired browser cached flags", () => {
    vi.useFakeTimers();
    vi.setSystemTime(new Date("2026-05-19T15:00:00.000Z"));

    writeCachedFeatureFlags("shop-1", {
      Enhanced_Payroll: { treatment: "on", config: null }
    });

    expect(readCachedFeatureFlags("shop-1", Date.parse("2026-05-20T15:00:01.000Z"))).toBeNull();
  });
});

describe("splitio-react-replacement live refresh helpers", () => {
  it("matches global and bodyshop-scoped socket changes", () => {
    expect(isFeatureFlagChangeRelevant({ scope: "global" }, "shop-1")).toBe(true);
    expect(isFeatureFlagChangeRelevant({ bodyshopId: "shop-1", scope: "bodyshop" }, "shop-1")).toBe(true);
    expect(isFeatureFlagChangeRelevant({ bodyshopId: "shop-2", scope: "bodyshop" }, "shop-1")).toBe(false);
  });

  it("finds the next active/deactive date boundary that needs a refresh", () => {
    const now = Date.parse("2026-05-19T15:00:00.000Z");

    expect(
      getNextScheduleRefreshDelay(
        {
          Demo: { treatment: "on", activeDate: "2026-05-19T15:05:00.000Z" },
          Expiring: { treatment: "on", deactiveDate: "2026-05-19T15:02:00.000Z" },
          Expired: { treatment: "on", deactiveDate: "2026-05-19T14:59:00.000Z" }
        },
        now
      )
    ).toBe(120050);
  });
});
