/**
 * Mawidi Demo Scheduler - Date Validation Utilities
 *
 * Centralized date validation to prevent epoch date bugs (Jan 1, 1970)
 * and ensure consistent date handling across the scheduler.
 */

/**
 * Result of date validation
 */
export interface DateValidationResult {
  valid: boolean;
  date?: Date;
  error?: string;
}

/**
 * Options for date validation
 */
export interface DateValidationOptions {
  /** Whether to require the date to be in the future (default: true) */
  requireFuture?: boolean;
  /** Whether to allow today's date (default: true when requireFuture is true) */
  allowToday?: boolean;
}

const DEFAULT_OPTIONS: DateValidationOptions = {
  requireFuture: true,
  allowToday: true,
};

/**
 * Check if a value represents a valid booking date.
 * Rejects epoch dates (1970), invalid dates, and optionally past dates.
 *
 * @param value - The value to validate (Date, string, number, or unknown)
 * @param options - Validation options
 * @returns DateValidationResult with validity status and parsed date if valid
 *
 * @example
 * ```ts
 * const result = isValidBookingDate(new Date('2025-12-15'));
 * if (result.valid) {
 *   console.log('Valid date:', result.date);
 * } else {
 *   console.log('Invalid:', result.error);
 * }
 * ```
 */
export function isValidBookingDate(
  value: unknown,
  options: DateValidationOptions = DEFAULT_OPTIONS,
): DateValidationResult {
  const { requireFuture = true, allowToday = true } = options;

  // Handle null/undefined/falsy values
  if (value == null || value === "" || value === 0) {
    return { valid: false, error: "Date is required" };
  }

  // Parse the date
  let date: Date;

  if (value instanceof Date) {
    date = value;
  } else if (typeof value === "string") {
    // Reject obviously invalid strings
    if (value === "null" || value === "undefined" || value === "NaN") {
      return { valid: false, error: "Invalid date format" };
    }
    date = new Date(value);
  } else if (typeof value === "number") {
    // Reject zero/negative timestamps (epoch or before)
    if (value <= 0) {
      return {
        valid: false,
        error: "Invalid date - epoch dates are not allowed",
      };
    }
    date = new Date(value);
  } else {
    return { valid: false, error: "Invalid date type" };
  }

  // Check if date is valid (not NaN)
  if (isNaN(date.getTime())) {
    return { valid: false, error: "Invalid date format" };
  }

  // Reject epoch dates (year 1970 or earlier)
  if (date.getFullYear() <= 1970) {
    return {
      valid: false,
      error: "Invalid date selected. Please select a valid date.",
    };
  }

  // Check if date is in the future (if required)
  if (requireFuture) {
    const now = new Date();
    now.setHours(0, 0, 0, 0);

    const dateOnly = new Date(date);
    dateOnly.setHours(0, 0, 0, 0);

    if (allowToday) {
      if (dateOnly < now) {
        return { valid: false, error: "Date must be today or in the future" };
      }
    } else {
      if (dateOnly <= now) {
        return { valid: false, error: "Date must be in the future" };
      }
    }
  }

  return { valid: true, date };
}

/**
 * Parse and validate a date value, returning the Date object or undefined.
 * This is a convenience function for when you just need the date or undefined.
 *
 * @param value - The value to parse and validate
 * @param options - Validation options
 * @returns Valid Date object or undefined
 *
 * @example
 * ```ts
 * const date = parseValidBookingDate(storedValue);
 * if (date) {
 *   // Use the valid date
 * }
 * ```
 */
export function parseValidBookingDate(
  value: unknown,
  options: DateValidationOptions = DEFAULT_OPTIONS,
): Date | undefined {
  const result = isValidBookingDate(value, options);
  return result.valid ? result.date : undefined;
}

/**
 * Convert a value to a Date if valid, otherwise return undefined.
 * Does NOT require the date to be in the future - only checks for valid date and non-epoch.
 * Use this for restoring dates from storage where past dates should be cleared.
 *
 * @param value - The value to convert
 * @returns Valid Date object or undefined
 */
export function toValidDate(value: unknown): Date | undefined {
  if (value == null || value === "" || value === 0) {
    return undefined;
  }

  let date: Date;

  if (value instanceof Date) {
    date = value;
  } else if (typeof value === "string") {
    if (
      value === "null" ||
      value === "undefined" ||
      value === "NaN" ||
      value.length === 0
    ) {
      return undefined;
    }
    date = new Date(value);
  } else if (typeof value === "number") {
    if (value <= 0) {
      return undefined;
    }
    date = new Date(value);
  } else {
    return undefined;
  }

  // Check if date is valid and not epoch
  if (isNaN(date.getTime()) || date.getFullYear() <= 1970) {
    return undefined;
  }

  return date;
}

/**
 * Check if a date value represents an epoch date (Jan 1, 1970 or year 1970)
 *
 * @param value - The value to check
 * @returns true if the value represents an epoch date
 */
export function isEpochDate(value: unknown): boolean {
  if (value == null) return false;

  let date: Date;

  if (value instanceof Date) {
    date = value;
  } else if (typeof value === "string" || typeof value === "number") {
    date = new Date(value as string | number);
  } else {
    return false;
  }

  if (isNaN(date.getTime())) return false;

  return date.getFullYear() === 1970;
}

/**
 * Validate a date for form submission.
 * Returns an error message if invalid, undefined if valid.
 *
 * @param value - The date value to validate
 * @returns Error message or undefined
 */
export function getDateValidationError(value: unknown): string | undefined {
  const result = isValidBookingDate(value, { requireFuture: false });
  return result.valid ? undefined : result.error;
}
