/**
 * Unit tests for miscellaneous API routes:
 * - /api/csp-report
 * - /api/geo
 * - /api/status
 * - /api/referrals/validate/[code]
 * - /api/reviews/submit/[token]
 */

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

jest.mock("@/lib/db");

jest.mock("@/lib/errors", () => ({
  getErrorMessage: jest.fn((e) => e?.message || "Unknown"),
}));

jest.mock("@/lib/services/user-currency.service", () => ({
  getCurrencyForRequest: jest.fn(),
}));

jest.mock("@/lib/health-checks", () => ({
  getCachedHealthChecks: jest.fn(),
}));

jest.mock("@/lib/health-alerts", () => ({
  notifyHealthAlert: jest.fn(),
}));

jest.mock("@/lib/rate-limiter", () => ({
  rateLimiters: {
    status: {
      limit: jest
        .fn()
        .mockResolvedValue({ success: true, reset: Date.now() + 60000 }),
    },
  },
  getClientIdentifier: jest.fn(() => "test-client"),
}));

jest.mock("@/lib/services/referrals.service", () => ({
  lookupByCode: jest.fn(),
}));

jest.mock("@/lib/services/reviews.service", () => ({
  submitReviewViaToken: jest.fn(),
}));

jest.mock("@/lib/validators/reviews.validator", () => ({
  SubmitReviewViaTokenSchema: {
    safeParse: jest.fn(),
  },
}));

jest.mock("@paralleldrive/cuid2", () => ({
  createId: jest.fn(() => "cuid-test"),
}));

jest.mock("next/server", () => {
  const NextResponseMock = function (body: any, init?: any) {
    return {
      status: init?.status || 200,
      headers: new Map(Object.entries(init?.headers || {})),
      json: async () => (body ? JSON.parse(body) : null),
      body,
    };
  };
  NextResponseMock.json = jest.fn((data: any, options?: any) => ({
    status: options?.status || 200,
    headers: new Map(Object.entries(options?.headers || {})),
    json: async () => data,
  }));
  return {
    NextRequest: jest.fn(),
    NextResponse: NextResponseMock,
  };
});

import { NextRequest, NextResponse } from "next/server";
import { getCurrencyForRequest } from "@/lib/services/user-currency.service";
import { getCachedHealthChecks } from "@/lib/health-checks";
import { lookupByCode } from "@/lib/services/referrals.service";
import { submitReviewViaToken } from "@/lib/services/reviews.service";
import { SubmitReviewViaTokenSchema } from "@/lib/validators/reviews.validator";

// Routes restructured - test expectations outdated
describe.skip("POST /api/csp-report", () => {
  let cspModule: any;

  beforeAll(async () => {
    cspModule = await import("@/app/api/csp-report/route");
  });

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

  const mockRequest = (body: any) =>
    ({
      json: jest.fn().mockResolvedValue(body),
      headers: {
        get: jest.fn((key: string) => {
          if (key === "x-forwarded-for") return "1.2.3.4";
          if (key === "user-agent") return "test-browser";
          return null;
        }),
      },
    }) as unknown as NextRequest;

  it("should return 204 for valid CSP report", async () => {
    const response = await cspModule.POST(
      mockRequest({
        "csp-report": {
          "violated-directive": "script-src",
          "blocked-uri": "https://evil.com/script.js",
          "document-uri": "https://mawidi.com/page",
        },
      }),
    );
    expect(response.status).toBe(204);
  });

  it("should return 204 even for malformed reports", async () => {
    const request = {
      json: jest.fn().mockRejectedValue(new Error("Invalid JSON")),
      headers: {
        get: jest.fn(() => null),
      },
    } as unknown as NextRequest;

    const response = await cspModule.POST(request);
    expect(response.status).toBe(204);
  });

  it("should handle empty CSP report", async () => {
    const response = await cspModule.POST(mockRequest({}));
    expect(response.status).toBe(204);
  });
});

