<?php
/*
*
* All common functions for gravity booking.
*/
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

add_filter('gform_get_field_value', function ( $value, $entry, $field ) {
	// phpcs:ignore
	if ( isset($field->type) && 'apbgf_appointment_calendar' == $field->type && isset($_GET['page']) && 'gf_entries' === $_GET['page'] && ! isset($_GET['view']) ) {
		$html = '';
		$value = unserialize($value);
		if ( is_array( $value ) ) { 
			return get_the_title($value['service']);
		}
	}

	return $value;
}, 10, 3);
function apbgf_randon_pass() {
		$length = 6;
		$keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
		$str = '';
		$max = mb_strlen($keyspace, '8bit') - 1;
		
	if ($max < 1) {
		throw new Exception('$keyspace must be at least two characters long');
	}
		
	for ($i = 0; $i < $length; ++$i) {
		$str .= $keyspace[ random_int(0, $max) ];
	}

		return $str;
}
if ( ! function_exists('apbgf_translable_name') ) {
	function apbgf_translable_name( $type = '', $string = '' ) {      
		
		if ( 'weeks_short' == $type ) {
			$weeks = apply_filters('apbgf_weeks_name', array(
				'sunday' => __('SUN', 'appointment-and-booking-for-gravity-forms'),
				'monday' => __('MON', 'appointment-and-booking-for-gravity-forms'),
				'tuesday' => __('TUE', 'appointment-and-booking-for-gravity-forms'),
				'wednesday' => __('WED', 'appointment-and-booking-for-gravity-forms'),
				'thursday' => __('THU', 'appointment-and-booking-for-gravity-forms'),
				'friday' => __('FRI', 'appointment-and-booking-for-gravity-forms'),
				'saturday' => __('SAT', 'appointment-and-booking-for-gravity-forms'),
			), $type);          

			if ( empty( $string ) ) {
				return $weeks;
			} else {
				return isset($weeks[ $string ]) ? $weeks[ $string ] : $string;
			}
		}

		if ( 'weeks' == $type ) {
			$weeks = apply_filters('apbgf_weeks_name', array(
				'sunday' => __('Sunday', 'appointment-and-booking-for-gravity-forms'),
				'monday' => __('Monday', 'appointment-and-booking-for-gravity-forms'),
				'tuesday' => __('Tuesday', 'appointment-and-booking-for-gravity-forms'),
				'wednesday' => __('Wednesday', 'appointment-and-booking-for-gravity-forms'),
				'thursday' => __('Thursday', 'appointment-and-booking-for-gravity-forms'),
				'friday' => __('Friday', 'appointment-and-booking-for-gravity-forms'),
				'saturday' => __('Saturday', 'appointment-and-booking-for-gravity-forms'),
			), $type);

			if ( empty( $string ) ) {
				return $weeks;
			} else {
				return isset($weeks[ $string ]) ? $weeks[ $string ] : $string;
			}
		}

		if ( 'months_short' == $type ) {
			$months = apply_filters('apbgf_months_name', array(
				'january' => __('JAN', 'appointment-and-booking-for-gravity-forms'),
				'february' => __('FEB', 'appointment-and-booking-for-gravity-forms'),
				'march' => __('MAR', 'appointment-and-booking-for-gravity-forms'),
				'april' => __('APR', 'appointment-and-booking-for-gravity-forms'),
				'may' => __('MAY', 'appointment-and-booking-for-gravity-forms'),
				'june' => __('JUN', 'appointment-and-booking-for-gravity-forms'),
				'july' => __('JUL', 'appointment-and-booking-for-gravity-forms'),
				'august' => __('AUG', 'appointment-and-booking-for-gravity-forms'),
				'september' => __('SEP', 'appointment-and-booking-for-gravity-forms'),
				'october' => __('OCT', 'appointment-and-booking-for-gravity-forms'),
				'november' => __('NOV', 'appointment-and-booking-for-gravity-forms'),
				'december' => __('DEC', 'appointment-and-booking-for-gravity-forms'),
			), $type);

			if ( empty( $string ) ) {
				return $months;
			} else {
				return isset($months[ $string ]) ? $months[ $string ] : $string;
			}

		}

		if ( 'months' == $type ) {
			$months = apply_filters('apbgf_months_name', array(
				'january' => __('January', 'appointment-and-booking-for-gravity-forms'),
				'february' => __('February', 'appointment-and-booking-for-gravity-forms'),
				'march' => __('March', 'appointment-and-booking-for-gravity-forms'),
				'april' => __('April', 'appointment-and-booking-for-gravity-forms'),
				'may' => __('May', 'appointment-and-booking-for-gravity-forms'),
				'june' => __('June', 'appointment-and-booking-for-gravity-forms'),
				'july' => __('July', 'appointment-and-booking-for-gravity-forms'),
				'august' => __('August', 'appointment-and-booking-for-gravity-forms'),
				'september' => __('September', 'appointment-and-booking-for-gravity-forms'),
				'october' => __('October', 'appointment-and-booking-for-gravity-forms'),
				'november' => __('November', 'appointment-and-booking-for-gravity-forms'),
				'december' => __('December', 'appointment-and-booking-for-gravity-forms'),
			), $type);

			if ( empty( $string ) ) {
				return $months;
			} else {
				return isset($months[ $string ]) ? $months[ $string ] : $string;
			}

		}
	}
}

