<?php
/**
 * Helper functions for loading and querying JSON mock data.
 *
 * These functions read from the /data/ directory JSON files and provide
 * a clean API for retrieving event, instance, and ticket type data.
 * When switching to a real Spektrix integration, only this file
 * needs to be replaced — the function signatures stay the same.
 *
 * @package Northfield_Theatre
 * @since 1.0.0
 */

/**
 * Load and cache a JSON data file.
 *
 * Uses a static variable to avoid reading the file on every call
 * within a single request.
 *
 * @param string $filename The JSON filename (without path).
 * @return array Decoded JSON data, or empty array on failure.
 */
function northfield_load_json( $filename ) {
	static $cache = array();

	if ( isset( $cache[ $filename ] ) ) {
		return $cache[ $filename ];
	}

	$file_path = NORTHFIELD_DIR . '/data/' . $filename;

	if ( ! file_exists( $file_path ) ) {
		return array();
	}

	$contents = file_get_contents( $file_path );
	if ( false === $contents ) {
		return array();
	}

	$data = json_decode( $contents, true );
	if ( json_last_error() !== JSON_ERROR_NONE ) {
		return array();
	}

	$cache[ $filename ] = $data;
	return $data;
}

/**
 * Get all events.
 *
 * @param array $args Optional. Query arguments to filter events.
 *   - 'category'    (string) Filter by category name.
 *   - 'venue'       (string) Filter by venue name.
 *   - 'featured'    (bool)   Only featured events.
 *   - 'search'      (string) Search term for name/summary/description.
 *   - 'sale_status' (string) Filter by sale status.
 *   - 'limit'       (int)    Max number of results.
 *   - 'offset'      (int)    Number of results to skip.
 *   - 'orderby'     (string) 'name', 'date', 'price'. Default 'date'.
 *   - 'order'       (string) 'ASC' or 'DESC'. Default 'ASC'.
 * @return array Array of event objects.
 */
function northfield_get_events( $args = array() ) {
	$defaults = array(
		'category'    => '',
		'venue'       => '',
		'featured'    => null,
		'search'      => '',
		'sale_status' => '',
		'limit'       => 0,
		'offset'      => 0,
		'orderby'     => 'date',
		'order'       => 'ASC',
	);

	$args   = wp_parse_args( $args, $defaults );
	$events = northfield_load_json( 'events.json' );

	if ( empty( $events ) ) {
		return array();
	}

	// Filter by category.
	if ( ! empty( $args['category'] ) ) {
		$cat    = strtolower( $args['category'] );
		$events = array_filter( $events, function ( $event ) use ( $cat ) {
			return strtolower( $event['category'] ) === $cat;
		} );
	}

	// Filter by venue.
	if ( ! empty( $args['venue'] ) ) {
		$venue  = strtolower( $args['venue'] );
		$events = array_filter( $events, function ( $event ) use ( $venue ) {
			return strtolower( $event['venue'] ) === $venue;
		} );
	}

	// Filter by featured.
	if ( null !== $args['featured'] ) {
		$featured = (bool) $args['featured'];
		$events   = array_filter( $events, function ( $event ) use ( $featured ) {
			return $event['featured'] === $featured;
		} );
	}

	// Filter by sale status.
	if ( ! empty( $args['sale_status'] ) ) {
		$status = $args['sale_status'];
		$events = array_filter( $events, function ( $event ) use ( $status ) {
			return $event['saleStatus'] === $status;
		} );
	}

	// Search by name, summary, or description.
	if ( ! empty( $args['search'] ) ) {
		$term   = strtolower( $args['search'] );
		$events = array_filter( $events, function ( $event ) use ( $term ) {
			return str_contains( strtolower( $event['name'] ), $term )
				|| str_contains( strtolower( $event['summary'] ), $term )
				|| str_contains( strtolower( $event['description'] ), $term );
		} );
	}

	// Sort events.
	$events = array_values( $events );
	$order  = strtoupper( $args['order'] ) === 'DESC' ? -1 : 1;

	usort( $events, function ( $a, $b ) use ( $args, $order ) {
		switch ( $args['orderby'] ) {
			case 'name':
				return $order * strcmp( $a['name'], $b['name'] );
			case 'price':
				return $order * ( $a['minPrice'] - $b['minPrice'] );
			case 'date':
			default:
				$a_date = northfield_get_event_first_date( $a['id'] );
				$b_date = northfield_get_event_first_date( $b['id'] );
				return $order * strcmp( $a_date, $b_date );
		}
	} );

	// Apply offset and limit.
	if ( $args['offset'] > 0 || $args['limit'] > 0 ) {
		$limit  = $args['limit'] > 0 ? $args['limit'] : null;
		$events = array_slice( $events, (int) $args['offset'], $limit );
	}

	return $events;
}

