/**
 * @jest-environment node
 */

import {
  TwilioIncomingMessageSchema,
  TwilioKeysConfigSchema,
  AIEngineResponseSchema,
  LanguagePreferenceSetSchema,
} from "@/lib/validators/whatsapp-ai.validator";

// ---------------------------------------------------------------------------
// TwilioIncomingMessageSchema
// ---------------------------------------------------------------------------
describe("TwilioIncomingMessageSchema", () => {
  const validMessage = {
    MessageSid: "SM1234567890abcdef1234567890abcdef",
    From: "whatsapp:+974501234567",
    To: "whatsapp:+447450018521",
    Body: "Hello there",
    NumMedia: 0,
  };

  it("accepts a valid incoming message", () => {
    const result = TwilioIncomingMessageSchema.safeParse(validMessage);
    expect(result.success).toBe(true);
  });

  it('rejects From that does not start with "whatsapp:"', () => {
    const result = TwilioIncomingMessageSchema.safeParse({
      ...validMessage,
      From: "+974501234567",
    });
    expect(result.success).toBe(false);
  });

  it('rejects To that does not start with "whatsapp:"', () => {
    const result = TwilioIncomingMessageSchema.safeParse({
      ...validMessage,
      To: "+447450018521",
    });
    expect(result.success).toBe(false);
  });

  it("coerces NumMedia from string to number", () => {
    const result = TwilioIncomingMessageSchema.safeParse({
      ...validMessage,
      NumMedia: "3",
    });
    expect(result.success).toBe(true);
    if (result.success) {
      expect(result.data.NumMedia).toBe(3);
      expect(typeof result.data.NumMedia).toBe("number");
    }
  });

  it("defaults NumMedia to 0 when not provided", () => {
    const { NumMedia, ...withoutNumMedia } = validMessage;
    const result = TwilioIncomingMessageSchema.safeParse(withoutNumMedia);
    expect(result.success).toBe(true);
    if (result.success) {
      expect(result.data.NumMedia).toBe(0);
    }
  });

  it("defaults Body to empty string when not provided", () => {
    const { Body, ...withoutBody } = validMessage;
    const result = TwilioIncomingMessageSchema.safeParse(withoutBody);
    expect(result.success).toBe(true);
    if (result.success) {
      expect(result.data.Body).toBe("");
    }
  });

  it("rejects missing MessageSid", () => {
    const { MessageSid, ...withoutSid } = validMessage;
    const result = TwilioIncomingMessageSchema.safeParse(withoutSid);
    expect(result.success).toBe(false);
  });

  it("accepts optional ProfileName", () => {
    const result = TwilioIncomingMessageSchema.safeParse({
      ...validMessage,
      ProfileName: "John Doe",
    });
    expect(result.success).toBe(true);
    if (result.success) {
      expect(result.data.ProfileName).toBe("John Doe");
    }
  });
});

// ---------------------------------------------------------------------------
// TwilioKeysConfigSchema
// ---------------------------------------------------------------------------
describe("TwilioKeysConfigSchema", () => {
  const validConfig = {
    accountSid: "AC" + "a".repeat(32), // 34 chars total, starts with AC
    authToken: "b".repeat(32), // 32 chars minimum
    whatsappNumber: "+974501234567", // E.164 format
  };

  it("accepts a valid config", () => {
    const result = TwilioKeysConfigSchema.safeParse(validConfig);
    expect(result.success).toBe(true);
  });

  it("rejects accountSid that does not start with AC", () => {
    const result = TwilioKeysConfigSchema.safeParse({
      ...validConfig,
      accountSid: "XX" + "a".repeat(32),
    });
    expect(result.success).toBe(false);
  });

  it("rejects accountSid shorter than 34 characters", () => {
    const result = TwilioKeysConfigSchema.safeParse({
      ...validConfig,
      accountSid: "AC" + "a".repeat(10), // only 12 chars
    });
    expect(result.success).toBe(false);
  });

  it("rejects accountSid longer than 34 characters", () => {
    const result = TwilioKeysConfigSchema.safeParse({
      ...validConfig,
      accountSid: "AC" + "a".repeat(40), // 42 chars
    });
    expect(result.success).toBe(false);
  });

  it("rejects authToken shorter than 32 characters", () => {
    const result = TwilioKeysConfigSchema.safeParse({
      ...validConfig,
      authToken: "short",
    });
    expect(result.success).toBe(false);
  });

  it("rejects whatsappNumber without leading +", () => {
    const result = TwilioKeysConfigSchema.safeParse({
      ...validConfig,
      whatsappNumber: "974501234567",
    });
    expect(result.success).toBe(false);
  });

  it("rejects whatsappNumber with letters", () => {
    const result = TwilioKeysConfigSchema.safeParse({
      ...validConfig,
      whatsappNumber: "+974ABC1234",
    });
    expect(result.success).toBe(false);
  });

  it("rejects whatsappNumber with too few digits", () => {
    const result = TwilioKeysConfigSchema.safeParse({
      ...validConfig,
      whatsappNumber: "+123",
    });
    expect(result.success).toBe(false);
  });
});

