import { describe, expect, it } from "vitest";
import {
  signOAuthState,
  signSession,
  verifyOAuthState,
  verifySession,
} from "../../src/admin/auth/session.js";
import { sanitizeReturnTo } from "../../src/admin/routes/authRoutes.js";

const SECRET = "test-session-secret-not-for-production";

describe("session cookie signing", () => {
  it("round-trips a valid session", () => {
    const token = signSession(
      { userId: "u1", feishuOpenId: "ou_1" },
      SECRET,
      3600,
      1_700_000_000,
    );
    const payload = verifySession(token, SECRET, 1_700_000_100);
    expect(payload).toEqual({
      userId: "u1",
      feishuOpenId: "ou_1",
      iat: 1_700_000_000,
      exp: 1_700_003_600,
    });
  });

  it("rejects tampered tokens", () => {
    const token = signSession({ userId: "u1", feishuOpenId: "ou_1" }, SECRET);
    const [body] = token.split(".");
    expect(verifySession(`${body}.deadbeef`, SECRET)).toBeNull();
  });

  it("rejects expired sessions", () => {
    const token = signSession(
      { userId: "u1", feishuOpenId: "ou_1" },
      SECRET,
      10,
      1_700_000_000,
    );
    expect(verifySession(token, SECRET, 1_700_000_011)).toBeNull();
  });

  it("rejects wrong secret", () => {
    const token = signSession({ userId: "u1", feishuOpenId: "ou_1" }, SECRET);
    expect(verifySession(token, "other-secret")).toBeNull();
  });

  it("round-trips a connection-scoped identity", () => {
    const token = signSession({
      userId: "u-scoped",
      feishuIdentityId: "identity-1",
      feishuConnectionId: "connection-1",
      feishuOrganizationId: "organization-1",
    }, SECRET, 3600, 1_700_000_000);
    expect(verifySession(token, SECRET, 1_700_000_100)).toEqual({
      userId: "u-scoped",
      feishuIdentityId: "identity-1",
      feishuConnectionId: "connection-1",
      feishuOrganizationId: "organization-1",
      iat: 1_700_000_000,
      exp: 1_700_003_600,
    });
  });
});

describe("oauth state signing", () => {
  it("round-trips state with returnTo", () => {
    const token = signOAuthState(
      { nonce: "abc", returnTo: "/admin" },
      SECRET,
      600,
      1_700_000_000,
    );
    expect(verifyOAuthState(token, SECRET, 1_700_000_100)).toEqual({
      nonce: "abc",
      returnTo: "/admin",
      exp: 1_700_000_600,
    });
  });

  it("binds state to an Organization and connection as one inseparable scope", () => {
    const token = signOAuthState({
      nonce: "scoped",
      returnTo: "/admin",
      organizationId: "org-acme",
      connectionId: "connection-acme",
    }, SECRET, 600, 1_700_000_000);
    expect(verifyOAuthState(token, SECRET, 1_700_000_100)).toEqual({
      nonce: "scoped",
      returnTo: "/admin",
      organizationId: "org-acme",
      connectionId: "connection-acme",
      exp: 1_700_000_600,
    });
  });
});

describe("sanitizeReturnTo", () => {
  it("allows admin paths and rewrites legacy org slug prefixes", () => {
    expect(sanitizeReturnTo("/admin")).toBe("/admin");
    expect(sanitizeReturnTo("/admin/usage")).toBe("/admin/usage");
    expect(sanitizeReturnTo("/admin/org/acme")).toBe("/admin");
    expect(sanitizeReturnTo("/admin/org/acme/usage")).toBe("/admin/usage");
  });

  it("blocks open redirects", () => {
    expect(sanitizeReturnTo("https://evil.example/")).toBe("/admin");
    expect(sanitizeReturnTo("//evil.example")).toBe("/admin");
    expect(sanitizeReturnTo("/api/me")).toBe("/admin");
    expect(sanitizeReturnTo("")).toBe("/admin");
  });
});