/**
 * Get a single event by its JSON ID.
 *
 * @param string $event_id The event ID (e.g. 'evt_001').
 * @return array|null The event data, or null if not found.
 */
function northfield_get_event( $event_id ) {
	$events = northfield_load_json( 'events.json' );

	foreach ( $events as $event ) {
		if ( $event['id'] === $event_id ) {
			return $event;
		}
	}

	return null;
}

/**
 * Get a single event by its slug.
 *
 * @param string $slug The event slug (e.g. 'hamlet').
 * @return array|null The event data, or null if not found.
 */
function northfield_get_event_by_slug( $slug ) {
	$events = northfield_load_json( 'events.json' );

	foreach ( $events as $event ) {
		if ( $event['slug'] === $slug ) {
			return $event;
		}
	}

	return null;
}

/**
 * Get instances for an event.
 *
 * @param string $event_id The event ID.
 * @param array  $args     Optional query arguments.
 *   - 'availability' (string) Filter by availability.
 *   - 'from'         (string) ISO date, instances on or after this date.
 *   - 'to'           (string) ISO date, instances on or before this date.
 * @return array Array of instance objects, sorted by datetime.
 */
function northfield_get_instances( $event_id = '', $args = array() ) {
	$instances = northfield_load_json( 'instances.json' );

	if ( empty( $instances ) ) {
		return array();
	}

	// Filter by event ID.
	if ( ! empty( $event_id ) ) {
		$instances = array_filter( $instances, function ( $instance ) use ( $event_id ) {
			return $instance['eventId'] === $event_id;
		} );
	}

	// Filter by availability.
	if ( ! empty( $args['availability'] ) ) {
		$avail     = $args['availability'];
		$instances = array_filter( $instances, function ( $instance ) use ( $avail ) {
			return $instance['availability'] === $avail;
		} );
	}

	// Filter by date range.
	if ( ! empty( $args['from'] ) ) {
		$from      = $args['from'];
		$instances = array_filter( $instances, function ( $instance ) use ( $from ) {
			return $instance['datetime'] >= $from;
		} );
	}

	if ( ! empty( $args['to'] ) ) {
		$to        = $args['to'];
		$instances = array_filter( $instances, function ( $instance ) use ( $to ) {
			return $instance['datetime'] <= $to;
		} );
	}

	// Sort by datetime.
	$instances = array_values( $instances );
	usort( $instances, function ( $a, $b ) {
		return strcmp( $a['datetime'], $b['datetime'] );
	} );

	return $instances;
}

/**
 * Get a single instance by its ID.
 *
 * @param string $instance_id The instance ID (e.g. 'inst_001').
 * @return array|null The instance data, or null if not found.
 */
function northfield_get_instance( $instance_id ) {
	$instances = northfield_load_json( 'instances.json' );

	foreach ( $instances as $instance ) {
		if ( $instance['id'] === $instance_id ) {
			return $instance;
		}
	}

	return null;
}

/**
 * Get the earliest performance date for an event.
 *
 * @param string $event_id The event ID.
 * @return string ISO datetime string, or empty string if no instances.
 */
function northfield_get_event_first_date( $event_id ) {
	$instances = northfield_get_instances( $event_id );
	if ( empty( $instances ) ) {
		return '';
	}
	return $instances[0]['datetime'];
}

/**
 * Get the latest performance date for an event.
 *
 * @param string $event_id The event ID.
 * @return string ISO datetime string, or empty string if no instances.
 */
function northfield_get_event_last_date( $event_id ) {
	$instances = northfield_get_instances( $event_id );
	if ( empty( $instances ) ) {
		return '';
	}
	return end( $instances )['datetime'];
}

/**
 * Get all ticket types.
 *
 * @return array Array of ticket type objects.
 */
function northfield_get_ticket_types() {
	return northfield_load_json( 'ticket-types.json' );
}

/**
 * Get ticket types with calculated prices for a specific event.
 *
 * Prices are derived from the event's maxPrice and each ticket type's
 * price multiplier. This mimics how real Spektrix serves per-event pricing.
 *
 * @param string $event_id The event ID.
 * @return array Ticket types with 'price' field added.
 */
function northfield_get_event_ticket_types( $event_id ) {
	$event = northfield_get_event( $event_id );
	if ( ! $event ) {
		return array();
	}

	$ticket_types = northfield_get_ticket_types();
	$max_price    = (float) $event['maxPrice'];
	$result       = array();

	foreach ( $ticket_types as $tt ) {
		$price = round( $max_price * $tt['priceMultiplier'], 2 );

		// Family tickets: price is for the bundle.
		$result[] = array(
			'id'          => $tt['id'],
			'name'        => $tt['name'],
			'description' => $tt['description'],
			'price'       => $price,
			'quantity'    => isset( $tt['quantity'] ) ? $tt['quantity'] : 1,
		);
	}

	return $result;
}

