/**
 * Unit Tests: useBookingForm Hook Date Validation
 *
 * Tests the validation logic in useBookingForm to ensure
 * invalid dates (especially epoch dates) are caught before submission
 */

import { renderHook, act } from "@testing-library/react";
import { useBookingForm } from "@/components/DemoScheduler/hooks/useBookingForm";

// Mock localStorage
const localStorageMock = (() => {
  let store: Record<string, string> = {};
  return {
    getItem: jest.fn((key: string) => store[key] || null),
    setItem: jest.fn((key: string, value: string) => {
      store[key] = value;
    }),
    removeItem: jest.fn((key: string) => {
      delete store[key];
    }),
    clear: jest.fn(() => {
      store = {};
    }),
    get length() {
      return Object.keys(store).length;
    },
    key: jest.fn((index: number) => Object.keys(store)[index] || null),
  };
})();

Object.defineProperty(window, "localStorage", {
  value: localStorageMock,
});

// Mock fetch for API calls
global.fetch = jest.fn();

describe("useBookingForm - Date Validation", () => {
  beforeEach(() => {
    localStorageMock.clear();
    jest.clearAllMocks();
    (global.fetch as jest.Mock).mockReset();
  });

  describe("validateForm - Date Checks", () => {
    it("should fail validation when date is missing", () => {
      const { result } = renderHook(() => useBookingForm());

      act(() => {
        result.current.updateBookingData({
          meetingDuration: 60,
          selectedTime: "14:00",
          // No selectedDate
        });
        result.current.updateUserInfo({
          name: "Test User",
          email: "test@example.com",
          phone: "+97412345678",
          message: "Test message for booking",
        });
      });

      let isValid: boolean = false;
      act(() => {
        isValid = result.current.validateForm();
      });

      expect(isValid).toBe(false);
      expect(result.current.errors.date).toBeDefined();
    });

    it("should fail validation when date is null", () => {
      const { result } = renderHook(() => useBookingForm());

      act(() => {
        result.current.updateBookingData({
          meetingDuration: 60,
          selectedDate: null as any,
          selectedTime: "14:00",
        });
        result.current.updateUserInfo({
          name: "Test User",
          email: "test@example.com",
          phone: "+97412345678",
          message: "Test message for booking",
        });
      });

      let isValid: boolean = false;
      act(() => {
        isValid = result.current.validateForm();
      });

      expect(isValid).toBe(false);
      expect(result.current.errors.date).toBeDefined();
    });

    it("should fail validation when date is epoch (Jan 1, 1970)", () => {
      const { result } = renderHook(() => useBookingForm());

      const epochDate = new Date(0); // Jan 1, 1970

      act(() => {
        result.current.updateBookingData({
          meetingDuration: 60,
          selectedDate: epochDate,
          selectedTime: "14:00",
        });
        result.current.updateUserInfo({
          name: "Test User",
          email: "test@example.com",
          phone: "+97412345678",
          message: "Test message for booking",
        });
      });

      let isValid: boolean = false;
      act(() => {
        isValid = result.current.validateForm();
      });

      expect(isValid).toBe(false);
      expect(result.current.errors.date).toContain("Invalid date");
    });

    it("should fail validation when date year is 1970", () => {
      const { result } = renderHook(() => useBookingForm());

      const date1970 = new Date("1970-06-15");

      act(() => {
        result.current.updateBookingData({
          meetingDuration: 60,
          selectedDate: date1970,
          selectedTime: "14:00",
        });
        result.current.updateUserInfo({
          name: "Test User",
          email: "test@example.com",
          phone: "+97412345678",
          message: "Test message for booking",
        });
      });

      let isValid: boolean = false;
      act(() => {
        isValid = result.current.validateForm();
      });

      expect(isValid).toBe(false);
      expect(result.current.errors.date).toContain("Invalid date");
    });

    it("should pass validation with valid future date", () => {
      const { result } = renderHook(() => useBookingForm());

      const futureDate = new Date();
      futureDate.setDate(futureDate.getDate() + 7); // 1 week from now

      act(() => {
        result.current.updateBookingData({
          meetingDuration: 60,
          selectedDate: futureDate,
          selectedTime: "14:00",
          timezone: "Asia/Qatar",
        });
        result.current.updateUserInfo({
          name: "Test User",
          email: "test@example.com",
          phone: "+97412345678",
          message: "Test message for booking",
        });
      });

      let isValid: boolean = false;
      act(() => {
        isValid = result.current.validateForm();
      });

      expect(isValid).toBe(true);
      expect(result.current.errors.date).toBeUndefined();
    });
  });

  describe("Initial State from Storage", () => {
    it("should NOT load epoch date from corrupted storage", () => {
      // Pre-populate storage with corrupted epoch date
      const corruptedState = {
        state: {
          meetingDuration: 60,
          selectedDate: "1970-01-01T00:00:00.000Z",
          selectedTime: "14:00",
        },
        timestamp: Date.now(),
        version: "1.0.0",
      };
      localStorageMock.setItem(
        "mawidi_booking_draft",
        JSON.stringify(corruptedState),
      );

      const { result } = renderHook(() => useBookingForm());

      // selectedDate should be undefined, not epoch
      expect(result.current.bookingData.selectedDate).toBeUndefined();
      // Other fields should be preserved
      expect(result.current.bookingData.meetingDuration).toBe(60);
      expect(result.current.bookingData.selectedTime).toBe("14:00");
    });

    it("should NOT load null date from storage", () => {
      const stateWithNullDate = {
        state: {
          meetingDuration: 30,
          selectedDate: null,
          selectedTime: "10:00",
        },
        timestamp: Date.now(),
        version: "1.0.0",
      };
      localStorageMock.setItem(
        "mawidi_booking_draft",
        JSON.stringify(stateWithNullDate),
      );

      const { result } = renderHook(() => useBookingForm());

      expect(result.current.bookingData.selectedDate).toBeUndefined();
    });

    it("should load valid future date from storage", () => {
      const futureDate = new Date();
      futureDate.setDate(futureDate.getDate() + 14);

      const validState = {
        state: {
          meetingDuration: 60,
          selectedDate: futureDate.toISOString(),
          selectedTime: "15:00",
        },
        timestamp: Date.now(),
        version: "1.0.0",
      };
      localStorageMock.setItem(
        "mawidi_booking_draft",
        JSON.stringify(validState),
      );

      const { result } = renderHook(() => useBookingForm());

      expect(result.current.bookingData.selectedDate).toBeInstanceOf(Date);
      const loadedDate = result.current.bookingData.selectedDate as Date;
      expect(loadedDate.getFullYear()).toBeGreaterThan(1970);
    });

    it("should NOT load past dates from storage", () => {
      const pastDate = new Date();
      pastDate.setDate(pastDate.getDate() - 7); // 1 week ago

      const stateWithPastDate = {
        state: {
          meetingDuration: 60,
          selectedDate: pastDate.toISOString(),
          selectedTime: "14:00",
        },
        timestamp: Date.now(),
        version: "1.0.0",
      };
      localStorageMock.setItem(
        "mawidi_booking_draft",
        JSON.stringify(stateWithPastDate),
      );

      const { result } = renderHook(() => useBookingForm());

      // Past dates should not be restored
      expect(result.current.bookingData.selectedDate).toBeUndefined();
    });
  });

  describe("updateBookingData - Date Updates", () => {
    it("should accept valid date updates", () => {
      const { result } = renderHook(() => useBookingForm());

      const futureDate = new Date();
      futureDate.setDate(futureDate.getDate() + 10);

      act(() => {
        result.current.updateBookingData({ selectedDate: futureDate });
      });

      expect(result.current.bookingData.selectedDate).toEqual(futureDate);
    });

    it("should clear date when set to undefined", () => {
      const { result } = renderHook(() => useBookingForm());

      const futureDate = new Date();
      futureDate.setDate(futureDate.getDate() + 10);

      act(() => {
        result.current.updateBookingData({ selectedDate: futureDate });
      });

      expect(result.current.bookingData.selectedDate).toBeDefined();

      act(() => {
        result.current.updateBookingData({ selectedDate: undefined });
      });

      expect(result.current.bookingData.selectedDate).toBeUndefined();
    });
  });

  describe("resetForm", () => {
    it("should clear all booking data including date", () => {
      const { result } = renderHook(() => useBookingForm());

      const futureDate = new Date();
      futureDate.setDate(futureDate.getDate() + 7);

      act(() => {
        result.current.updateBookingData({
          meetingDuration: 60,
          selectedDate: futureDate,
          selectedTime: "14:00",
        });
        result.current.updateUserInfo({
          name: "Test User",
          email: "test@example.com",
          phone: "+97412345678",
          message: "Test message",
        });
      });

      expect(result.current.bookingData.selectedDate).toBeDefined();

      act(() => {
        result.current.resetForm();
      });

      expect(result.current.bookingData.selectedDate).toBeUndefined();
      expect(result.current.bookingData.meetingDuration).toBeUndefined();
      expect(result.current.bookingData.selectedTime).toBeUndefined();
    });
  });

  describe("Complete Validation Flow", () => {
    it("should validate all required fields including valid date", () => {
      const { result } = renderHook(() => useBookingForm());

      const futureDate = new Date();
      futureDate.setDate(futureDate.getDate() + 7);

      act(() => {
        result.current.updateBookingData({
          meetingDuration: 60,
          selectedDate: futureDate,
          selectedTime: "14:00",
          timezone: "Asia/Qatar",
        });
        result.current.updateUserInfo({
          name: "John Doe",
          email: "john@example.com",
          phone: "+97412345678",
          message: "I would like to see a demo of your product.",
        });
      });

      let isValid: boolean = false;
      act(() => {
        isValid = result.current.validateForm();
      });

      expect(isValid).toBe(true);
      expect(Object.keys(result.current.errors)).toHaveLength(0);
    });

    it("should collect all validation errors including date error", () => {
      const { result } = renderHook(() => useBookingForm());

      // Set invalid data
      act(() => {
        result.current.updateBookingData({
          meetingDuration: undefined, // Missing
          selectedDate: new Date(0), // Epoch - invalid
          selectedTime: undefined, // Missing
        });
        result.current.updateUserInfo({
          name: "", // Empty - invalid
          email: "invalid-email", // Invalid format
          phone: "", // Empty - invalid (now required)
          message: "Hi", // Too short
        });
      });

      let isValid: boolean = false;
      act(() => {
        isValid = result.current.validateForm();
      });

      expect(isValid).toBe(false);
      expect(result.current.errors.duration).toBeDefined();
      expect(result.current.errors.date).toBeDefined();
      expect(result.current.errors.time).toBeDefined();
      expect(result.current.errors.name).toBeDefined();
      expect(result.current.errors.email).toBeDefined();
    });
  });
});

