<?php
/**
 * Zmeet_Zoom_Reports API Class
 *
 * This class manages the API functionality for the ZooMeet plugin settings.
 *
 * @package SOVLIX\ZMEET\API
 */

namespace SOVLIX\ZMEET\API;

use WP_REST_Controller;
use WP_REST_Server;
use WP_Error;

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

if ( ! class_exists( 'Zmeet_Zoom_Reports' ) ) {
	/**
	 * Zmeet_Zoom_Reports Class
	 */
	class Zmeet_Zoom_Reports extends WP_REST_Controller {
		/**
		 * Zoom Api class.
		 *
		 * @var Zmeet_Zoom_Api
		 */
		private $zoom_api;

		/**
		 * Zmeet_Zoom_Reports constructor
		 */
		public function __construct() {
			$this->namespace = 'zmeet/v2';
			$this->rest_base = 'zoom';
			$this->zoom_api  = \SOVLIX\ZMEET\Zoom\Zmeet_Zoom_Api::instance();
		}

		/**
		 * Register REST API routes for users
		 *
		 * @since 1.0.0
		 */
		public function register_routes() {

			register_rest_route(
				$this->namespace,
				'/' . $this->rest_base . '/reports',
				array(
					array(
						'methods'             => WP_REST_Server::READABLE,
						'callback'            => array( $this, 'zmeet_get_zoom_reports' ),
						'permission_callback' => array( $this, 'check_permissions' ),
						'args'                => array(
							'month' => array(
								'required'          => true,
								'validate_callback' => function ( $param, $request, $key ) {
									return is_numeric( $param ) && $param > 0 && $param <= 12;
								},
							),
							'year'  => array(
								'required'          => true,
								'validate_callback' => function ( $param, $request, $key ) {
									return is_numeric( $param ) && strlen( $param ) === 4;
								},
							),
						),
					),
				)
			);

			register_rest_route(
				$this->namespace,
				'/' . $this->rest_base . '/reports/account',
				array(
					array(
						'methods'             => WP_REST_Server::READABLE,
						'callback'            => array( $this, 'zmeet_get_zoom_account_reports' ),
						'permission_callback' => array( $this, 'check_permissions' ),
						'args'                => array(
							'fromDate' => array(
								'required'          => true,
								'validate_callback' => function ( $param, $request, $key ) {
									return preg_match( '/^\d{4}-\d{2}-\d{2}$/', $param );
								},
							),
							'toDate'   => array(
								'required'          => true,
								'validate_callback' => function ( $param, $request, $key ) {
									return preg_match( '/^\d{4}-\d{2}-\d{2}$/', $param );
								},
							),
						),
					),
				)
			);

			/**
			 * Participant list endpoint.
			 *
			 * Supports two use-cases:
			 *   1. Daily Report  → pass `date`  (single day, uses the first active Zoom user)
			 *   2. Account Report → pass `userId` + `fromDate` + `toDate` (date range for a user)
			 *
			 * Required params: `userId` always; either `date` OR `fromDate`+`toDate`.
			 */
			register_rest_route(
				$this->namespace,
				'/' . $this->rest_base . '/reports/participants',
				array(
					array(
						'methods'             => WP_REST_Server::READABLE,
						'callback'            => array( $this, 'zmeet_get_zoom_participants' ),
						'permission_callback' => array( $this, 'check_permissions' ),
						'args'                => array(
							'userId'   => array(
								'required'          => true,
								'validate_callback' => function ( $param ) {
									return ! empty( $param );
								},
							),
							'date'     => array(
								'required'          => false,
								'validate_callback' => function ( $param ) {
									return preg_match( '/^\d{4}-\d{2}-\d{2}$/', $param );
								},
							),
							'fromDate' => array(
								'required'          => false,
								'validate_callback' => function ( $param ) {
									return preg_match( '/^\d{4}-\d{2}-\d{2}$/', $param );
								},
							),
							'toDate'   => array(
								'required'          => false,
								'validate_callback' => function ( $param ) {
									return preg_match( '/^\d{4}-\d{2}-\d{2}$/', $param );
								},
							),
						),
					),
				)
			);

			// Per-meeting participant list (used externally or for future direct look-ups).
			register_rest_route(
				$this->namespace,
				'/' . $this->rest_base . '/reports/meeting-participants',
				array(
					array(
						'methods'             => WP_REST_Server::READABLE,
						'callback'            => array( $this, 'zmeet_get_zoom_meeting_participants' ),
						'permission_callback' => array( $this, 'check_permissions' ),
						'args'                => array(
							'meetingId' => array(
								'required'          => true,
								'validate_callback' => function ( $param ) {
									return ! empty( $param );
								},
							),
						),
					),
				)
			);
		}

		/**
		 * Check if the current user has permission to edit posts.
		 *
		 * This function checks if the current user has the capability to edit posts.
		 * It returns true if the user has the 'edit_posts' capability, and false otherwise.
		 *
		 * @return bool True if the current user can edit posts, false otherwise.
		 */
		public function check_permissions() {
			return current_user_can( 'edit_posts' );
		}

		/**
		 * Retrieves daily reports.
		 *
		 * @param WP_REST_Request $request Request object.
		 *
		 * @return WP_Error|WP_REST_Response
		 */
		public function zmeet_get_zoom_reports( $request ) {
			$month = $request->get_param( 'month' );
			$year  = $request->get_param( 'year' );

			$zoom_response = json_decode( $this->zoom_api->get_daily_report( $month, $year ), true );
			return $zoom_response;
		}

		/**
		 * Retrieves account reports.
		 *
		 * @param WP_REST_Request $request Request object.
		 *
		 * @return WP_Error|WP_REST_Response
		 */
		public function zmeet_get_zoom_account_reports( $request ) {
			$from_date = $request->get_param( 'fromDate' );
			$to_date   = $request->get_param( 'toDate' );

			// Ensure dates are in the correct format.
			$from_date_formatted = gmdate( 'Y-m-d', strtotime( $from_date ) );
			$to_date_formatted   = gmdate( 'Y-m-d', strtotime( $to_date ) );

			$zoom_response = json_decode( $this->zoom_api->get_account_report( $from_date_formatted, $to_date_formatted ), true );
			return $zoom_response;
		}

		/**
		 * Unified participant list handler.
		 *
		 * Works for both:
		 *   • Daily Report  — pass ?userId=...&date=YYYY-MM-DD
		 *   • Account Report — pass ?userId=...&fromDate=YYYY-MM-DD&toDate=YYYY-MM-DD
		 *
		 * Fetches meetings in the requested window, then participant details per meeting.
		 * Requires Zoom Pro, Business, or Enterprise account.
		 *
		 * @param \WP_REST_Request $request Request object.
		 * @return array
		 */
		public function zmeet_get_zoom_participants( $request ) {
			$user_id   = sanitize_text_field( $request->get_param( 'userId' ) );
			$date      = sanitize_text_field( $request->get_param( 'date' ) );
			$from_date = sanitize_text_field( $request->get_param( 'fromDate' ) );
			$to_date   = sanitize_text_field( $request->get_param( 'toDate' ) );

			// Determine the date range.
			if ( ! empty( $date ) ) {
				// Daily Report: single day.
				$from = $date;
				$to   = $date;
			} elseif ( ! empty( $from_date ) && ! empty( $to_date ) ) {
				// Account Report: date range.
				$from = $from_date;
				$to   = $to_date;
			} else {
				return array(
					'success'      => false,
					'message'      => __( 'Please provide a date or date range.', 'zoomeet' ),
					'participants' => array(),
				);
			}

			// Fetch the meetings list for this user and window.
			$meetings_raw = $this->zoom_api->get_meetings_report( $user_id, $from, $to );

			if ( ! $meetings_raw ) {
				return array(
					'success'      => false,
					'message'      => __( 'Unable to connect to the Zoom API. Please check your credentials.', 'zoomeet' ),
					'participants' => array(),
				);
			}

			$meetings_data = json_decode( $meetings_raw, true );

			// Handle Zoom API error codes.
			if ( isset( $meetings_data['code'] ) ) {
				$error_message = isset( $meetings_data['message'] ) ? $meetings_data['message'] : __( 'Zoom API error.', 'zoomeet' );
				if ( in_array( (int) $meetings_data['code'], array( 200, 3001, 124, 300 ), true ) ) {
					$error_message = __( 'This feature requires a Zoom Pro, Business, or Enterprise account. The Reports API is not available on your current Zoom plan.', 'zoomeet' );
				}
				return array(
					'success'      => false,
					'message'      => $error_message,
					'participants' => array(),
				);
			}

			$meetings = isset( $meetings_data['meetings'] ) ? $meetings_data['meetings'] : array();

			if ( empty( $meetings ) ) {
				return array(
					'success'       => true,
					'message'       => '',
					'from'          => $from,
					'to'            => $to,
					'meeting_count' => 0,
					'participants'  => array(),
				);
			}

			// Collect all participants across every meeting in the window.
			$all_participants = array();
			foreach ( $meetings as $meeting ) {
				$meeting_id    = isset( $meeting['uuid'] ) ? $meeting['uuid'] : $meeting['id'];
				$meeting_topic = isset( $meeting['topic'] ) ? $meeting['topic'] : '';
				$start_time    = isset( $meeting['start_time'] ) ? $meeting['start_time'] : '';

				$participants_raw = $this->zoom_api->get_meeting_participants( $meeting_id );
				if ( ! $participants_raw ) {
					continue;
				}

				$participants_data = json_decode( $participants_raw, true );

				if ( isset( $participants_data['participants'] ) && is_array( $participants_data['participants'] ) ) {
					foreach ( $participants_data['participants'] as $p ) {
						$all_participants[] = array(
							'name'          => isset( $p['name'] ) ? $p['name'] : '',
							'email'         => isset( $p['user_email'] ) ? $p['user_email'] : '',
							'join_time'     => isset( $p['join_time'] ) ? $p['join_time'] : '',
							'leave_time'    => isset( $p['leave_time'] ) ? $p['leave_time'] : '',
							'duration'      => isset( $p['duration'] ) ? (int) $p['duration'] : 0,
							'meeting_topic' => $meeting_topic,
							'meeting_start' => $start_time,
							'meeting_id'    => $meeting['id'],
						);
					}
				}
			}

			return array(
				'success'       => true,
				'message'       => '',
				'from'          => $from,
				'to'            => $to,
				'meeting_count' => count( $meetings ),
				'participants'  => $all_participants,
			);
		}

		/**
		 * Per-meeting participant handler.
		 *
		 * Requires Zoom Pro, Business, or Enterprise account.
		 *
		 * @param \WP_REST_Request $request Request object.
		 * @return array
		 */
		public function zmeet_get_zoom_meeting_participants( $request ) {
			$meeting_id = sanitize_text_field( $request->get_param( 'meetingId' ) );

			$raw = $this->zoom_api->get_meeting_participants( $meeting_id );

			if ( ! $raw ) {
				return array(
					'success'      => false,
					'message'      => __( 'Unable to connect to the Zoom API. Please check your credentials.', 'zoomeet' ),
					'participants' => array(),
				);
			}

			$data = json_decode( $raw, true );

			if ( isset( $data['code'] ) ) {
				$error_message = isset( $data['message'] ) ? $data['message'] : __( 'Zoom API error.', 'zoomeet' );
				if ( in_array( (int) $data['code'], array( 200, 3001, 124, 300 ), true ) ) {
					$error_message = __( 'This feature requires a Zoom Pro, Business, or Enterprise account. The Reports API is not available on your current Zoom plan.', 'zoomeet' );
				}
				return array(
					'success'      => false,
					'message'      => $error_message,
					'participants' => array(),
				);
			}

			$participants = array();
			foreach ( isset( $data['participants'] ) ? $data['participants'] : array() as $p ) {
				$participants[] = array(
					'name'       => isset( $p['name'] ) ? $p['name'] : '',
					'email'      => isset( $p['user_email'] ) ? $p['user_email'] : '',
					'join_time'  => isset( $p['join_time'] ) ? $p['join_time'] : '',
					'leave_time' => isset( $p['leave_time'] ) ? $p['leave_time'] : '',
					'duration'   => isset( $p['duration'] ) ? (int) $p['duration'] : 0,
				);
			}

			return array(
				'success'      => true,
				'message'      => '',
				'meeting_id'   => $meeting_id,
				'participants' => $participants,
			);
		}
	}
}
