<?php

declare(strict_types=1);

/**
 * HVAC Community Events Dashboard Data Handler
 *
 * Retrieves and calculates data needed for the Trainer Dashboard.
 *
 * @package    HVAC Community Events
 * @subpackage Includes
 * @author     Roo
 * @version    1.0.0
 */

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class HVAC_Dashboard_Data
 *
 * Handles fetching and processing data for the trainer dashboard.
 */
class HVAC_Dashboard_Data {

	/**
	 * Constructor with promoted property.
	 *
	 * @param int $user_id The ID of the trainer user.
	 */
	public function __construct(
		private int $user_id
	) {
		// Property is automatically assigned via promotion
	}

	/**
	 * Get the total number of events created by the trainer.
	 *
	 * @return int
	 */
	public function get_total_events_count() {
		global $wpdb;

		try {
			// Check if TEC is available
			if ( ! class_exists( 'Tribe__Events__Main' ) ) {
				return 0;
			}

			// Cache key based on user ID
			$cache_key = 'hvac_dashboard_total_events_' . $this->user_id;
			$count = wp_cache_get( $cache_key, 'hvac_dashboard' );

			if ( false === $count ) {
				// Use direct database query to avoid TEC query hijacking
				$count = $wpdb->get_var( $wpdb->prepare(
					"SELECT COUNT(*) FROM {$wpdb->posts}
					 WHERE post_type = %s
					 AND post_author = %d
					 AND post_status IN ('publish', 'future', 'draft', 'pending', 'private')",
					Tribe__Events__Main::POSTTYPE,
					$this->user_id
				) );
				
				// Handle database errors
				if ( $wpdb->last_error ) {
					$this->log_error( 'Database error in get_total_events_count', $wpdb->last_error );
					return 0;
				}
				
				// Cache for 1 hour
				wp_cache_set( $cache_key, $count, 'hvac_dashboard', HOUR_IN_SECONDS );
			}
			
			return (int) $count;
		} catch ( Exception $e ) {
			$this->log_error( 'Exception in get_total_events_count', $e->getMessage() );
			return 0;
		}
	}

	/**
	 * Get the number of upcoming events for the trainer.
	 *
	 * @return int
	 */
	public function get_upcoming_events_count() {
		global $wpdb;

		// Check if TEC is available
		if ( ! class_exists( 'Tribe__Events__Main' ) ) {
			return 0;
		}

		// Cache key based on user ID
		$cache_key = 'hvac_dashboard_upcoming_events_' . $this->user_id;
		$count = wp_cache_get( $cache_key, 'hvac_dashboard' );

		if ( false === $count ) {
			$today = date( 'Y-m-d H:i:s' );

			// Use direct database query to avoid TEC query hijacking
			$count = $wpdb->get_var( $wpdb->prepare(
				"SELECT COUNT(*) FROM {$wpdb->posts} p
				 LEFT JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id AND pm.meta_key = '_EventStartDate'
				 WHERE p.post_type = %s
				 AND p.post_author = %d
				 AND p.post_status IN ('publish', 'future')
				 AND (pm.meta_value >= %s OR pm.meta_value IS NULL)",
				Tribe__Events__Main::POSTTYPE,
				$this->user_id,
				$today
			) );
			
			// Cache for 15 minutes (shorter for time-sensitive data)
			wp_cache_set( $cache_key, $count, 'hvac_dashboard', 15 * MINUTE_IN_SECONDS );
		}
		
		return (int) $count;
	}