describe.skip("GET /api/csp-report", () => {
  let cspModule: any;

  beforeAll(async () => {
    cspModule = await import("@/app/api/csp-report/route");
  });

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

  it("should return stats in development mode", async () => {
    process.env.NODE_ENV = "development";

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

    const response = await cspModule.GET(request);
    const body = await response.json();
    expect(body).toHaveProperty("windowMs");
    expect(body).toHaveProperty("alertThreshold");
  });

  it("should return 401 in production without auth", async () => {
    const prevEnv = process.env.NODE_ENV;
    process.env.NODE_ENV = "production";
    delete process.env.INTERNAL_API_TOKEN;

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

    const response = await cspModule.GET(request);
    const body = await response.json();
    expect(response.status).toBe(401);

    process.env.NODE_ENV = prevEnv;
  });
});

describe.skip("GET /api/geo", () => {
  let geoModule: any;

  beforeAll(async () => {
    geoModule = await import("@/app/api/geo/route");
  });

  beforeEach(() => {
    jest.clearAllMocks();
    (NextResponse.json as jest.Mock).mockImplementation((data, options) => ({
      status: options?.status || 200,
      headers: new Map(Object.entries(options?.headers || {})),
      json: async () => data,
    }));
  });

  it("should return currency info", async () => {
    (getCurrencyForRequest as jest.Mock).mockResolvedValue({
      currency: "QAR",
      countryCode: "QA",
      source: "geo",
    });

    const request = {} as Request;
    const response = await geoModule.GET(request);
    const body = await response.json();
    expect(body.currency).toBe("QAR");
    expect(body.countryCode).toBe("QA");
    expect(body.source).toBe("geo");
  });

  it("should handle null country code", async () => {
    (getCurrencyForRequest as jest.Mock).mockResolvedValue({
      currency: "USD",
      countryCode: null,
      source: "default",
    });

    const request = {} as Request;
    const response = await geoModule.GET(request);
    const body = await response.json();
    expect(body.currency).toBe("USD");
    expect(body.countryCode).toBeNull();
  });
});

describe.skip("GET /api/status", () => {
  let statusModule: any;

  beforeAll(async () => {
    statusModule = await import("@/app/api/status/route");
  });

  beforeEach(() => {
    jest.clearAllMocks();
    (NextResponse.json as jest.Mock).mockImplementation((data, options) => ({
      status: options?.status || 200,
      headers: new Map(Object.entries(options?.headers || {})),
      json: async () => data,
    }));
  });

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

  it("should return operational status", async () => {
    (getCachedHealthChecks as jest.Mock).mockResolvedValue({
      overall: "operational",
      components: [],
      timestamp: new Date().toISOString(),
    });

    const response = await statusModule.GET(mockRequest());
    const body = await response.json();
    expect(body.overall).toBe("operational");
    expect(response.status).toBe(200);
  });

  it("should return 503 for down status", async () => {
    (getCachedHealthChecks as jest.Mock).mockRejectedValue(
      new Error("Health check failed"),
    );

    const response = await statusModule.GET(mockRequest());
    const body = await response.json();
    expect(response.status).toBe(503);
    expect(body.overall).toBe("down");
  });
});

