<?php

/**
 * Read policy for the public course schedule.
 *
 * Same contract as bw_post_grid_policy() in the post grid block: the REST route
 * in blocks/bw-course-schedule.php is unauthenticated, so this is what bounds
 * it rather than auth. 'meta' and 'tax' are what may be RETURNED to the
 * browser; 'meta_filter' and 'tax_filter' are what a caller may filter ON.
 *
 * The two _Event* keys are protected (underscore-prefixed) but are exactly what
 * the layout renders, so they are named here explicitly - this list is the
 * authority, not the underscore convention.
 */
function bw_course_schedule_policy () {
	return apply_filters('bw_course_schedule_policy', array(
		'meta'        => array('_EventStartDate', '_EventEndDate', 'city'),
		'tax'         => array('tribe_events_cat'),
		'meta_filter' => array('content_block'),
		'tax_filter'  => array('program', 'college_of_record'),
	));
}

/**
 * Ceiling on how many events one request may pull.
 */
function bw_course_schedule_max_per_page () {
	return (int) apply_filters('bw_course_schedule_max_per_page', 200);
}

/**
 * The meta an event may expose to the browser, limited to the policy's list.
 * Mirrors bw_post_grid_public_meta() - harden both together.
 */
function bw_course_schedule_public_meta ($post_id, $allowed) {
	$meta = get_fields($post_id);
	if (!is_array($meta)) $meta = array();

	foreach (get_post_meta($post_id) as $key => $values) {
		if (!is_array($values) || isset($meta[$key])) continue;
		$meta[$key] = reset($values);
	}

	return array_intersect_key($meta, array_flip($allowed));
}

function bw_course_schedule_request ($request) {

	$policy = bw_course_schedule_policy();

	// filters may only reference the fields this block actually filters on
	$meta = $request->get_param('meta');
	if (empty($meta) || !is_array($meta)) {
		$meta = false;
	} else {
		$meta = array_intersect_key($meta, array_flip($policy['meta_filter']));
		if (empty($meta)) $meta = false;
	}

	$tax = $request->get_param('tax');
	if (empty($tax) || !is_array($tax)) {
		$tax = false;
	} else {
		$tax = array_intersect_key($tax, array_flip($policy['tax_filter']));
		if (empty($tax)) $tax = false;
	}

	$posts_per_page = (int) $request->get_param('posts_per_page');
	if ($posts_per_page < 1) $posts_per_page = 12;

	$paged = (int) $request->get_param('paged');
	if ($paged < 1) $paged = 1;

	return resource_schedule($meta, $tax, $posts_per_page, $paged);
}

function resource_schedule ($meta = false, $tax = false, $posts_per_page = 20, $paged = 1) {

	// applied on both paths: the localized payload is as public as the endpoint
	$policy = bw_course_schedule_policy();

	$posts_per_page = min((int) $posts_per_page, bw_course_schedule_max_per_page());
	if ($posts_per_page < 1) $posts_per_page = 1;

	$args = array(
		'post_type'      => 'tribe_events',
		'post_status'    => 'publish',
		'posts_per_page' => $posts_per_page,
		'paged'          => max(1, (int) $paged),
		'tax_query'      => array(
			'relation' => 'AND'
		),
		'meta_query'     => array(
			'relation' => 'AND',
			'_EventStartDate_clause' => array(
				'key'     => '_EventStartDate',
				'value'   =>  date('Y-m-d 00:00:00', strtotime('-2 days', time())),
				'compare' => '>'
			)
		),
		'orderby'        => array(
			'title'                  => 'ASC',
			'_EventStartDate_clause' => 'ASC'
		)
	);
	if ($meta) {
		foreach ($meta as $key => $meta_query) {
			if (isset($meta_query['value'])) {
				$args['meta_query']["{$key}_clause"] = array(
					'key'     => $key,
					'value'   => $meta_query['value'],
					'compare' => isset($meta_query['compare']) ? $meta_query['compare'] : '=' 
				);
			}
		}
	}
	if ($tax) {
		foreach ($tax as $taxonomy => $tax_query) {
			if (isset($tax_query['terms'])) {
				$args['tax_query'][] = array(
					'taxonomy' => $taxonomy,
					'terms'    => $tax_query['terms'],
					'field'    => isset($tax_query['field']) ? $tax_query['field'] : 'slug',
					'operator'  => isset($tax_query['compare']) ? $tax_query['compare'] : 'IN' 
				);
			}
		}
	}
	$data = new stdClass();
	$data->posts = array();
	$results = new WP_Query($args);
	$data->found_posts = $results->found_posts;

	while ($results->have_posts()) {
		$results->the_post();

		$data->posts[] = $post = new stdClass();

		$post->title = get_the_title();
		$post->link = get_permalink();

		$post->meta = bw_course_schedule_public_meta(get_the_ID(), $policy['meta']);

		$post->tax = array();
		foreach ($policy['tax'] as $taxonomy) {
			$post->tax[$taxonomy] = wp_get_object_terms(get_the_ID(), $taxonomy);
		}
	}
	wp_reset_postdata();
	return $data;
}
function valid_courses ($terms) {
	global $wpdb;
	$is_valid = array();

	$args = array(
		'post_type'      => 'tribe_events',
		'posts_per_page' => -1,
		'tax_query'      => array(
			'relation' => 'AND',
			array(
					'taxonomy' => 'program',
					'terms'    => $terms,
					'field'    => 'term_id',
					'operator'  => 'NOT IN' 
			)
		),
		'meta_query'     => array(
			'relation' => 'AND',
			'_EventStartDate_clause' => array(
				'key'     => '_EventStartDate',
				'value'   =>  date('Y-m-d 00:00:00', strtotime('-2 days', time())),
				'compare' => '>'
			)
		)
	);
	$results = new WP_Query($args);
	while ($results->have_posts()) {
		$results->the_post();
		$content_block = get_field('content_block', get_the_ID());
		if ( $content_block ) {
			if (!is_array( $content_block )) {
				if (is_object($content_block)) {
					$is_valid[$content_block->ID] = true;
				} else {
					$is_valid[$content_block] = true;
				}
			} else {
				foreach ($content_block as $cb) {
					if (is_object($cb)) {
						$is_valid[$cb->ID] = true;
					} else {
						$is_valid[$cb] = true;
					}
				}
			}
		}
	}
	wp_reset_postdata();

	// deliberately returns IDs only. This used to carry the WP_Query as well,
	// which nothing read but which serialized the raw SQL and every matched
	// post - including post_content and post_password - if it was ever
	// localized into a page.
	return $is_valid;
}