/**
 * Get all unique event categories from the data.
 *
 * @return array Array of category name strings.
 */
function northfield_get_event_categories() {
	$events     = northfield_load_json( 'events.json' );
	$categories = array();

	foreach ( $events as $event ) {
		if ( ! in_array( $event['category'], $categories, true ) ) {
			$categories[] = $event['category'];
		}
	}

	sort( $categories );
	return $categories;
}

/**
 * Get all unique venues from the data.
 *
 * @return array Array of venue name strings.
 */
function northfield_get_venues() {
	$events = northfield_load_json( 'events.json' );
	$venues = array();

	foreach ( $events as $event ) {
		if ( ! in_array( $event['venue'], $venues, true ) ) {
			$venues[] = $event['venue'];
		}
	}

	sort( $venues );
	return $venues;
}

/**
 * Get events that have instances within a date range.
 *
 * Useful for "What's On This Week" type queries.
 *
 * @param string $from ISO date string (e.g. '2026-05-15').
 * @param string $to   ISO date string (e.g. '2026-05-22').
 * @return array Events with instances in the date range.
 */
function northfield_get_events_in_range( $from, $to ) {
	$events    = northfield_load_json( 'events.json' );
	$instances = northfield_load_json( 'instances.json' );
	$result    = array();

	// Find event IDs that have instances in the range.
	$event_ids = array();
	foreach ( $instances as $instance ) {
		$inst_date = substr( $instance['datetime'], 0, 10 );
		if ( $inst_date >= $from && $inst_date <= $to ) {
			$event_ids[ $instance['eventId'] ] = true;
		}
	}

	foreach ( $events as $event ) {
		if ( isset( $event_ids[ $event['id'] ] ) ) {
			$result[] = $event;
		}
	}

	return $result;
}

/**
 * Get events grouped by date, for the What's On page.
 *
 * Returns an array keyed by date string (Y-m-d), each containing
 * an array of events with their instances for that date.
 *
 * @param array $args Optional filter arguments (same as northfield_get_events).
 * @return array Associative array: date => array of event data with instances.
 */
function northfield_get_events_by_date( $args = array() ) {
	$events    = northfield_get_events( $args );
	$instances = northfield_load_json( 'instances.json' );
	$grouped   = array();

	foreach ( $instances as $instance ) {
		$date = substr( $instance['datetime'], 0, 10 );

		// Find the matching event.
		foreach ( $events as $event ) {
			if ( $event['id'] === $instance['eventId'] ) {
				if ( ! isset( $grouped[ $date ] ) ) {
					$grouped[ $date ] = array();
				}

				$grouped[ $date ][] = array(
					'event'    => $event,
					'instance' => $instance,
				);
				break;
			}
		}
	}

	ksort( $grouped );
	return $grouped;
}

/**
 * Pick the single most relevant badge for an event card.
 *
 * Priority (high to low):
 *   1. Sold out           (saleStatus or availability)
 *   2. Last few           (availability)
 *   3. Closing this week  (last instance within 7 days)
 *   4. Just announced     (justAnnounced flag on the event)
 *
 * Returns null when nothing is urgent — empty cards read cleaner than
 * cards showing "Available" on every tile.
 *
 * @param array $event Event data.
 * @return array{label:string,variant:string}|null Badge descriptor or null.
 */
function northfield_get_event_badge( $event ) {
	$sale         = $event['saleStatus'] ?? '';
	$availability = $event['availability'] ?? '';

	if ( $sale === 'SoldOut' || $availability === 'SoldOut' ) {
		return array(
			'label'   => __( 'Sold out', 'northfield-theatre' ),
			'variant' => 'soldout',
		);
	}

	if ( $availability === 'LastFew' ) {
		return array(
			'label'   => __( 'Last few', 'northfield-theatre' ),
			'variant' => 'low',
		);
	}

	$last_date = northfield_get_event_last_date( $event['id'] );
	if ( $last_date ) {
		$last_ts = strtotime( $last_date );
		$now     = time();
		if ( $last_ts > $now && ( $last_ts - $now ) <= 7 * DAY_IN_SECONDS ) {
			return array(
				'label'   => __( 'Closing this week', 'northfield-theatre' ),
				'variant' => 'closing',
			);
		}
	}

	if ( ! empty( $event['justAnnounced'] ) ) {
		return array(
			'label'   => __( 'Just announced', 'northfield-theatre' ),
			'variant' => 'announced',
		);
	}

	return null;
}
