/**
 * Authentication Test Helpers
 *
 * Utilities for testing dual authentication system:
 * 1. NextAuth sessions (Google OAuth, password login)
 * 2. Custom auth_token cookies (OTP login)
 *
 * @module __tests__/helpers/auth-test-helpers
 */

import { NextRequest } from "next/server";

/**
 * Mock NextAuth session data
 */
export interface MockSession {
  user: {
    id: string;
    email: string;
    name?: string;
    stripeCustomerId?: string;
  };
  expires: string;
}

/**
 * Create mock NextAuth session for testing
 *
 * @param userId - User ID
 * @param email - User email
 * @param options - Optional user data
 * @returns Mock NextAuth session
 *
 * @example
 * ```typescript
 * const session = createMockNextAuthSession(
 *   'user-123',
 *   'test@example.com',
 *   { name: 'Test User', stripeCustomerId: 'cus_123' }
 * );
 * ```
 */
export function createMockNextAuthSession(
  userId: string,
  email: string,
  options?: {
    name?: string;
    stripeCustomerId?: string;
  },
): MockSession {
  return {
    user: {
      id: userId,
      email,
      name: options?.name,
      stripeCustomerId: options?.stripeCustomerId,
    },
    expires: new Date(Date.now() + 7200000).toISOString(), // 2 hours
  };
}

/**
 * Create auth_token cookie value (OTP login method)
 *
 * @param userId - User ID
 * @param email - User email
 * @param fullName - User full name
 * @returns Base64-encoded auth_token value
 *
 * @example
 * ```typescript
 * const authToken = createAuthTokenCookie('user-123', 'test@example.com', 'Test User');
 * // Use in cookie: auth_token={authToken}
 * ```
 */
export function createAuthTokenCookie(
  userId: string,
  email: string,
  fullName?: string,
): string {
  const tokenData = {
    userId,
    email,
    fullName: fullName || email.split("@")[0],
    timestamp: Date.now(),
  };

  return Buffer.from(JSON.stringify(tokenData)).toString("base64");
}

/**
 * Create mock NextRequest with auth_token cookie
 *
 * @param userId - User ID
 * @param email - User email
 * @param options - Optional request options
 * @returns Mock NextRequest with auth_token cookie
 *
 * @example
 * ```typescript
 * const request = createMockRequestWithAuthToken('user-123', 'test@example.com');
 * // Use in API route tests
 * ```
 */
export function createMockRequestWithAuthToken(
  userId: string,
  email: string,
  options?: {
    fullName?: string;
    url?: string;
    method?: string;
  },
): any {
  const authToken = createAuthTokenCookie(userId, email, options?.fullName);
  const url = options?.url || "http://localhost:9000/api/test";
  const method = options?.method || "GET";

  // Return mock object with minimal NextRequest interface
  return {
    url,
    method,
    cookies: {
      get: (name: string) => {
        if (name === "auth_token") {
          return { name: "auth_token", value: authToken };
        }
        return undefined;
      },
    },
    headers: {
      get: () => null,
    },
  };
}

/**
 * Mock auth function that returns a session
 *
 * @param session - Session to return (null for unauthenticated)
 * @returns Auth function
 *
 * @example
 * ```typescript
 * const session = createMockNextAuthSession('user-123', 'test@example.com');
 * const authFn = createMockAuthFunction(session);
 * const userEmail = await getAuthenticatedEmail(request, authFn);
 * ```
 */
export function createMockAuthFunction(session: MockSession | null) {
  return async () => session;
}

/**
 * Create mock request without any authentication
 *
 * @param url - Request URL
 * @param method - HTTP method
 * @returns Mock NextRequest with no auth
 */
export function createMockRequestNoAuth(
  url: string = "http://localhost:9000/api/test",
  method: string = "GET",
): any {
  // Return mock object with minimal NextRequest interface
  return {
    url,
    method,
    cookies: {
      get: () => undefined,
    },
    headers: {
      get: () => null,
    },
  };
}

/**
 * Test data: Common test user
 */
export const TEST_USER = {
  id: "test-user-123",
  email: "test@example.com",
  name: "Test User",
  stripeCustomerId: "cus_test123",
};

/**
 * Test data: User with OTP login
 */
export const OTP_USER = {
  id: "otp-user-456",
  email: "otp@example.com",
  name: "OTP Test User",
  stripeCustomerId: "cus_otp456",
};

/**
 * Assert helpers for authentication tests
 */
export const authAssertions = {
  /**
   * Assert that API endpoint accepts NextAuth session
   */
  expectNextAuthAccepted: async (
    apiHandler: (req: NextRequest) => Promise<Response>,
    userId: string,
    email: string,
  ) => {
    const session = createMockNextAuthSession(userId, email, {
      stripeCustomerId: "cus_test123",
    });
    const authFn = createMockAuthFunction(session);
    const request = createMockRequestNoAuth();

    // Mock auth() to return session
    const response = await apiHandler(request);
    return response;
  },

  /**
   * Assert that API endpoint accepts auth_token cookie
   */
  expectAuthTokenAccepted: async (
    apiHandler: (req: NextRequest) => Promise<Response>,
    userId: string,
    email: string,
  ) => {
    const request = createMockRequestWithAuthToken(userId, email);
    const response = await apiHandler(request);
    return response;
  },

  /**
   * Assert that API endpoint rejects unauthenticated requests
   */
  expectUnauthorized: async (
    apiHandler: (req: NextRequest) => Promise<Response>,
  ) => {
    const request = createMockRequestNoAuth();
    const response = await apiHandler(request);
    return response;
  },
};

// Dummy test to satisfy Jest requirement that test files have at least one test
describe("Helper Module", () => {
  it("should export utilities", () => {
    expect(true).toBe(true);
  });
});
