import type { Response } from "express";
import type { Logger } from "nestjs-pino";
import { CsrfController } from "./csrf.controller";
import type { AuthenticatedRequest } from "./csrf.controller";
import type { CsrfService, CsrfTokenData } from "../services/csrf.service";

const createMockResponse = () => {
  const cookie = jest.fn();
  const json = jest.fn();
  return {
    cookie,
    json,
  } as unknown as Response;
};

describe("CsrfController", () => {
  const csrfToken: CsrfTokenData = {
    token: "token-value",
    secret: "secret-value",
    expiresAt: new Date(),
  };

  const makeController = (overrides: Partial<CsrfService> = {}) => {
    const csrfService: Partial<CsrfService> = {
      generateToken: jest.fn().mockReturnValue(csrfToken),
      invalidateUserTokens: jest.fn(),
      ...overrides,
    };

    const logger = { debug: jest.fn() } as unknown as Logger;
    return {
      controller: new CsrfController(csrfService as CsrfService, logger),
      csrfService,
    };
  };

  it("passes session and user identifiers to generateToken in the correct argument order", () => {
    const { controller, csrfService } = makeController();
    const res = createMockResponse();

    const req = {
      user: { id: "user-123", sessionId: "session-456" },
      cookies: {},
      get: jest.fn(),
      ip: "127.0.0.1",
    } as unknown as AuthenticatedRequest;

    controller.getCsrfToken(req, res);

    expect(csrfService.generateToken).toHaveBeenCalledWith(undefined, "session-456", "user-123");
  });

  it("defaults to anonymous user during refresh and still forwards identifiers correctly", () => {
    const { controller, csrfService } = makeController();
    const res = createMockResponse();

    const req = {
      cookies: { "connect.sid": "cookie-session" },
      get: jest.fn(),
      ip: "127.0.0.1",
    } as unknown as AuthenticatedRequest;

    controller.refreshCsrfToken(req, res);

    expect(csrfService.generateToken).toHaveBeenCalledWith(
      undefined,
      "cookie-session",
      "anonymous"
    );
  });
});