if ( ! function_exists('apbgf_field_exist') ) {
	function apbgf_field_exist( $form, $field_type = 'apbgf_appointment_calendar' ) {
		if ( isset( $form['fields'] ) ) {
			foreach ( $form['fields'] as $field ) {
				if ( $field->type === $field_type ) {                   
					return $field->id;       
				}
			}           
		} else {
			return false;
		}
	}
}

if ( ! function_exists('apbgf_timezone_string') ) {
	function apbgf_timezone_string( $staff_id = '' ) {        

		if ( ! empty( $staff_id ) ) {           

			$offset  = get_post_meta( $staff_id, 'timezone', true );
			if ( str_contains($offset, 'UTC') ) {
				$offset = (float) str_replace('UTC', '', $offset);              

				$hours   = (int) $offset;               
				$minutes = ( $offset - $hours );                
			 
				$sign      = ( $offset < 0 ) ? '+' : '-';
				$abs_hour  = abs( $hours );
				$abs_mins  = abs( $minutes * 60 );
				$tz_offset = sprintf( 'Etc/GMT%s%s', $sign, $abs_hour );
				
				return $tz_offset;
			} else {
				return $offset;
			}
		}

		$timezone_string = get_option( 'timezone_string' );
	 
		if ( $timezone_string ) {
			return $timezone_string;
		}
	 
		$offset  = (float) get_option( 'gmt_offset' );
		$hours   = (int) $offset;
		$minutes = ( $offset - $hours );
	 
		$sign      = ( $offset < 0 ) ? '+' : '-';
		$abs_hour  = abs( $hours );
		$abs_mins  = abs( $minutes * 60 );
		$tz_offset = sprintf( 'Etc/GMT%s%s', $sign, $abs_hour );
	 
		return $tz_offset;
	}
}

if ( ! function_exists('apbgf_currency_symbol') ) {
	function apbgf_currency_symbol() {
		// $arr = APBGF_Main::$apbgf_currency;
		$arr = RGCurrency::get_currency(GFCommon::get_currency());
		if ( is_array($arr) && isset($arr['symbol_left']) && ! empty($arr['symbol_left']) ) {
			return $arr['symbol_left'];
		}

		if ( is_array($arr) && isset($arr['symbol_right']) && ! empty($arr['symbol_right']) ) {
			return $arr['symbol_right'];
		}
	}
}

if ( ! function_exists( 'apbgf_get_price_input_step' ) ) {
	/**
	 * HTML step attribute for price inputs (allows decimal entry).
	 */
	function apbgf_get_price_input_step() {
		if ( class_exists( 'GFCommon' ) && class_exists( 'RGCurrency' ) ) {
			$arr      = RGCurrency::get_currency( GFCommon::get_currency() );
			$decimals = isset( $arr['decimals'] ) ? max( 0, (int) $arr['decimals'] ) : 2;
			if ( 0 === $decimals ) {
				return '1';
			}
			return '0.' . str_repeat( '0', $decimals - 1 ) . '1';
		}
		return '0.01';
	}
}

