import { beforeEach, describe, expect, test } from "vitest";
import {
  ipFromHeaders,
  rateLimit,
  resetRateLimitForTests,
} from "@/lib/rate-limit";

beforeEach(() => {
  resetRateLimitForTests();
});

describe("rateLimit", () => {
  test("allows up to max within window", () => {
    for (let i = 0; i < 3; i++) {
      const r = rateLimit({ key: "a", max: 3, windowMs: 60_000, now: i * 100 });
      expect(r.ok).toBe(true);
    }
  });

  test("rejects the max+1 request", () => {
    for (let i = 0; i < 3; i++) {
      rateLimit({ key: "b", max: 3, windowMs: 60_000, now: i });
    }
    const r = rateLimit({ key: "b", max: 3, windowMs: 60_000, now: 10 });
    expect(r.ok).toBe(false);
    expect(r.remaining).toBe(0);
  });

  test("forgets entries older than the window", () => {
    rateLimit({ key: "c", max: 2, windowMs: 1000, now: 0 });
    rateLimit({ key: "c", max: 2, windowMs: 1000, now: 500 });
    const blocked = rateLimit({
      key: "c",
      max: 2,
      windowMs: 1000,
      now: 999,
    });
    expect(blocked.ok).toBe(false);

    const allowed = rateLimit({
      key: "c",
      max: 2,
      windowMs: 1000,
      now: 1500,
    });
    expect(allowed.ok).toBe(true);
  });

  test("keys are independent", () => {
    rateLimit({ key: "x", max: 1, windowMs: 60_000, now: 0 });
    rateLimit({ key: "x", max: 1, windowMs: 60_000, now: 100 });
    const y = rateLimit({ key: "y", max: 1, windowMs: 60_000, now: 200 });
    expect(y.ok).toBe(true);
  });
});

describe("ipFromHeaders", () => {
  test("prefers first x-forwarded-for", () => {
    const h = new Headers({ "x-forwarded-for": "1.2.3.4, 5.6.7.8" });
    expect(ipFromHeaders(h)).toBe("1.2.3.4");
  });

  test("falls back to x-real-ip", () => {
    const h = new Headers({ "x-real-ip": "9.9.9.9" });
    expect(ipFromHeaders(h)).toBe("9.9.9.9");
  });

  test("returns unknown when no header present", () => {
    expect(ipFromHeaders(new Headers())).toBe("unknown");
  });
});
