/**
 * Unit tests for GET /api/dashboard/access
 * Tests dashboard access checking, auth, and access status
 */

// Mock all dependencies BEFORE imports
jest.mock("@/lib/auth", () => ({
  auth: jest.fn(),
}));

jest.mock("@/lib/dashboard-access", () => ({
  checkDashboardAccess: jest.fn(),
}));

jest.mock("@/lib/logger", () => ({
  logger: {
    warn: jest.fn(),
    error: jest.fn(),
    info: jest.fn(),
    debug: jest.fn(),
  },
}));

jest.mock("next/server", () => ({
  NextRequest: jest.fn(),
  NextResponse: {
    json: jest.fn((data: any, options?: any) => ({
      status: options?.status || 200,
      headers: { get: jest.fn(), set: jest.fn() },
      json: async () => data,
    })),
  },
}));

import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { checkDashboardAccess } from "@/lib/dashboard-access";

describe("GET /api/dashboard/access", () => {
  let accessModule: any;

  beforeAll(async () => {
    accessModule = await import("@/app/api/dashboard/access/route");
  });

  beforeEach(() => {
    jest.clearAllMocks();
    (NextResponse.json as jest.Mock).mockImplementation(
      (data: any, options?: any) => ({
        status: options?.status || 200,
        headers: { get: jest.fn(), set: jest.fn() },
        json: async () => data,
      }),
    );
  });

  const mockRequest = () =>
    ({
      headers: { get: jest.fn() },
    }) as unknown as NextRequest;

  it("should return 401 when no session exists", async () => {
    (auth as jest.Mock).mockResolvedValue(null);

    const request = mockRequest();
    const response = await accessModule.GET(request);
    const body = await response.json();

    expect(response.status).toBe(401);
    expect(body.hasAccess).toBe(false);
    expect(body.reason).toBe("Not authenticated");
    expect(body.redirectUrl).toBe("/en/login");
  });

  it("should return 401 when session has no user id", async () => {
    (auth as jest.Mock).mockResolvedValue({ user: { email: "test@test.com" } });

    const request = mockRequest();
    const response = await accessModule.GET(request);
    const body = await response.json();

    expect(response.status).toBe(401);
    expect(body.hasAccess).toBe(false);
  });

  it("should return access status for authenticated user with access", async () => {
    (auth as jest.Mock).mockResolvedValue({
      user: { id: "user-123", email: "test@test.com" },
    });
    (checkDashboardAccess as jest.Mock).mockResolvedValue({
      hasAccess: true,
      tier: "tier2",
      subscription: { status: "active" },
    });

    const request = mockRequest();
    const response = await accessModule.GET(request);
    const body = await response.json();

    expect(response.status).toBe(200);
    expect(body.hasAccess).toBe(true);
    expect(body.tier).toBe("tier2");
    expect(checkDashboardAccess).toHaveBeenCalledWith("user-123");
  });

  it("should return denied access status", async () => {
    (auth as jest.Mock).mockResolvedValue({
      user: { id: "user-456", email: "free@test.com" },
    });
    (checkDashboardAccess as jest.Mock).mockResolvedValue({
      hasAccess: false,
      reason: "No active subscription",
      redirectUrl: "/en/pricing",
    });

    const request = mockRequest();
    const response = await accessModule.GET(request);
    const body = await response.json();

    expect(response.status).toBe(200);
    expect(body.hasAccess).toBe(false);
    expect(body.reason).toBe("No active subscription");
    expect(body.redirectUrl).toBe("/en/pricing");
  });

  it("should return 500 on unexpected error", async () => {
    (auth as jest.Mock).mockRejectedValue(new Error("Auth service down"));

    const request = mockRequest();
    const response = await accessModule.GET(request);
    const body = await response.json();

    expect(response.status).toBe(500);
    expect(body.hasAccess).toBe(false);
    expect(body.reason).toBe("System error");
    expect(body.redirectUrl).toBe("/en/login");
  });

  it("should pass correct userId to checkDashboardAccess", async () => {
    (auth as jest.Mock).mockResolvedValue({
      user: { id: "user-789", email: "test@test.com" },
    });
    (checkDashboardAccess as jest.Mock).mockResolvedValue({
      hasAccess: true,
    });

    const request = mockRequest();
    await accessModule.GET(request);

    expect(checkDashboardAccess).toHaveBeenCalledWith("user-789");
  });
});
