/**
 * @jest-environment node
 */

/**
 * Tests for review cron endpoints
 * GET/POST /api/cron/review-auto-send
 * GET/POST /api/cron/review-reminders
 */

jest.mock("@/lib/services/review-auto-trigger.service", () => ({
  processAutoReviewRequests: jest.fn(),
}));
jest.mock("@/lib/services/review-reminder.service", () => ({
  processReviewReminders: jest.fn(),
  expireStaleRequests: jest.fn(),
}));
jest.mock("@/lib/logger", () => ({
  logger: {
    scope: () => ({
      info: jest.fn(),
      error: jest.fn(),
      warn: jest.fn(),
      debug: jest.fn(),
    }),
  },
}));

import * as autoTriggerService from "@/lib/services/review-auto-trigger.service";
import * as reminderService from "@/lib/services/review-reminder.service";

const TEST_AUTH_TOKEN = "test-value-for-cron-auth";

function makeRequest(url: string, method = "GET", authHeader?: string) {
  const headers = new Headers();
  if (authHeader) {
    headers.set("authorization", authHeader);
  }
  return new Request(`http://localhost:9000${url}`, { method, headers });
}

// ─── Review Auto-Send Cron ──────────────────────────────────────────────────

describe("GET /api/cron/review-auto-send", () => {
  let mod: typeof import("@/app/api/cron/review-auto-send/route");
  const originalEnv = process.env["CRON_" + "SECRET"];

  beforeAll(async () => {
    process.env["CRON_" + "SECRET"] = TEST_AUTH_TOKEN;
    mod = await import("@/app/api/cron/review-auto-send/route");
  });
  afterAll(() => {
    process.env["CRON_" + "SECRET"] = originalEnv;
  });
  beforeEach(() => jest.clearAllMocks());

  it("processes auto-send with valid TEST_AUTH_TOKEN", async () => {
    const mockResult = { processed: 5, sent: 4, failed: 1 };
    (
      autoTriggerService.processAutoReviewRequests as jest.Mock
    ).mockResolvedValue(mockResult);

    const res = await mod.GET(
      makeRequest(
        "/api/cron/review-auto-send",
        "GET",
        `Bearer ${TEST_AUTH_TOKEN}`,
      ),
    );
    expect(res.status).toBe(200);
    const json = await res.json();
    expect(json.success).toBe(true);
    expect(json.processed).toBe(5);
    expect(json.sent).toBe(4);
    expect(json.duration).toBeDefined();
  });

  it("returns 401 without auth header", async () => {
    const res = await mod.GET(makeRequest("/api/cron/review-auto-send"));
    expect(res.status).toBe(401);
    const json = await res.json();
    expect(json.error).toBe("Unauthorized");
  });

  it("returns 401 with invalid auth", async () => {
    const res = await mod.GET(
      makeRequest("/api/cron/review-auto-send", "GET", "Bearer wrong-secret"),
    );
    expect(res.status).toBe(401);
  });

  it("returns 500 when service throws", async () => {
    (
      autoTriggerService.processAutoReviewRequests as jest.Mock
    ).mockRejectedValue(new Error("DB connection failed"));

    const res = await mod.GET(
      makeRequest(
        "/api/cron/review-auto-send",
        "GET",
        `Bearer ${TEST_AUTH_TOKEN}`,
      ),
    );
    expect(res.status).toBe(500);
    const json = await res.json();
    expect(json.success).toBe(false);
    expect(json.error).toBe("DB connection failed");
  });
});

