<?php
/**
 * Cron job functionality for event imports.
 *
 * @package EventimUSEventListings
 */

defined( 'ABSPATH' ) || exit;
// Add custom interval to wp-cron.
add_filter( 'cron_schedules', 'evusel_custom_cron_interval' );
/**
 * Add custom cron interval.
 *
 * @param array $schedules Existing cron schedules.
 * @return array Modified cron schedules.
 */
function evusel_custom_cron_interval( $schedules ) {
	global $evuselConfig;
	$currentSetting = $evuselConfig->get( 'import.scheduled_import_interval' );
	$interval       = $evuselConfig::CRON_INTERVALS[ $currentSetting ];

	// Define translatable strings for each interval
	$interval_labels = array(
		'every_minute'          => __( 'Every Minute', 'eventim-us-event-listings' ),
		'every_five_minutes'    => __( 'Every Five Minutes', 'eventim-us-event-listings' ),
		'every_fifteen_minutes' => __( 'Every Fifteen Minutes', 'eventim-us-event-listings' ),
		'every_thirty_minutes'  => __( 'Every Thirty Minutes', 'eventim-us-event-listings' ),
		'hourly'                => __( 'Hourly', 'eventim-us-event-listings' ),
		'daily'                 => __( 'Daily', 'eventim-us-event-listings' ),
		'weekly'                => __( 'Weekly', 'eventim-us-event-listings' ),
	);

	$schedules[ $interval ] = array(
		'interval' => $evuselConfig::CRON_INTERVAL_SECS[ $currentSetting ],
		'display'  => isset( $interval_labels[ $interval ] ) ? $interval_labels[ $interval ] : $interval,
	);

	return $schedules;
}


// Register the cron action hook
if ( $evuselConfig->get( 'import.enable_scheduled_import' ) !== 'on' ) {
	$evusel_currentSetting = $evuselConfig->get( 'import.scheduled_import_interval' );
	add_action( 'evusel_cron_hook', 'evusel_cron_exec' );
	if ( ! wp_next_scheduled( 'evusel_cron_hook' ) ) {
		wp_schedule_event( time(), $evuselConfig::CRON_INTERVALS[ $evusel_currentSetting ], 'evusel_cron_hook' );
	}
} elseif ( wp_next_scheduled( 'evusel_cron_hook' ) ) {
		wp_clear_scheduled_hook( 'evusel_cron_hook' );
}

// Add an API route to trigger seetickets cron manually
add_action( 'rest_api_init', 'evusel_init_cron_trigger_endpoint' );
function evusel_init_cron_trigger_endpoint() {
	global $evuselConfig;

	register_rest_route(
		$evuselConfig::API_ENDPOINT_NAMESPACE,
		$evuselConfig::CRON_TRIGGER_ENDPOINT,
		array(
			'methods'             => 'GET',
			'callback'            => 'evusel_cron_exec',
			'permission_callback' => function () {
				return current_user_can( 'manage_options' );
			},
		)
	);
}

/**
 * Execute cron job to import events.
 *
 * @return string|void Cron execution result.
 */
