/**
 * Unit Tests: Form Validation Functions
 * Tests validation logic for booking form inputs
 */

import {
  validateEmail,
  validatePhoneNumber,
  validateName,
  validateMessage,
  validateBookingData,
  sanitizeInput,
} from "@/components/DemoScheduler/utils/validationHelpers";

describe("Form Validation", () => {
  describe("Email Validation", () => {
    it("should accept valid emails", () => {
      const validEmails = [
        "john@example.com",
        "test.user@domain.co.uk",
        "user+tag@example.com",
        "user_name@test.com",
      ];

      validEmails.forEach((email) => {
        const result = validateEmail(email);
        expect(result.valid).toBe(true);
      });
    });

    it("should reject invalid emails", () => {
      const invalidEmails = [
        "notanemail",
        "@example.com",
        "user@",
        "user @example.com",
        "",
      ];

      invalidEmails.forEach((email) => {
        const result = validateEmail(email);
        expect(result.valid).toBe(false);
        expect(result.error).toBeDefined();
      });
    });

    it("should trim whitespace", () => {
      const result = validateEmail("  john@example.com  ");
      expect(result.valid).toBe(true);
    });
  });

  describe("Name Validation", () => {
    it("should accept valid names", () => {
      const validNames = [
        "John Doe",
        "Mary O'Brien",
        "Jean-Paul Smith",
        "محمد أحمد", // Arabic name
      ];

      validNames.forEach((name) => {
        const result = validateName(name);
        expect(result.valid).toBe(true);
      });
    });

    it("should reject names too short", () => {
      const result = validateName("A");
      expect(result.valid).toBe(false);
      expect(result.error).toContain("at least");
    });

    it("should reject names too long", () => {
      const longName = "A".repeat(101);
      const result = validateName(longName);
      expect(result.valid).toBe(false);
      expect(result.error).toContain("at most");
    });

    it("should reject empty name", () => {
      const result = validateName("");
      expect(result.valid).toBe(false);
      expect(result.error).toContain("required");
    });
  });

  describe("Message Validation", () => {
    it("should accept valid messages", () => {
      const result = validateMessage("This is a test message for booking");
      expect(result.valid).toBe(true);
    });

    it("should reject empty messages", () => {
      const result = validateMessage("");
      expect(result.valid).toBe(false);
      expect(result.error).toContain("required");
    });

    it("should reject messages too short", () => {
      const result = validateMessage("Hi");
      expect(result.valid).toBe(false);
      expect(result.error).toContain("at least");
    });

    it("should reject messages too long", () => {
      const longMessage = "A".repeat(1001);
      const result = validateMessage(longMessage);
      expect(result.valid).toBe(false);
      expect(result.error).toContain("at most");
    });
  });

  describe("Complete Booking Validation", () => {
    const validBooking = {
      duration: 60,
      date: new Date("2025-10-24"),
      time: "10:00",
      userInfo: {
        name: "John Doe",
        email: "john@example.com",
        phone: "+97412345678",
        message: "Test booking message",
        timezone: "Asia/Qatar",
      },
    };

    it("should validate complete booking data", () => {
      const result = validateBookingData(validBooking);
      expect(result.valid).toBe(true);
    });

    it("should reject booking without duration", () => {
      const booking = { ...validBooking, duration: null };
      const result = validateBookingData(booking);
      expect(result.valid).toBe(false);
      expect(result.error).toContain("duration");
    });

    it("should reject booking without date", () => {
      const booking = { ...validBooking, date: null };
      const result = validateBookingData(booking);
      expect(result.valid).toBe(false);
      expect(result.error).toContain("date");
    });

    it("should reject booking without time", () => {
      const booking = { ...validBooking, time: null };
      const result = validateBookingData(booking);
      expect(result.valid).toBe(false);
      expect(result.error).toContain("time");
    });

    it("should reject booking without userInfo", () => {
      const booking = { ...validBooking, userInfo: null };
      const result = validateBookingData(booking);
      expect(result.valid).toBe(false);
      expect(result.error).toContain("contact information");
    });

    it("should reject invalid duration", () => {
      const booking = { ...validBooking, duration: 45 };
      const result = validateBookingData(booking);
      expect(result.valid).toBe(false);
      expect(result.error).toContain("Invalid meeting duration");
    });
  });

  describe("Input Sanitization", () => {
    it("should remove script tags", () => {
      const malicious = 'Hello<script>alert("xss")</script>World';
      const sanitized = sanitizeInput(malicious);
      expect(sanitized).not.toContain("<script>");
      expect(sanitized).not.toContain("</script>");
    });

    it("should remove javascript: protocol", () => {
      const malicious = 'javascript:alert("xss")';
      const sanitized = sanitizeInput(malicious);
      expect(sanitized).not.toContain("javascript:");
    });

    it("should remove event handlers", () => {
      const malicious = 'text onclick=alert("xss")';
      const sanitized = sanitizeInput(malicious);
      expect(sanitized).not.toContain("onclick=");
    });

    it("should limit string length", () => {
      const longString = "A".repeat(2000);
      const sanitized = sanitizeInput(longString);
      expect(sanitized.length).toBeLessThanOrEqual(1000);
    });

    it("should preserve safe content", () => {
      const safe = "This is safe content with spaces and punctuation!";
      const sanitized = sanitizeInput(safe);
      expect(sanitized).toBe(safe);
    });
  });
});