if ( ! function_exists( 'apbgf_normalize_price' ) ) {
	/**
	 * Normalize a price string for storage (handles comma decimal separators).
	 */
	function apbgf_normalize_price( $price ) {
		$price = trim( (string) $price );
		if ( '' === $price ) {
			return '';
		}
		if ( class_exists( 'GFCommon' ) && class_exists( 'RGCurrency' ) ) {
			$arr = RGCurrency::get_currency( GFCommon::get_currency() );
			$dec = isset( $arr['decimal_separator'] ) ? $arr['decimal_separator'] : '.';
			$tho = isset( $arr['thousand_separator'] ) ? $arr['thousand_separator'] : ',';
			if ( ',' === $dec ) {
				$price = str_replace( '.', '', $price );
				$price = str_replace( ',', '.', $price );
			} else {
				$price = str_replace( $tho, '', $price );
			}
		} else {
			$price = str_replace( ',', '.', $price );
		}
		return is_numeric( $price ) ? $price : '';
	}
}

if ( ! function_exists('apbgf_price_format') ) {
	function apbgf_price_format( $price, $currency = true, $echo = false, $code = false ) {
		$price = (float) $price;
		$arr = RGCurrency::get_currency(GFCommon::get_currency());      

		if ( is_array($arr) && isset($arr['symbol_left']) && ! empty($arr['symbol_left']) ) {
			if ( $echo ) {
				if ( $currency ) {
					echo esc_attr($arr['symbol_left']) . number_format($price, $arr['decimals'], $arr['decimal_separator'], $arr['thousand_separator'] );
				} else {
					echo number_format($price, $arr['decimals'], $arr['decimal_separator'], $arr['thousand_separator'] );
				}
			} elseif ( $currency ) {
				if ( $code ) {
					return $arr['code'] . number_format($price, $arr['decimals'], $arr['decimal_separator'], $arr['thousand_separator'] ); 
				} else {
					return $arr['symbol_left'] . number_format($price, $arr['decimals'], $arr['decimal_separator'], $arr['thousand_separator'] );  
				}
					
			} else {
				return number_format($price, $arr['decimals'], $arr['decimal_separator'], $arr['thousand_separator'] );
			}
			
		}

		if ( is_array($arr) && isset($arr['symbol_right']) && ! empty($arr['symbol_right']) ) {
			if ( $echo ) {
				if ( $currency ) {
					echo number_format($price, $arr['decimals'], $arr['decimal_separator'], $arr['thousand_separator'] ) . esc_attr($arr['symbol_right']);
				} else {
					echo number_format($price, $arr['decimals'], $arr['decimal_separator'], $arr['thousand_separator'] );
				}
			} elseif ( $currency ) {
				if ( $code ) {
					return number_format($price, $arr['decimals'], $arr['decimal_separator'], $arr['thousand_separator'] ) . esc_attr($arr['code']);    
				} else {
					return number_format($price, $arr['decimals'], $arr['decimal_separator'], $arr['thousand_separator'] ) . esc_attr($arr['symbol_right']);    
				}                   
			} else {
				return number_format($price, $arr['decimals'], $arr['decimal_separator'], $arr['thousand_separator'] );
			}
			
		}

		return $price;
	}
}