function evusel_cron_exec() {
	define( 'EVUSEL_RUNNING_CRON', true );

	$feedStatus = get_transient( 'seetickets_feed_status' );

	if ( ! empty( $feedStatus['status'] ) && $feedStatus['status'] === 'in_progress' ) {
		$message = 'Import in progress, attempt was cancelled';

		return new WP_REST_Response( array( 'message' => $message ) );
	}

	set_transient( 'seetickets_feed_status', array( 'status' => 'in_progress' ), 10 * MINUTE_IN_SECONDS );

	global $evuselConfig;

	$eventsArray = array();

	foreach ( $evuselConfig->get( 'api.client_credentials' ) as $credentials ) {
		$url = str_replace( '{clientId}', $credentials['client_id'], $evuselConfig->get( 'api.url' ) );

		// $urls = [
		// $baseUrl,
		// $baseUrl . '&status=pending%20settlement'
		// ];

		// foreach ($urls as $url) {
		$timeOutCall = 150;
		$args        = array(
			'headers' => array(
				'api-key'    => $credentials['api_key'],
				'api-secret' => $credentials['api_secret'],
			),
			'timeout' => $timeOutCall,
		);

		$response = @wp_remote_get( $url, $args );
		if ( is_wp_error( $response ) ) {
			$responseMessage = '';
			foreach ( $response->get_error_messages() as $message ) {
				$responseMessage .= $message . '; ';
			}
			delete_transient( 'seetickets_feed_status' );
			return new WP_REST_Response( 'Seetickets cron error: ' . $responseMessage );
		}

		$code = wp_remote_retrieve_response_code( $response );

		// Log API errors
		switch ( $code ) {
			case '401':
			case '403':
			case '404':
			case '503':
			case '504':
				$message = wp_remote_retrieve_response_message( $response );
                // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log,WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Error logging for production issues
				error_log( print_r( 'Seetickets cron error: ' . $message, true ), 0 );
				delete_transient( 'seetickets_feed_status' );
				return new WP_REST_Response( 'Seetickets cron error: ' . $message );
				break;
		}

		if ( ! $response instanceof WP_Error && isset( $response['body'] ) ) {

			$responseBody = json_decode( wp_remote_retrieve_body( $response ), true );
			$keys         = array_keys( $responseBody );
			$isError      = reset( $keys ) === 'error';
			if ( $isError ) {
				delete_transient( 'seetickets_feed_status' );
				return new WP_REST_Response( 'Seetickets cron error: ' . reset( $responseBody ) );
			} else {
				foreach ( $responseBody as $seeEvent ) {
					$seeEvent['clientId'] = $credentials['client_id'];
					$eventsArray[]        = $seeEvent;
				}
			}
		}

		// }
	}

	$seeIds = array();

	$sortedEvents = array();
	foreach ( $eventsArray as $seeEvent ) {
		$eventId                  = (string) $seeEvent['id'];
		$sortedEvents[ $eventId ] = $seeEvent;
		$seeIds[ $eventId ]       = $eventId;
	}

	$existingEvents = get_posts(
		array(
			'numberposts'   => -1,
			'post_type'     => 'seetickets-event',
			'post_status'   => array( 'publish', 'draft' ),
			'meta_key'      => 'seetickets_id',
			'meta_compare'  => 'IN',
			'meta_value'    => implode( ',', $seeIds ),
			'no_found_rows' => true,
		)
	);

	$nonExistentEventIds = get_posts(
		array(
			'numberposts'   => -1,
			'post_type'     => 'seetickets-event',
			'post_status'   => array( 'publish', 'draft' ),
			'meta_key'      => 'seetickets_id',
			'meta_compare'  => 'NOT IN',
			'meta_value'    => implode( ',', $seeIds ),
			'no_found_rows' => true,
			'fields'        => 'ids',
		)
	);

	$importMedia   = $evuselConfig->get( 'import.import_to_wp_media_lib' ) === 'on';
	$defaultStatus = $evuselConfig->get( 'default_event_status' );

	// UPDATE events
	foreach ( $existingEvents as $key => $event ) {
		$id = $event->ID;

		$seeId    = get_post_meta( $id, 'seetickets_id', true );
		$seeEvent = $sortedEvents[ $seeId ];
		$args     = array(
			'ID' => $id,
		);

		$fieldsToExclude = array_keys( $evuselConfig->get( 'api.api_exclude_list' ) );

		if ( ! in_array( 'event_title', $fieldsToExclude ) ) {
			$args['post_title'] = $seeEvent['title'];
		}

		$imageChanged = ! empty( $seeEvent['image'] ) && get_post_meta( $id, 'image', true ) != $seeEvent['image'];

		wp_update_post( $args );

		if ( ! in_array( 'door_time', $fieldsToExclude ) ) {
			if ( isset( $seeEvent['datesTimes']['times']['doorTime'] ) ) {
				update_field( 'field_6053a14a0c016', $seeEvent['datesTimes']['times']['doorTime'], $args['ID'] );
			} else {
				update_field( 'field_6053a14a0c016', null, $args['ID'] );
			}
		}

		if ( isset( $seeEvent['eventtime'] ) ) {
			update_field( 'field_604944203e333', $seeEvent['eventtime'], $args['ID'] );
		} else {
			update_field( 'field_604944203e333', '', $args['ID'] );
		}

		// Add meta and ACF
		add_post_meta( $id, 'seetickets_id', $seeEvent['id'], true );
		try {
			evusel_update_event_meta( $id, $seeEvent );

		} catch ( Throwable $e ) {

			evusel_output_error_notification( $e, $seeEvent );
			continue;

		} catch ( Exception $e ) {

			evusel_output_error_notification( $e, $seeEvent );
			continue;
		}

		// Handle tags
		$tags     = explode( ', ', $seeEvent['tags'] );
		$tagSlugs = array();
		foreach ( $tags as $tag ) {
			if ( ! empty( $tag ) ) {
				$slug = str_replace( ' ', '-', strtolower( $tag ) );
				if ( ! term_exists( $tag, 'seetickets-event-tag' ) ) {
					$tids = wp_insert_term(
						$tag,
						'seetickets-event-tag',
						array(
							'slug' => $slug,
						)
					);
					add_term_meta( $tids['term_id'], 'client_id', $seeEvent['clientId'], true );
				}
				$tagSlugs[] = $slug;
			}
		}
		wp_set_object_terms( $id, $tagSlugs, 'seetickets-event-tag' );

		/** Media Import */
		if ( ! in_array( 'image', $fieldsToExclude ) ) {

			$isMediaImported = get_post_meta( $id, 'media_imported', true );

			if ( $isMediaImported === 'yes' ) {
				$oldAttachmentId       = get_post_thumbnail_id( $id );
				$attachmentStillExists = ! empty( get_attached_file( $oldAttachmentId ) );
			}

			// Import media if import settings have changed since import
			if ( $importMedia && ( $imageChanged || ! $attachmentStillExists ) ) {
				$attachmentId = evusel_import_media( $seeEvent, $id );
				update_post_meta( $id, 'media_imported', 'yes' );
				if ( ! empty( $oldAttachmentId ) ) {
					wp_delete_attachment( $oldAttachmentId );
				}
			} else {
				$attachmentId = $oldAttachmentId;
			}
		}
		/** End Media Import */

		if ( $seeEvent['isMultiDays'] && ( ! empty( $seeEvent['datesTimes']['dates'] ) ) ) {

			$eventDates         = $seeEvent['datesTimes']['dates'];
			$existingEventDates = get_post_meta( $id, 'repeating_dates', true );

			$repeatingEvents = get_posts(
				array(
					'numberposts'   => -1,
					'fields'        => 'ids',
					'post_parent'   => $id,
					'post_type'     => 'seetickets-event',
					'post_status'   => array( 'publish', 'draft' ),
					'no_found_rows' => true,
				)
			);

			/** If all dates are NOT matching */
			if ( implode( ',', $existingEventDates ) !== implode( ',', $eventDates ) ) { // Array diff won't work, because we need unmatched elements from both arrays

				unset( $eventDates[0] ); // The first date will match the main event's date, we don't need it.

				// Remove matching dates
				foreach ( $repeatingEvents as $repeatingId ) {

					$eventSortDate = get_post_meta( $repeatingId, 'sort_date', true );
					if ( ! empty( $eventSortDate ) ) {
						$sortDateTime = DateTime::createFromFormat( 'Ymd', $eventSortDate );

						if ( ! empty( $sortDateTime ) ) {

							$formattedSortDateTime = $sortDateTime->format( 'n/j/Y' );

							$key = array_search( $formattedSortDateTime, $eventDates );

							if ( ! empty( $key ) ) {
								unset( $eventDates[ $key ] );
								unset( $repeatingEvents[ array_search( $repeatingId, $repeatingEvents ) ] );
							}
						}
					}
				}

				// Delete events that are not needed in DB
				foreach ( $repeatingEvents as $repeatingId ) {
					wp_delete_post( $repeatingId, true );
				}

				// Create Events not found in DB
				foreach ( $eventDates as $date ) {

					/** Recurring dates are stored as separate events, this way they can be queried separately */
					$repeatingId  = wp_insert_post(
						array(
							'post_type'   => 'seetickets-event',
							'post_title'  => $seeEvent['title'],
							'post_parent' => $id,
							'post_status' => $defaultStatus,
							'meta_input'  => array(
								'is_multiday'  => $seeEvent['isMultiDays'],
								'image'        => $seeEvent['image'],
								'image_sm'     => $seeEvent['image-sm'],
								'event_title'  => $seeEvent['title'],
								'client_id'    => $seeEvent['clientId'],
								'ianaTimezone' => $seeEvent['ianaTimezone'],
							),
						)
					);
					$sortDateTime = DateTime::createFromFormat( 'm/d/Y', $date );
					if ( ! empty( $sortDateTime ) ) {
						update_field( 'field_6049443d3ed27', $sortDateTime->format( 'Ymd' ), $repeatingId );
					}
					$parentDateTimeString = get_post_meta( $id, 'event_time', true );
					update_field( 'field_604944203ed23', $seeEvent['datesTimes'], $repeatingId );
					if ( $importMedia && ! empty( $attachmentId ) && ! is_wp_error( $attachmentId ) ) {
						set_post_thumbnail( $repeatingId, $attachmentId );
						update_post_meta( $repeatingId, 'media_imported', 'yes' );
					}
					if ( ! $importMedia ) {
						update_post_meta( $repeatingId, 'media_imported', 'no' );
					}
				}

				update_post_meta( $id, 'repeating_dates', $seeEvent['datesTimes']['dates'] );

				/** If all dates ARE matching */
			} else {
				foreach ( $repeatingEvents as $repeatingId ) {
					wp_update_post(
						array(
							'ID'          => $repeatingId,
							'post_title'  => $seeEvent['title'],
							'post_parent' => $id,
							'meta_input'  => array(
								'is_multiday'  => $seeEvent['isMultiDays'],
								'image'        => $seeEvent['image'],
								'image_sm'     => $seeEvent['image-sm'],
								'event_title'  => $seeEvent['title'],
								'ianaTimezone' => $seeEvent['ianaTimezone'],
							),
						)
					);
				}
			}
		}

		unset( $seeIds[ $seeId ] );
	}

	// CREATE events
	foreach ( $seeIds as $seeId ) {

		$seeEvent = $sortedEvents[ $seeId ];

		if ( $seeEvent['isUnlisted'] ) {
			$defaultStatus = 'draft';
		} else {
			$defaultStatus = 'publish';
		}
		// Create Post
		$doorTimeCore = '';
		if ( isset( $seeEvent['eventtime'] ) ) {
			$doorTimeCore = $seeEvent['eventtime'];
			$eventTime    = $seeEvent['eventtime'];
		}

		$id = wp_insert_post(
			array(
				'post_type'   => 'seetickets-event',
				'post_title'  => $seeEvent['title'],
				'post_status' => $defaultStatus,
				'meta_input'  => array(
					'seetickets_id'  => $seeEvent['id'],
					'client_id'      => $seeEvent['clientId'],
					'door_time_core' => $doorTimeCore,
					'event_time'     => $eventTime,
				),
			)
		);

		// Remove debug output or use proper debugging
		if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
            // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log,WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug code only runs when WP_DEBUG is enabled
			error_log( print_r( $eventTime, true ) );
			// Or use a proper debugging function
			// evusel_debug_log('Event Time:', $eventTime);
		}

		// Add meta and ACF fields
		try {
			evusel_update_event_meta( $id, $seeEvent, true );

		} catch ( Throwable $e ) {

			evusel_output_error_notification( $e, $seeEvent );
			continue;

		} catch ( Exception $e ) {

			evusel_output_error_notification( $e, $seeEvent );
			continue;
		}

		// Handle tags
		$tags     = explode( ', ', $seeEvent['tags'] );
		$tagSlugs = array();
		foreach ( $tags as $tag ) {
			if ( ! empty( $tag ) ) {
				$slug = str_replace( ' ', '-', strtolower( $tag ) );
				if ( ! term_exists( $tag, 'seetickets-event-tag' ) ) {
					$tids = wp_insert_term(
						$tag,
						'seetickets-event-tag',
						array(
							'slug' => $slug,
						)
					);
					add_term_meta( $tids['term_id'], 'client_id', $seeEvent['clientId'], true );
				}
				$tagSlugs[] = $slug;
			}
		}
		wp_set_object_terms( $id, $tagSlugs, 'seetickets-event-tag' );

		// Save image
		if ( $importMedia ) {
			$attachmentId = evusel_import_media( $seeEvent, $id );
			update_post_meta( $id, 'media_imported', 'yes' );
		} else {
			update_post_meta( $id, 'media_imported', 'no' );
		}

		// Add repeating events in case of multiday events
		if ( $seeEvent['isMultiDays'] && ( ! empty( $seeEvent['datesTimes']['dates'] ) ) ) {

			$dates = $seeEvent['datesTimes']['dates'];
			update_post_meta( $id, 'multiDayEventDates', $dates );

			foreach ( $dates as $index => $date ) {

				if ( $index > 0 ) { // Skip the first date, because it will match the sort date

					/** Recurring dates are stored this way so they can be queried */
					$repeatingId  = wp_insert_post(
						array(
							'post_type'   => 'seetickets-event',
							'post_title'  => $seeEvent['title'],
							'post_parent' => $id,
							'post_status' => $defaultStatus,
							'meta_input'  => array(
								'is_multiday'        => $seeEvent['isMultiDays'],
								'image'              => $seeEvent['image'],
								'image_sm'           => $seeEvent['image-sm'],
								'event_title'        => $seeEvent['title'],
								'client_id'          => $seeEvent['clientId'],
								'ianaTimezone'       => $seeEvent['ianaTimezone'],
								'multiDayEventDates' => $dates,
							),
						)
					);
					$sortDateTime = DateTime::createFromFormat( 'm/d/Y', $date );
					if ( ! empty( $sortDateTime ) ) {
						update_field( 'field_6049443d3ed27', $sortDateTime->format( 'Ymd' ), $repeatingId );
					}
					$parentDateTimeString = get_post_meta( $id, 'event_time', true );
					update_field( 'field_604944203ed23', $seeEvent['eventtime'] . ' ' . substr( $parentDateTimeString, 11 ), $repeatingId );
					if ( $importMedia && ! empty( $attachmentId ) && ! is_wp_error( $attachmentId ) ) {
						set_post_thumbnail( $repeatingId, $attachmentId );
					}
					if ( ! $importMedia ) {
						update_post_meta( $repeatingId, 'media_imported', 'no' );
					}
				}
			}

			update_post_meta( $id, 'repeating_dates', $dates );
		}
	}

	// DELETE events no longer present in the feed
	foreach ( $nonExistentEventIds as $event_id ) {
		$attachment_id = get_post_thumbnail_id( $event_id );
		wp_delete_attachment( $attachment_id, true );
		wp_delete_post( $event_id );
	}

	$message = 'Finished running the import, processed ' . count( $eventsArray ) . ' events from the feed(s).';

	set_transient(
		'seetickets_feed_status',
		array(
			'status'                => 'finished',
			'processed_event_count' => count( $eventsArray ),
		),
		20
	);
}

/**
 * Receive Heartbeat data and respond.
 *
 * @param array  $response  The Heartbeat response.
 * @param string $screen_id The screen ID.
 * @since 0.32.0b
 *
 * @return array
 */
function evusel_send_heartbeat( array $response, string $screen_id ) {
	$feedStatus                         = get_transient( 'seetickets_feed_status' );
	$response['seetickets_feed_status'] = $feedStatus;
	if ( ! empty( $feedStatus['status'] ) && $feedStatus['status'] === 'finished' ) {
		delete_transient( 'seetickets_feed_status' );
	}
	return $response;
}
add_filter( 'heartbeat_send', 'evusel_send_heartbeat', 10, 2 );

/**
 * Seed up "pulse"
 *
 * @param array $settings
 * @since 0.32.0b
 *
 * @return array
 */
function evusel_heartbeat_settings( $settings ) {
	$settings['interval'] = 15;
	return $settings;
}
add_filter( 'heartbeat_settings', 'evusel_heartbeat_settings' );