describe("Date Edge Cases", () => {
  beforeEach(() => {
    localStorageMock.clear();
    jest.clearAllMocks();
  });

  it('should handle Date object created from string "null"', () => {
    const { result } = renderHook(() => useBookingForm());

    // @ts-ignore - Testing edge case
    const weirdDate = new Date("null");

    act(() => {
      result.current.updateBookingData({
        meetingDuration: 60,
        selectedDate: weirdDate,
        selectedTime: "14:00",
      });
      result.current.updateUserInfo({
        name: "Test User",
        email: "test@example.com",
        phone: "+97412345678",
        message: "Test message for booking",
      });
    });

    let isValid: boolean = false;
    act(() => {
      isValid = result.current.validateForm();
    });

    // new Date('null') creates Invalid Date
    expect(isValid).toBe(false);
    expect(result.current.errors.date).toBeDefined();
  });

  it('should handle Date object created from string "undefined"', () => {
    const { result } = renderHook(() => useBookingForm());

    // @ts-ignore - Testing edge case
    const weirdDate = new Date("undefined");

    act(() => {
      result.current.updateBookingData({
        meetingDuration: 60,
        selectedDate: weirdDate,
        selectedTime: "14:00",
      });
      result.current.updateUserInfo({
        name: "Test User",
        email: "test@example.com",
        phone: "+97412345678",
        message: "Test message for booking",
      });
    });

    let isValid: boolean = false;
    act(() => {
      isValid = result.current.validateForm();
    });

    // new Date('undefined') creates Invalid Date
    expect(isValid).toBe(false);
    expect(result.current.errors.date).toBeDefined();
  });

  it("should handle negative timestamp (pre-1970)", () => {
    const { result } = renderHook(() => useBookingForm());

    const pre1970Date = new Date(-86400000); // Dec 31, 1969

    act(() => {
      result.current.updateBookingData({
        meetingDuration: 60,
        selectedDate: pre1970Date,
        selectedTime: "14:00",
      });
      result.current.updateUserInfo({
        name: "Test User",
        email: "test@example.com",
        phone: "+97412345678",
        message: "Test message for booking",
      });
    });

    let isValid: boolean = false;
    act(() => {
      isValid = result.current.validateForm();
    });

    expect(isValid).toBe(false);
    expect(result.current.errors.date).toContain("Invalid date");
  });
});