	/**
	 * Get the number of past events for the trainer.
	 *
	 * @return int
	 */
	public function get_past_events_count() {
		global $wpdb;

		// Check if TEC is available
		if ( ! class_exists( 'Tribe__Events__Main' ) ) {
			return 0;
		}

		// Cache key based on user ID
		$cache_key = 'hvac_dashboard_past_events_' . $this->user_id;
		$count = wp_cache_get( $cache_key, 'hvac_dashboard' );

		if ( false === $count ) {
			$today = date( 'Y-m-d H:i:s' );

			// Use direct database query to avoid TEC query hijacking
			$count = $wpdb->get_var( $wpdb->prepare(
				"SELECT COUNT(*) FROM {$wpdb->posts} p
				 LEFT JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id AND pm.meta_key = '_EventEndDate'
				 WHERE p.post_type = %s
				 AND p.post_author = %d
				 AND p.post_status IN ('publish', 'private')
				 AND pm.meta_value < %s",
				Tribe__Events__Main::POSTTYPE,
				$this->user_id,
				$today
			) );
			
			// Cache for 1 hour
			wp_cache_set( $cache_key, $count, 'hvac_dashboard', HOUR_IN_SECONDS );
		}
		
		return (int) $count;
	}

	/**
	 * Get the total number of tickets sold across all the trainer's events.
	 *
	 * @return int
	 */
	public function get_total_tickets_sold() {
		global $wpdb;
		
		// Cache key based on user ID
		$cache_key = 'hvac_dashboard_tickets_sold_' . $this->user_id;
		$total = wp_cache_get( $cache_key, 'hvac_dashboard' );
		
		if ( false === $total ) {
			// Count TEC Commerce attendees
			$tec_commerce_count = $wpdb->get_var( $wpdb->prepare(
				"SELECT COUNT(*) FROM {$wpdb->posts} p
				 INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id AND pm.meta_key = '_tec_tickets_commerce_event'
				 WHERE p.post_type = %s 
				 AND pm.meta_value IN (
					 SELECT ID FROM {$wpdb->posts} 
					 WHERE post_type = %s 
					 AND post_author = %d 
					 AND post_status IN ('publish', 'private')
				 )",
				'tec_tc_attendee',
				'tribe_events',
				$this->user_id
			) );
			
			// Count legacy Tribe PayPal attendees
			$tribe_tpp_count = $wpdb->get_var( $wpdb->prepare(
				"SELECT COUNT(*) FROM {$wpdb->posts} p
				 INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id AND pm.meta_key = '_tribe_tpp_event'
				 WHERE p.post_type = %s 
				 AND pm.meta_value IN (
					 SELECT ID FROM {$wpdb->posts} 
					 WHERE post_type = %s 
					 AND post_author = %d 
					 AND post_status IN ('publish', 'private')
				 )",
				'tribe_tpp_attendees',
				'tribe_events',
				$this->user_id
			) );
			
			// Note: RSVP attendees are not counted as "tickets sold" since they are free registrations
			$total = (int) ($tec_commerce_count + $tribe_tpp_count);
			
			// Cache for 30 minutes
			wp_cache_set( $cache_key, $total, 'hvac_dashboard', 30 * MINUTE_IN_SECONDS );
		}
		
		return $total;
	}