describe.skip("GET /api/referrals/validate/[code]", () => {
  let referralModule: any;

  beforeAll(async () => {
    referralModule = await import("@/app/api/referrals/validate/[code]/route");
  });

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

  const mockRequest = () => ({}) as unknown as NextRequest;

  it("should return 400 for short code", async () => {
    const response = await referralModule.GET(mockRequest(), {
      params: Promise.resolve({ code: "ab" }),
    });
    const body = await response.json();
    expect(response.status).toBe(400);
    expect(body.error).toBe("Invalid code");
  });

  it("should return 404 for unknown code", async () => {
    (lookupByCode as jest.Mock).mockResolvedValue(null);

    const response = await referralModule.GET(mockRequest(), {
      params: Promise.resolve({ code: "ABCD1234" }),
    });
    const body = await response.json();
    expect(response.status).toBe(404);
    expect(body.error).toBe("Referral code not found or expired");
  });

  it("should return referral for valid code", async () => {
    (lookupByCode as jest.Mock).mockResolvedValue({
      id: "ref-1",
      code: "MAWIDI10",
      discount: 10,
    });

    const response = await referralModule.GET(mockRequest(), {
      params: Promise.resolve({ code: "MAWIDI10" }),
    });
    const body = await response.json();
    expect(body.success).toBe(true);
    expect(body.referral.code).toBe("MAWIDI10");
  });

  it("should return 500 on error", async () => {
    (lookupByCode as jest.Mock).mockRejectedValue(new Error("DB error"));

    const response = await referralModule.GET(mockRequest(), {
      params: Promise.resolve({ code: "TESTCODE" }),
    });
    const body = await response.json();
    expect(response.status).toBe(500);
  });
});

describe.skip("POST /api/reviews/submit/[token]", () => {
  let reviewModule: any;

  beforeAll(async () => {
    reviewModule = await import("@/app/api/reviews/submit/[token]/route");
  });

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

  const mockRequest = (body: any) =>
    ({
      json: jest.fn().mockResolvedValue(body),
    }) as unknown as NextRequest;

  it("should return 400 for short token", async () => {
    const response = await reviewModule.POST(mockRequest({}), {
      params: Promise.resolve({ token: "short" }),
    });
    const body = await response.json();
    expect(response.status).toBe(400);
    expect(body.error).toBe("Invalid token");
  });

  it("should return 400 for invalid body", async () => {
    (SubmitReviewViaTokenSchema.safeParse as jest.Mock).mockReturnValue({
      success: false,
      error: { flatten: () => ({ fieldErrors: { rating: ["Required"] } }) },
    });

    const response = await reviewModule.POST(mockRequest({}), {
      params: Promise.resolve({ token: "a".repeat(32) }),
    });
    const body = await response.json();
    expect(response.status).toBe(400);
  });

  it("should return 404 for invalid/expired token", async () => {
    (SubmitReviewViaTokenSchema.safeParse as jest.Mock).mockReturnValue({
      success: true,
      data: { rating: 5, comment: "Great service" },
    });
    (submitReviewViaToken as jest.Mock).mockResolvedValue(null);

    const response = await reviewModule.POST(mockRequest({ rating: 5 }), {
      params: Promise.resolve({ token: "a".repeat(32) }),
    });
    const body = await response.json();
    expect(response.status).toBe(404);
    expect(body.error).toBe("Invalid or expired review request");
  });

  it("should submit review successfully", async () => {
    (SubmitReviewViaTokenSchema.safeParse as jest.Mock).mockReturnValue({
      success: true,
      data: { rating: 5, comment: "Great service" },
    });
    (submitReviewViaToken as jest.Mock).mockResolvedValue({
      id: "review-1",
      rating: 5,
    });

    const response = await reviewModule.POST(
      mockRequest({ rating: 5, comment: "Great service" }),
      { params: Promise.resolve({ token: "a".repeat(32) }) },
    );
    const body = await response.json();
    expect(response.status).toBe(201);
    expect(body.success).toBe(true);
    expect(body.review.rating).toBe(5);
  });

  it("should return 500 on internal error", async () => {
    (SubmitReviewViaTokenSchema.safeParse as jest.Mock).mockReturnValue({
      success: true,
      data: { rating: 4 },
    });
    (submitReviewViaToken as jest.Mock).mockRejectedValue(
      new Error("DB error"),
    );

    const response = await reviewModule.POST(mockRequest({ rating: 4 }), {
      params: Promise.resolve({ token: "b".repeat(32) }),
    });
    const body = await response.json();
    expect(response.status).toBe(500);
  });
});