/**
* Create time slots between two given times
* Created by developer53 for future purpose
*/
if ( ! function_exists('apbgf_split_time') ) {
	function apbgf_split_time( $StartTime = '', $EndTime = '', $duration = 30, $interval = 15, $capacity = 1, $index = '' ) {
		
		$ReturnArray = array();// Define output        
		$StartTime    = strtotime($StartTime); //Get Timestamp
		$EndTime      = strtotime($EndTime); //Get Timestamp

		if ( '' != $duration && '' != $interval ) {

			$AddMins  = $duration * 60;
			$gap = $interval * 60;
			$i = 1;

			while ( ( $StartTime + $gap ) < $EndTime ) { //Run loop  
				
				if ( $i > 1 ) {
					$StartTime += $gap;     
				}
				
				if ( 0 == $index ) {
					$ReturnArray['index'] = '0';
				}

				if ( '' != $index ) {
					$ReturnArray['index'] = $index;
				}
				$ReturnArray['slot'][] = gmdate ( 'G:i', $StartTime ) . ' - ' . gmdate ( 'G:i', ( $StartTime + $AddMins ) );
				$ReturnArray['capacity'][] = $capacity;
				// $ReturnArray['add_break'][] = 'false';
				$ReturnArray['start'][] = gmdate ( 'G:i', $StartTime );
				$ReturnArray['end'][] = gmdate ( 'G:i', ( $StartTime + $AddMins ) );
				$StartTime += $AddMins; //Endtime check

				$i++;
			}
		}

		return $ReturnArray;
	}
}

if ( ! function_exists('apbgf_dates_in_range') ) {
	function apbgf_dates_in_range( $date1, $date2, $format = 'Y-m-d' ) {

		if ( empty($date1) || empty($date2) ) {
			return array();
		}

		$dates = array();
		$current = strtotime($date1);
		$date2 = strtotime($date2);
		$stepVal = '+1 day';
		while ( $current <= $date2 ) {
			$dates[] = gmdate($format, $current);
			$current = strtotime($stepVal, $current);
		}
		return $dates;
	}
}

add_filter('apbgf_staff_time_slot', function ( $slot, $staff_data = array() ) {

	$apbgf_settings = get_option('apbgf_settings', array());
	$apbgf_calendar_timeslot_format = isset($apbgf_settings['general']['apbgf_calendar_timeslot_format']) ? $apbgf_settings['general']['apbgf_calendar_timeslot_format'] : '24';

	if ( '12' == $apbgf_calendar_timeslot_format && isset($staff_data['booking_type']) && 'custom' == $staff_data['booking_type'] ) {

		$slot = explode('-', $slot);    
		$start_time = isset($slot[0]) ? trim($slot[0]) : '';
		$end_time = isset($slot[1]) ? trim($slot[1]) : '';
		if ( ! empty($start_time) && ! empty($end_time) ) {
			$start_time = gmdate('h:i a', strtotime($start_time));
			$end_time = gmdate('h:i a', strtotime($end_time));
			return $start_time . ' - ' . $end_time;         
		}
	}

	return $slot;
}, 10, 2);

//adding customization file.
if ( file_exists( get_stylesheet_directory() . '/gf-bookings/apbgf-custom.php' ) ) {
	require_once get_stylesheet_directory() . '/gf-bookings/apbgf-custom.php';
}

add_action('wp_loaded', function () {    
	
	$apbgf_settings = APBGF_Setting::get_settings();

	if ( isset($apbgf_settings['hide_slot_capacity']) && 'enabled' == $apbgf_settings['hide_slot_capacity'] ) {
		
		add_filter('apbgf_show_default_capacity', function ( $default_capacity ) {
			$default_capacity = 1;
			return $default_capacity;
		}, 10, 1);

		add_filter('apbgf_show_slot_list', function ( $flag ) {
			return false;
		});
	} else {
		add_filter('apbgf_show_default_capacity', function ( $default_capacity ) {
			$default_capacity = '';
			return $default_capacity;
		}, 10, 1);
	}
});

if ( ! function_exists( 'gcal_collect_body_from_raw' ) ) {

	function gcal_collect_body_from_raw( $raw_body ) {

		$body       = array();
		$raw_body   = ( array ) array_filter( explode( ',', $raw_body ) );
		$raw_body   = array_map( 'strip_tags', $raw_body );
		$raw_body   = array_map( 'trim', $raw_body );
		
		foreach ( $raw_body as $body_item ) {
			$item   = explode(':', $body_item);
			$column = reset( $item );

			$body[ $column ] = end( $item );

		}

		return $body;
	}

}