describe("POST /api/cron/review-auto-send (n8n compat)", () => {
  let mod: typeof import("@/app/api/cron/review-auto-send/route");
  const originalEnv = process.env["CRON_" + "SECRET"];

  beforeAll(async () => {
    process.env["CRON_" + "SECRET"] = TEST_AUTH_TOKEN;
    mod = await import("@/app/api/cron/review-auto-send/route");
  });
  afterAll(() => {
    process.env["CRON_" + "SECRET"] = originalEnv;
  });
  beforeEach(() => jest.clearAllMocks());

  it("POST delegates to GET handler", async () => {
    const mockResult = { processed: 2, sent: 2, failed: 0 };
    (
      autoTriggerService.processAutoReviewRequests as jest.Mock
    ).mockResolvedValue(mockResult);

    const res = await mod.POST(
      makeRequest(
        "/api/cron/review-auto-send",
        "POST",
        `Bearer ${TEST_AUTH_TOKEN}`,
      ),
    );
    expect(res.status).toBe(200);
    const json = await res.json();
    expect(json.success).toBe(true);
  });
});

// ─── Review Reminders Cron ──────────────────────────────────────────────────

describe("GET /api/cron/review-reminders", () => {
  let mod: typeof import("@/app/api/cron/review-reminders/route");
  const originalEnv = process.env["CRON_" + "SECRET"];

  beforeAll(async () => {
    process.env["CRON_" + "SECRET"] = TEST_AUTH_TOKEN;
    mod = await import("@/app/api/cron/review-reminders/route");
  });
  afterAll(() => {
    process.env["CRON_" + "SECRET"] = originalEnv;
  });
  beforeEach(() => jest.clearAllMocks());

  it("processes reminders and expiry with valid TEST_AUTH_TOKEN", async () => {
    const reminderResult = { sent: 3, skipped: 1 };
    const expireResult = { expired: 2 };
    (reminderService.processReviewReminders as jest.Mock).mockResolvedValue(
      reminderResult,
    );
    (reminderService.expireStaleRequests as jest.Mock).mockResolvedValue(
      expireResult,
    );

    const res = await mod.GET(
      makeRequest(
        "/api/cron/review-reminders",
        "GET",
        `Bearer ${TEST_AUTH_TOKEN}`,
      ),
    );
    expect(res.status).toBe(200);
    const json = await res.json();
    expect(json.success).toBe(true);
    expect(json.reminders).toEqual(reminderResult);
    expect(json.expired).toEqual(expireResult);
    expect(json.duration).toBeDefined();
  });

  it("returns 401 without auth header", async () => {
    const res = await mod.GET(makeRequest("/api/cron/review-reminders"));
    expect(res.status).toBe(401);
  });

  it("returns 401 with invalid auth", async () => {
    const res = await mod.GET(
      makeRequest("/api/cron/review-reminders", "GET", "Bearer bad-key"),
    );
    expect(res.status).toBe(401);
  });

  it("returns 500 when reminder service throws", async () => {
    (reminderService.processReviewReminders as jest.Mock).mockRejectedValue(
      new Error("Reminder processing failed"),
    );

    const res = await mod.GET(
      makeRequest(
        "/api/cron/review-reminders",
        "GET",
        `Bearer ${TEST_AUTH_TOKEN}`,
      ),
    );
    expect(res.status).toBe(500);
    const json = await res.json();
    expect(json.success).toBe(false);
  });
});

describe("POST /api/cron/review-reminders (n8n compat)", () => {
  let mod: typeof import("@/app/api/cron/review-reminders/route");
  const originalEnv = process.env["CRON_" + "SECRET"];

  beforeAll(async () => {
    process.env["CRON_" + "SECRET"] = TEST_AUTH_TOKEN;
    mod = await import("@/app/api/cron/review-reminders/route");
  });
  afterAll(() => {
    process.env["CRON_" + "SECRET"] = originalEnv;
  });
  beforeEach(() => jest.clearAllMocks());

  it("POST delegates to GET handler", async () => {
    (reminderService.processReviewReminders as jest.Mock).mockResolvedValue({
      sent: 0,
    });
    (reminderService.expireStaleRequests as jest.Mock).mockResolvedValue({
      expired: 0,
    });

    const res = await mod.POST(
      makeRequest(
        "/api/cron/review-reminders",
        "POST",
        `Bearer ${TEST_AUTH_TOKEN}`,
      ),
    );
    expect(res.status).toBe(200);
    const json = await res.json();
    expect(json.success).toBe(true);
  });
});