	/**
	 * Get the total revenue generated across all the trainer's events.
	 *
	 * @return float
	 */
	public function get_total_revenue() {
		global $wpdb;
		
		// Cache key based on user ID
		$cache_key = 'hvac_dashboard_revenue_' . $this->user_id;
		$total_revenue = wp_cache_get( $cache_key, 'hvac_dashboard' );
		
		if ( false === $total_revenue ) {
			// Get TEC Commerce revenue
			$tec_commerce_revenue = $wpdb->get_var( $wpdb->prepare(
			"SELECT SUM(CAST(pm_price.meta_value AS DECIMAL(10,2))) 
			FROM {$wpdb->posts} p
			INNER JOIN {$wpdb->postmeta} pm_event ON p.ID = pm_event.post_id AND pm_event.meta_key = '_tec_tickets_commerce_event'
			INNER JOIN {$wpdb->postmeta} pm_price ON p.ID = pm_price.post_id AND pm_price.meta_key = '_tec_tickets_commerce_price_paid'
			WHERE p.post_type = %s 
			AND pm_event.meta_value IN (
				SELECT ID FROM {$wpdb->posts} 
				WHERE post_type = %s 
				AND post_author = %d 
				AND post_status IN ('publish', 'private')
			)",
			'tec_tc_attendee',
			'tribe_events',
			$this->user_id
		) );
		
		// Get legacy Tribe PayPal revenue
		$tribe_tpp_revenue = $wpdb->get_var( $wpdb->prepare(
			"SELECT SUM(
				CASE 
					WHEN pm_price1.meta_value IS NOT NULL THEN CAST(pm_price1.meta_value AS DECIMAL(10,2))
					WHEN pm_price2.meta_value IS NOT NULL THEN CAST(pm_price2.meta_value AS DECIMAL(10,2))
					WHEN pm_price3.meta_value IS NOT NULL THEN CAST(pm_price3.meta_value AS DECIMAL(10,2))
					ELSE 0
				END
			) 
			FROM {$wpdb->posts} p
			INNER JOIN {$wpdb->postmeta} pm_event ON p.ID = pm_event.post_id AND pm_event.meta_key = '_tribe_tpp_event'
			LEFT JOIN {$wpdb->postmeta} pm_price1 ON p.ID = pm_price1.post_id AND pm_price1.meta_key = '_tribe_tpp_ticket_price'
			LEFT JOIN {$wpdb->postmeta} pm_price2 ON p.ID = pm_price2.post_id AND pm_price2.meta_key = '_paid_price'
			LEFT JOIN {$wpdb->postmeta} pm_price3 ON p.ID = pm_price3.post_id AND pm_price3.meta_key = '_tribe_tpp_price'
			WHERE p.post_type = %s 
			AND pm_event.meta_value IN (
				SELECT ID FROM {$wpdb->posts} 
				WHERE post_type = %s 
				AND post_author = %d 
				AND post_status IN ('publish', 'private')
			)",
			'tribe_tpp_attendees',
			'tribe_events',
			$this->user_id
		) );
		
			// Note: RSVP attendees typically don't have revenue (free tickets)
			
			$total_revenue = (float) (($tec_commerce_revenue ?: 0.00) + ($tribe_tpp_revenue ?: 0.00));
			
			// Cache for 30 minutes
			wp_cache_set( $cache_key, $total_revenue, 'hvac_dashboard', 30 * MINUTE_IN_SECONDS );
		}
		