// ---------------------------------------------------------------------------
// AIEngineResponseSchema
// ---------------------------------------------------------------------------
describe("AIEngineResponseSchema", () => {
  const validResponse = {
    intent: "greeting",
    response: "Hello! How can I help?",
    language: "en",
  };

  it("accepts a valid response with minimal fields", () => {
    const result = AIEngineResponseSchema.safeParse(validResponse);
    expect(result.success).toBe(true);
  });

  it("accepts all valid intents", () => {
    const intents = [
      "company_query",
      "booking_request",
      "amend_appointment",
      "check_status",
      "greeting",
      "general",
      "off_topic",
      "abuse",
    ];
    for (const intent of intents) {
      const result = AIEngineResponseSchema.safeParse({
        ...validResponse,
        intent,
      });
      expect(result.success).toBe(true);
    }
  });

  it("rejects invalid intent", () => {
    const result = AIEngineResponseSchema.safeParse({
      ...validResponse,
      intent: "unknown_intent",
    });
    expect(result.success).toBe(false);
  });

  it("rejects missing response field", () => {
    const { response, ...withoutResponse } = validResponse;
    const result = AIEngineResponseSchema.safeParse(withoutResponse);
    expect(result.success).toBe(false);
  });

  it("accepts optional action field", () => {
    const result = AIEngineResponseSchema.safeParse({
      ...validResponse,
      action: { type: "none" },
    });
    expect(result.success).toBe(true);
  });

  it("rejects invalid action type", () => {
    const result = AIEngineResponseSchema.safeParse({
      ...validResponse,
      action: { type: "hack_server" },
    });
    expect(result.success).toBe(false);
  });

  it("accepts optional collectedInfo with valid date/time", () => {
    const result = AIEngineResponseSchema.safeParse({
      ...validResponse,
      collectedInfo: {
        name: "Ali",
        date: "2026-03-15",
        time: "14:30",
      },
    });
    expect(result.success).toBe(true);
  });

  it("rejects collectedInfo with invalid date format", () => {
    const result = AIEngineResponseSchema.safeParse({
      ...validResponse,
      collectedInfo: {
        date: "15/03/2026",
      },
    });
    expect(result.success).toBe(false);
  });

  it("accepts optional missingFields array", () => {
    const result = AIEngineResponseSchema.safeParse({
      ...validResponse,
      missingFields: ["name", "date"],
    });
    expect(result.success).toBe(true);
  });
});

// ---------------------------------------------------------------------------
// LanguagePreferenceSetSchema
// ---------------------------------------------------------------------------
describe("LanguagePreferenceSetSchema", () => {
  const validPreference = {
    organizationId: "org-123",
    phone: "+974501234567",
    language: "en",
  };

  it('accepts language "en"', () => {
    const result = LanguagePreferenceSetSchema.safeParse(validPreference);
    expect(result.success).toBe(true);
  });

  it('accepts language "ar"', () => {
    const result = LanguagePreferenceSetSchema.safeParse({
      ...validPreference,
      language: "ar",
    });
    expect(result.success).toBe(true);
  });

  it('rejects language "fr"', () => {
    const result = LanguagePreferenceSetSchema.safeParse({
      ...validPreference,
      language: "fr",
    });
    expect(result.success).toBe(false);
  });

  it('rejects unsupported language "es"', () => {
    const result = LanguagePreferenceSetSchema.safeParse({
      ...validPreference,
      language: "es",
    });
    expect(result.success).toBe(false);
  });

  it("provides custom error message for invalid language", () => {
    const result = LanguagePreferenceSetSchema.safeParse({
      ...validPreference,
      language: "fr",
    });
    expect(result.success).toBe(false);
    if (!result.success) {
      const langError = result.error.issues.find((i) =>
        i.path.includes("language"),
      );
      expect(langError?.message).toContain("'en'");
      expect(langError?.message).toContain("'ar'");
    }
  });

  it("rejects missing organizationId", () => {
    const { organizationId, ...withoutOrg } = validPreference;
    const result = LanguagePreferenceSetSchema.safeParse(withoutOrg);
    expect(result.success).toBe(false);
  });

  it("rejects phone shorter than 5 characters", () => {
    const result = LanguagePreferenceSetSchema.safeParse({
      ...validPreference,
      phone: "+1",
    });
    expect(result.success).toBe(false);
  });
});