if ( ! function_exists( 'apbgf_appointment_body' ) ) {
	function apbgf_appointment_body( $enabled_fields, $field_values, $to = 'staff' ) {
		$description = '';

		if ( ! empty( $enabled_fields ) && count( $enabled_fields ) > 0 ) {

			$fields_data = APBGF_Setting::gcal_synchronization_fields();

			if ( 'customer' === $to ) {
				$fields_data['name']    = 'Staff Name';
				$fields_data['email']   = 'Staff Email';
				$fields_data['phone']   = 'Staff Phone';
			} else {
				$fields_data['name']    = 'Customer Name';
				$fields_data['email']   = 'Customer Email';
				$fields_data['phone']   = 'Customer Phone';
			}

			foreach ( $enabled_fields as $field ) { 

				if ( isset( $fields_data[ $field ] ) ) {

					$label = $fields_data[ $field ];
					$value = $field_values[ $field ];
					$description .= sprintf( '%1$s: %2$s <br/>', $label, $value );
				}
			}

		}

		return $description;
	}
}

function apbgf_parse_appointment_time( $date, $time_str, $staff_timezone ) {
	$start_time_str = isset( $time_str[0] ) ? trim( $time_str[0] ) : '';
	$end_time_str   = isset( $time_str[1] ) ? trim( $time_str[1] ) : '';

	$event_time = array();

	$start_datetime = new DateTime( "$date $start_time_str:00", new DateTimeZone( $staff_timezone ) );
	$end_datetime   = new DateTime( "$date $end_time_str:00", new DateTimeZone( $staff_timezone ) );

	// Convert to UTC and format in ISO 8601 (with milliseconds and Z)
	$start_datetime->setTimezone( new DateTimeZone( 'UTC' ) );
	$end_datetime->setTimezone( new DateTimeZone( 'UTC' ) );

	$event_time['startTime'] = $start_datetime->format( 'Y-m-d\TH:i:s.000\Z' );
	$event_time['endTime']   = $end_datetime->format( 'Y-m-d\TH:i:s.000\Z' );

	return $event_time;
}

// Back-compat alias, but avoid fatals if another plugin already defines it.
if ( ! function_exists( 'parse_appointment_time' ) ) {
	function parse_appointment_time( $date, $time_str, $staff_timezone ) {
		return apbgf_parse_appointment_time( $date, $time_str, $staff_timezone );
	}
}


/**
 * Convert array to CSV row without using filesystem functions
*/
function apbgf_array_to_csv_row( $data ) {
	$output = '';
	$separator = '';
	
	foreach ($data as $field) {
		// Escape fields containing quotes, commas or newlines
		$field = str_replace('"', '""', $field);
		if (preg_match('/[,"\n\r]/', $field)) {
			$field = '"' . $field . '"';
		}
		
		$output .= $separator . $field;
		$separator = ',';
	}
	
	return $output . "\n";
}
function apbgf_safe_html() {
	return array(
		'div' => array(
			'class' => array(),
			'id'    => array(),
			'style' => array(),
		),
		'span' => array(
			'class' => array(),
			'style' => array(),
		),
		'strong' => array(),
		'em'     => array(),
		'br'     => array(),
		'p'      => array(),
		'ul'     => array(
			'class' => array(),
		),
		'ol'     => array(),
		'li'     => array(),
		'table'  => array(
			'class' => array(),
			'style' => array(),
		),
		'thead' => array(),
		'tbody' => array(),
		'tr'    => array(),
		'td'    => array(
			'colspan' => array(),
			'rowspan' => array(),
			'style'   => array(),
		),
		'th'    => array(
			'colspan' => array(),
			'rowspan' => array(),
			'style'   => array(),
		),
		'a' => array(
			'href'       => array(),
			'title'      => array(),
			'target'     => array(),
			'rel'        => array(),
			'class'      => array(),
			'data-date'  => array(),
		),
		'img' => array(
			'src'    => array(),
			'alt'    => array(),
			'title'  => array(),
			'class'  => array(),
			'width'  => array(),
			'height' => array(),
			'style'  => array(),
		),
	);
}
