/**
 * Unit tests for WhatsApp Language Preference API
 * GET/POST /api/whatsapp/language-preference
 *
 * NOTE: Extended tests are in whatsapp-extended.test.ts.
 * This file covers the pre-existing integration test scenarios
 * converted to properly mocked unit tests.
 */

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

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

jest.mock("@/lib/services/system-settings.service", () => ({
  systemSettingsService: {
    validateN8NToken: jest.fn(),
  },
}));

jest.mock("@/lib/services/whatsapp-language.service", () => ({
  getLanguagePreference: jest.fn(),
  setLanguagePreference: jest.fn(),
}));

jest.mock("@/lib/validators/whatsapp-ai.validator", () => ({
  LanguagePreferenceGetSchema: {
    safeParse: jest.fn(),
  },
  LanguagePreferenceSetSchema: {
    safeParse: jest.fn(),
  },
}));

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

import { NextRequest, NextResponse } from "next/server";
import { systemSettingsService } from "@/lib/services/system-settings.service";
import {
  getLanguagePreference,
  setLanguagePreference,
} from "@/lib/services/whatsapp-language.service";
import {
  LanguagePreferenceGetSchema,
  LanguagePreferenceSetSchema,
} from "@/lib/validators/whatsapp-ai.validator";

// Route not yet implemented
describe.skip("WhatsApp Language Preference API (pre-existing)", () => {
  let langModule: {
    GET: (req: unknown) => Promise<{
      status: number;
      json: () => Promise<Record<string, unknown>>;
    }>;
    POST: (req: unknown) => Promise<{
      status: number;
      json: () => Promise<Record<string, unknown>>;
    }>;
  };

  beforeAll(async () => {
    langModule = await import("@/app/api/whatsapp/language-preference/route");
  });

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

  const mockGetRequest = (
    authHeader?: string,
    params?: Record<string, string>,
  ) =>
    ({
      headers: {
        get: jest.fn((key: string) => {
          if (key === "authorization") return authHeader || null;
          return null;
        }),
      },
      nextUrl: {
        searchParams: new URLSearchParams(params || {}),
      },
    }) as unknown as NextRequest;

  const mockPostRequest = (
    authHeader?: string,
    body?: Record<string, unknown>,
  ) =>
    ({
      headers: {
        get: jest.fn((key: string) => {
          if (key === "authorization") return authHeader || null;
          return null;
        }),
      },
      json: jest.fn().mockResolvedValue(body || {}),
    }) as unknown as NextRequest;

  describe("GET - Retrieve Language Preference", () => {
    it("should return 401 without auth", async () => {
      const response = await langModule.GET(mockGetRequest());
      expect(response.status).toBe(401);
    });

    it("should return 400 for missing parameters", async () => {
      (systemSettingsService.validateN8NToken as jest.Mock).mockResolvedValue(
        true,
      );
      (LanguagePreferenceGetSchema.safeParse as jest.Mock).mockReturnValue({
        success: false,
        error: { errors: [{ message: "Required" }] },
      });

      const response = await langModule.GET(
        mockGetRequest("Bearer valid-token"),
      );
      expect(response.status).toBe(400);
    });

    it("should return null for first-time user", async () => {
      (systemSettingsService.validateN8NToken as jest.Mock).mockResolvedValue(
        true,
      );
      (LanguagePreferenceGetSchema.safeParse as jest.Mock).mockReturnValue({
        success: true,
        data: { organizationId: "org-1", phone: "+966501234567" },
      });
      (getLanguagePreference as jest.Mock).mockResolvedValue(null);

      const response = await langModule.GET(
        mockGetRequest("Bearer valid-token", {
          organizationId: "org-1",
          phone: "+966501234567",
        }),
      );
      const body = await response.json();
      expect(body.success).toBe(true);
      expect(body.data.language).toBeNull();
    });

    it("should return saved preference for returning user", async () => {
      (systemSettingsService.validateN8NToken as jest.Mock).mockResolvedValue(
        true,
      );
      (LanguagePreferenceGetSchema.safeParse as jest.Mock).mockReturnValue({
        success: true,
        data: { organizationId: "org-1", phone: "+966501234567" },
      });
      (getLanguagePreference as jest.Mock).mockResolvedValue("ar");

      const response = await langModule.GET(
        mockGetRequest("Bearer valid-token"),
      );
      const body = await response.json();
      expect(body.success).toBe(true);
      expect(body.data.language).toBe("ar");
    });
  });

  describe("POST - Save Language Preference", () => {
    it("should return 401 without auth", async () => {
      const response = await langModule.POST(mockPostRequest());
      expect(response.status).toBe(401);
    });

    it("should return 400 for invalid body", async () => {
      (systemSettingsService.validateN8NToken as jest.Mock).mockResolvedValue(
        true,
      );
      (LanguagePreferenceSetSchema.safeParse as jest.Mock).mockReturnValue({
        success: false,
        error: { errors: [{ message: "Required" }] },
      });

      const response = await langModule.POST(
        mockPostRequest("Bearer valid-token", {}),
      );
      expect(response.status).toBe(400);
    });

    it("should save language preference for new user", async () => {
      (systemSettingsService.validateN8NToken as jest.Mock).mockResolvedValue(
        true,
      );
      (LanguagePreferenceSetSchema.safeParse as jest.Mock).mockReturnValue({
        success: true,
        data: {
          organizationId: "org-1",
          phone: "+966501234567",
          language: "en",
        },
      });
      (setLanguagePreference as jest.Mock).mockResolvedValue({
        organizationId: "org-1",
        userId: "+966501234567",
        language: "en",
        selectedAt: new Date("2026-02-17T10:00:00Z"),
      });

      const response = await langModule.POST(
        mockPostRequest("Bearer valid-token", {
          organizationId: "org-1",
          phone: "+966501234567",
          language: "en",
        }),
      );
      const body = await response.json();
      expect(body.success).toBe(true);
      expect(body.data.language).toBe("en");
    });

    it("should update existing preference", async () => {
      (systemSettingsService.validateN8NToken as jest.Mock).mockResolvedValue(
        true,
      );
      (LanguagePreferenceSetSchema.safeParse as jest.Mock).mockReturnValue({
        success: true,
        data: {
          organizationId: "org-1",
          phone: "+966501234567",
          language: "ar",
        },
      });
      (setLanguagePreference as jest.Mock).mockResolvedValue({
        organizationId: "org-1",
        userId: "+966501234567",
        language: "ar",
        selectedAt: new Date("2026-02-17T11:00:00Z"),
      });

      const response = await langModule.POST(
        mockPostRequest("Bearer valid-token", {
          organizationId: "org-1",
          phone: "+966501234567",
          language: "ar",
        }),
      );
      const body = await response.json();
      expect(body.data.language).toBe("ar");
    });

    it("should reject invalid language codes", async () => {
      (systemSettingsService.validateN8NToken as jest.Mock).mockResolvedValue(
        true,
      );
      (LanguagePreferenceSetSchema.safeParse as jest.Mock).mockReturnValue({
        success: false,
        error: { errors: [{ message: "Invalid language code" }] },
      });

      const response = await langModule.POST(
        mockPostRequest("Bearer valid-token", {
          organizationId: "org-1",
          phone: "+966501234567",
          language: "fr",
        }),
      );
      expect(response.status).toBe(400);
    });
  });
});