		return $total_revenue;
	}

	/**
	 * Get the annual revenue target set by the trainer.
	 *
	 * @return float|null Returns the target as a float, or null if not set.
	 */
	public function get_annual_revenue_target() {
		$target = get_user_meta( $this->user_id, 'annual_revenue_target', true );
		return ! empty( $target ) && is_numeric( $target ) ? (float) $target : null;
	}

	/**
	 * Get the data needed for the events table on the dashboard.
	 *
	 * @param array $args Query arguments including:
	 *   - 'status' (string): Event status filter ('all', 'publish', 'future', 'draft', 'pending', 'private')
	 *   - 'search' (string): Search term for event names
	 *   - 'orderby' (string): Column to sort by ('date', 'name', 'status', 'capacity', 'sold', 'revenue')
	 *   - 'order' (string): Sort order ('ASC' or 'DESC')
	 *   - 'page' (int): Current page number
	 *   - 'per_page' (int): Number of events per page
	 *   - 'date_from' (string): Start date filter (Y-m-d format)
	 *   - 'date_to' (string): End date filter (Y-m-d format)
	 * @return array Contains 'events' array and 'pagination' data
	 */
	public function get_events_table_data( $args = array() ) {
		// Default arguments
		$defaults = array(
			'status' => 'all',
			'search' => '',
			'orderby' => 'date',
			'order' => 'DESC',
			'page' => 1,
			'per_page' => 10,
			'date_from' => '',
			'date_to' => ''
		);
		
		$args = wp_parse_args( $args, $defaults );
		
		// Use direct database approach since TEC interferes with WP_Query
		return $this->get_events_table_data_direct( $args );
	}
	
	/**
	 * Get events table data using direct database queries (bypassing TEC query interference)
	 */
	private function get_events_table_data_direct( $args ) {
		global $wpdb;
		
		$events_data = [];
		$valid_statuses = array( 'publish', 'future', 'draft', 'pending', 'private' );
		
		// Build WHERE clauses
		$where_clauses = array(
			'p.post_type = %s',
			'p.post_author = %d'
		);
		$where_values = array( 'tribe_events', $this->user_id );
		
		// Status filter
		if ( 'all' === $args['status'] || ! in_array( $args['status'], $valid_statuses, true ) ) {
			$status_placeholders = implode( ',', array_fill( 0, count( $valid_statuses ), '%s' ) );
			$where_clauses[] = "p.post_status IN ($status_placeholders)";
			$where_values = array_merge( $where_values, $valid_statuses );
		} else {
			$where_clauses[] = 'p.post_status = %s';
			$where_values[] = $args['status'];
		}
		
		// Search filter
		if ( ! empty( $args['search'] ) ) {
			$where_clauses[] = 'p.post_title LIKE %s';
			$where_values[] = '%' . $wpdb->esc_like( $args['search'] ) . '%';
		}
		
		// Date range filters
		if ( ! empty( $args['date_from'] ) ) {
			$where_clauses[] = "pm_start.meta_value >= %s";
			$where_values[] = $args['date_from'] . ' 00:00:00';
		}
		
		if ( ! empty( $args['date_to'] ) ) {
			$where_clauses[] = "pm_start.meta_value <= %s";
			$where_values[] = $args['date_to'] . ' 23:59:59';
		}
		
		// Build ORDER BY clause
		$order_column = 'p.post_date';
		switch ( $args['orderby'] ) {
			case 'name':
				$order_column = 'p.post_title';
				break;
			case 'status':
				$order_column = 'p.post_status';
				break;
			case 'date':
				$order_column = 'COALESCE(pm_start.meta_value, p.post_date)';
				break;
			case 'capacity':
				$order_column = 'capacity';
				break;
			case 'sold':
				$order_column = 'sold';
				break;
			case 'revenue':
				$order_column = 'revenue';
				break;
		}
		$order_dir = ( strtoupper( $args['order'] ) === 'ASC' ) ? 'ASC' : 'DESC';
		
		// Calculate offset for pagination
		$offset = ( $args['page'] - 1 ) * $args['per_page'];
		
		// Build the complete SQL query
		$where_sql = implode( ' AND ', $where_clauses );
		
		// First, get total count for pagination
		$count_sql = "SELECT COUNT(DISTINCT p.ID) 
				FROM {$wpdb->posts} p
				LEFT JOIN {$wpdb->postmeta} pm_start ON p.ID = pm_start.post_id AND pm_start.meta_key = '_EventStartDate'
				WHERE $where_sql";
		
		$total_items = $wpdb->get_var( $wpdb->prepare( $count_sql, $where_values ) );
		
		// Main query with joins for all needed data
		$sql = "SELECT 
				p.ID, 
				p.post_title, 
				p.post_status, 
				p.post_date,
				COALESCE(pm_start.meta_value, p.post_date) as event_date,
				(
					(SELECT COUNT(*) 
					 FROM {$wpdb->posts} attendees
					 INNER JOIN {$wpdb->postmeta} pm_event ON attendees.ID = pm_event.post_id AND pm_event.meta_key = '_tec_tickets_commerce_event'
					 WHERE attendees.post_type = 'tec_tc_attendee' AND pm_event.meta_value = p.ID) +
					(SELECT COUNT(*) 
					 FROM {$wpdb->posts} attendees
					 INNER JOIN {$wpdb->postmeta} pm_event ON attendees.ID = pm_event.post_id AND pm_event.meta_key = '_tribe_tpp_event'
					 WHERE attendees.post_type = 'tribe_tpp_attendees' AND pm_event.meta_value = p.ID) +
					0 /* RSVP attendees not counted as tickets sold (free registrations) */
				) as sold,
				(
					COALESCE((SELECT SUM(CAST(pm_price.meta_value AS DECIMAL(10,2)))
					 FROM {$wpdb->posts} attendees
					 INNER JOIN {$wpdb->postmeta} pm_event ON attendees.ID = pm_event.post_id AND pm_event.meta_key = '_tec_tickets_commerce_event'
					 INNER JOIN {$wpdb->postmeta} pm_price ON attendees.ID = pm_price.post_id AND pm_price.meta_key = '_tec_tickets_commerce_price_paid'
					 WHERE attendees.post_type = 'tec_tc_attendee' AND pm_event.meta_value = p.ID), 0) +
					COALESCE((SELECT SUM(
						CASE 
							WHEN pm_price1.meta_value IS NOT NULL THEN CAST(pm_price1.meta_value AS DECIMAL(10,2))
							WHEN pm_price2.meta_value IS NOT NULL THEN CAST(pm_price2.meta_value AS DECIMAL(10,2))
							WHEN pm_price3.meta_value IS NOT NULL THEN CAST(pm_price3.meta_value AS DECIMAL(10,2))
							ELSE 0
						END
					)
					 FROM {$wpdb->posts} attendees
					 INNER JOIN {$wpdb->postmeta} pm_event ON attendees.ID = pm_event.post_id AND pm_event.meta_key = '_tribe_tpp_event'
					 LEFT JOIN {$wpdb->postmeta} pm_price1 ON attendees.ID = pm_price1.post_id AND pm_price1.meta_key = '_tribe_tpp_ticket_price'
					 LEFT JOIN {$wpdb->postmeta} pm_price2 ON attendees.ID = pm_price2.post_id AND pm_price2.meta_key = '_paid_price'
					 LEFT JOIN {$wpdb->postmeta} pm_price3 ON attendees.ID = pm_price3.post_id AND pm_price3.meta_key = '_tribe_tpp_price'
					 WHERE attendees.post_type = 'tribe_tpp_attendees' AND pm_event.meta_value = p.ID), 0)
				) as revenue,
				50 as capacity
				FROM {$wpdb->posts} p
				LEFT JOIN {$wpdb->postmeta} pm_start ON p.ID = pm_start.post_id AND pm_start.meta_key = '_EventStartDate'
				WHERE $where_sql
				ORDER BY $order_column $order_dir
				LIMIT %d OFFSET %d";
		
		$query_values = array_merge( $where_values, array( $args['per_page'], $offset ) );
		$events = $wpdb->get_results( $wpdb->prepare( $sql, $query_values ) );

		if ( ! empty( $events ) ) {
			foreach ( $events as $event ) {
				$event_id = $event->ID;
				$start_date_ts = $event->event_date ? strtotime( $event->event_date ) : strtotime( $event->post_date );
				
				// Build event data array (matching template expectations)
				$events_data[] = array(
					'id'            => $event_id,
					'name'          => $event->post_title,
					'status'        => $event->post_status,
					'start_date_ts' => $start_date_ts,
					'link'          => get_permalink( $event_id ),
					'organizer_id'  => $this->user_id,
					'capacity'      => (int) $event->capacity,
					'sold'          => (int) $event->sold,
					'revenue'       => (float) $event->revenue,
				);
			}
		}

		// Calculate pagination data
		$total_pages = ceil( $total_items / $args['per_page'] );
		
		return array(
			'events' => $events_data,
			'pagination' => array(
				'total_items' => $total_items,
				'total_pages' => $total_pages,
				'current_page' => $args['page'],
				'per_page' => $args['per_page'],
				'has_prev' => $args['page'] > 1,
				'has_next' => $args['page'] < $total_pages
			)
		);
	}

	/**
	 * Clear all cached data for this user
	 *
	 * This should be called whenever data changes (event created/updated/deleted)
	 */
	public function clear_cache() {
		$cache_keys = array(
			'hvac_dashboard_total_events_' . $this->user_id,
			'hvac_dashboard_upcoming_events_' . $this->user_id,
			'hvac_dashboard_past_events_' . $this->user_id,
			'hvac_dashboard_tickets_sold_' . $this->user_id,
			'hvac_dashboard_revenue_' . $this->user_id,
		);
		
		foreach ( $cache_keys as $key ) {
			wp_cache_delete( $key, 'hvac_dashboard' );
		}
	}
	
	/**
	 * Log errors for debugging
	 * 
	 * @param string $message Error message
	 * @param mixed $data Additional data to log
	 */
	private function log_error( $message, $data = null ) {
		if ( defined( 'WP_DEBUG' ) && WP_DEBUG && defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) {
			$log_message = '[HVAC Dashboard Data] ' . $message;
			if ( $data ) {
				$log_message .= ' | Data: ' . print_r( $data, true );
			}
			error_log( $log_message );
		}
	}
	
	/**
	 * Count the number of attendees for an event by querying attendee posts
	 *
	 * @param int $event_id Event ID to count attendees for
	 * @return int Number of attendees found
	 */
	private function count_event_attendees( $event_id ) {
		$attendee_count = 0;
		
		// Check if Event Tickets is active
		if (class_exists('Tribe__Tickets__Tickets_Handler') && method_exists(Tribe__Tickets__Tickets_Handler::instance(), 'get_attendees_by_id')) {
			$attendees = Tribe__Tickets__Tickets_Handler::instance()->get_attendees_by_id($event_id);
			if (is_array($attendees)) {
				$attendee_count = count($attendees);
			}
		} else {
			// Fallback to direct query if Event Tickets not available
			$attendees_query = new WP_Query([
				'post_type' => 'tribe_tpp_attendees',
				'posts_per_page' => -1,
				'fields' => 'ids',
				'meta_query' => [
					[
						'key' => '_tribe_tpp_event',
						'value' => $event_id,
						'compare' => '=',
					],
				],
			]);
			$attendee_count = $attendees_query->found_posts;
		}
		
		return $attendee_count;
	}
	
	/**
	 * Calculate total revenue for an event by summing ticket prices
	 *
	 * @param int $event_id Event ID to calculate revenue for
	 * @return float Total revenue calculated
	 */
	private function calculate_event_revenue( $event_id ) {
		$total_revenue = 0.0;
		
		// Check if Event Tickets is active
		if (class_exists('Tribe__Tickets__Tickets_Handler') && method_exists(Tribe__Tickets__Tickets_Handler::instance(), 'get_attendees_by_id')) {
			$attendees = Tribe__Tickets__Tickets_Handler::instance()->get_attendees_by_id($event_id);
			
			if (is_array($attendees)) {
				foreach ($attendees as $attendee) {
					// Extract price - structure might vary based on ticket provider
					$price = 0;
					if (isset($attendee['price']) && is_numeric($attendee['price'])) {
						$price = (float)$attendee['price'];
					} elseif (isset($attendee['price_paid']) && is_numeric($attendee['price_paid'])) {
						$price = (float)$attendee['price_paid'];
					}
					
					$total_revenue += $price;
				}
			}
		} else {
			// Fallback to direct calculation if Event Tickets not available
			// First get all tickets for this event to get prices
			$tickets_query = new WP_Query([
				'post_type' => 'tribe_tpp_tickets',
				'posts_per_page' => -1,
				'meta_query' => [
					[
						'key' => '_tribe_tpp_for_event',
						'value' => $event_id,
						'compare' => '=',
					],
				],
			]);
			
			if ($tickets_query->have_posts()) {
				while ($tickets_query->have_posts()) {
					$tickets_query->the_post();
					$ticket_id = get_the_ID();
					$price = get_post_meta($ticket_id, '_price', true);
					$sold = get_post_meta($ticket_id, '_tribe_tpp_sold', true);
					
					if (is_numeric($price) && is_numeric($sold)) {
						$total_revenue += ((float)$price * (int)$sold);
					}
				}
				wp_reset_postdata();
			}
		}
		
		return $total_revenue;
	}
} // End class HVAC_Dashboard_Data