<?php
/**
 * GoodMeet Functions
 *
 * @package Goodme
 * @version 1.0.0
 */

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

if ( ! function_exists( 'goodmeet_delete_meeting' ) ) {
	/**
	 * Delete Meeting
	 *
	 * @param int $id Delete Id.
	 *
	 * @return int|boolean
	 *
	 * @since 1.0.0
	 */
	function goodmeet_delete_meeting( $id ) {
		delete_post_meta( $id, 'goodmeet__meeting_settings', null );
		$deleted = wp_delete_post( $id );
		return $deleted;
	}
}


if ( ! function_exists( 'goodmeet_meetings' ) ) {
	/**
	 * Fetch jitsi all meetings
	 *
	 * @return array
	 *
	 * @since 1.0.0
	 */
	function goodmeet_meetings() {

		$user_id = get_current_user_id();

		$args = array(
			'post_type'      => 'goodmeet_meeting',
			'post_status'    => 'published',
			'posts_per_page' => -1,
		);

		// If the user does not have the manage_options capability, limit the query to their own meetings.
		if ( ! current_user_can( 'manage_options' ) ) {
			$args['author'] = $user_id;
		}

		$wp_query = new \WP_Query( $args );
		$results  = $wp_query->posts;

		$meetings = array();

		foreach ( $results as $result ) {
			$meeting         = array();
			$settings        = get_post_meta( $result->ID, 'goodmeet__meeting_settings', true );
			$settings        = maybe_unserialize( $settings );
			$settings['url'] = get_permalink( $result->ID );

			$meeting['id']       = $result->ID;
			$meeting['title']    = $result->post_title;
			$meeting['settings'] = $settings;
			$meeting['date']     = $result->post_date;
			$meetings[]          = $meeting;

		}

		wp_reset_postdata();

		return $meetings;
	}

}


if ( ! function_exists( 'goodmeet_meeting' ) ) {

	/**
	 * Fetch a single meeting from the DB
	 *
	 * @param int $id Meeting Id.
	 *
	 * @return object
	 *
	 * @since 1.0.0
	 */
	function goodmeet_meeting( $id ) {
		$meeting = array();

		$post                = get_post( $id );
		$settings            = get_post_meta( $id, 'goodmeet__meeting_settings', true );
		$meeting_description = get_post_meta( $id, 'meeting_description', true );

		$meeting['id']                  = $post->ID;
		$meeting['title']               = $post->post_title;
		$meeting['settings']            = maybe_unserialize( $settings );
		$meeting['meeting_description'] = $meeting_description;
		$meeting['date']                = $post->post_date;

		return $meeting;
	}
}


if ( ! function_exists( 'goodmeet_timezone_offset' ) ) {
	/**
	 * Retrieve the timezone offset in hours and minutes.
	 *
	 * This function fetches the timezone offset from WordPress options. If the offset is empty,
	 * it defaults to 'UTC'. The offset is returned in the format specified by WordPress options.
	 *
	 * @return string The timezone offset in hours and minutes.
	 */
	function goodmeet_timezone_offset() {
		$fetched_offset = get_option( 'timezone_string' );
		$offset         = empty( $fetched_offset ) ? 'UTC' : $fetched_offset;
		return $offset;
	}

}

if ( ! function_exists( 'goodmeet_convert_to_minutes' ) ) {
	/**
	 * Convert hours and minutes to minutes.
	 *
	 * This function takes the given hour and minute values and converts them into minutes.
	 * It multiplies the hour value by 60 and adds the minute value to get the total minutes.
	 *
	 * @param int $hour The hour value to be converted.
	 * @param int $minute The minute value to be converted.
	 * @return int The total minutes calculated from the provided hour and minute values.
	 */
	function goodmeet_convert_to_minutes( $hour, $minute ) {
		$hour   = $hour * 60;
		$result = $hour + $minute;
		return $result;
	}
}

if ( ! function_exists( 'goodmeet_pro_plugin_exists' ) ) {
	/**
	 * Checks if the MeetingHub Pro plugin is installed.
	 *
	 * @return bool True if MeetingHub Pro plugin exists, false otherwise.
	 */
	function goodmeet_pro_plugin_exists() {
		return file_exists( WP_PLUGIN_DIR . '/goodmeet-pro/goodmeet-pro.php' );
	}
}


if ( ! function_exists( 'goodmeet_insert_meeting' ) ) {
	/**
	 * Inserts a new meeting post into the database.
	 *
	 * @param string $title              The title of the meeting.
	 * @param array  $meeting_settings   The settings for the meeting.
	 * @param string $meeting_description The description of the meeting.
	 *
	 * @return int|WP_Error The ID of the inserted meeting post on success, or a WP_Error object on failure.
	 */
	function goodmeet_insert_meeting( $title, $meeting_settings, $meeting_description ) {
		$un_meeting_settings       = maybe_unserialize( $meeting_settings );
		$meeting_description_array = json_decode( $meeting_description, true );
		$meeting_description       = isset( $meeting_description_array['content'] ) ? wp_kses_post( $meeting_description_array['content'] ) : '';

		$new_meeting = array(
			'post_title'   => $title,
			'post_type'    => 'goodmeet_meeting',
			'post_status'  => 'publish',
			'post_content' => '',
			'meta_input'   => array(
				'goodmeet__meeting_settings' => $meeting_settings,
				'meeting_description'        => $meeting_description,
			),

		);

		$meeting_id = wp_insert_post( $new_meeting );

		$thumbnail_id = $un_meeting_settings['image_id'];

		// Set post thumbnail.
		if ( ! empty( $thumbnail_id ) ) {
			set_post_thumbnail( $meeting_id, $thumbnail_id );
		}

		if ( is_wp_error( $meeting_id ) ) {
			$meeting_id->add_data( array( 'status' => 400 ) );
			return $meeting_id;
		}

		return $meeting_id;
	}

}

if ( ! function_exists( 'goodmeet_update_meeting' ) ) {
	/**
	 * Updates an existing meeting post in the database.
	 *
	 * @param string $title              The new title of the meeting.
	 * @param array  $meeting_settings   The new settings for the meeting.
	 * @param int    $meeting_id         The ID of the meeting post to update.
	 * @param string $meeting_description The new description of the meeting.
	 *
	 * @return int|WP_Error The number of affected rows on success, or a WP_Error object on failure.
	 */
	function goodmeet_update_meeting( $title, $meeting_settings, $meeting_id, $meeting_description ) {
		$un_meeting_settings       = maybe_unserialize( $meeting_settings );
		$meeting_description_array = json_decode( $meeting_description, true );
		$meeting_description       = isset( $meeting_description_array['content'] ) ? wp_kses_post( $meeting_description_array['content'] ) : '';

		$arg = array(
			'ID'           => $meeting_id,
			'post_title'   => $title,
			'post_type'    => 'goodmeet_meeting',
			'post_status'  => 'publish',
			'post_content' => '',
			'meta_input'   => array(
				'goodmeet__meeting_settings' => $meeting_settings,
				'meeting_description'        => $meeting_description,
			),
		);

		$updated = wp_update_post( $arg );

		$thumbnail_id = isset( $un_meeting_settings['image_id'] ) ? $un_meeting_settings['image_id'] : '';

		// Check if the image ID is empty and remove the thumbnail if it is.
		if ( empty( $thumbnail_id ) ) {
			delete_post_thumbnail( $meeting_id );
		} else {
			// Set the post thumbnail if the image ID is not empty.
			set_post_thumbnail( $meeting_id, $thumbnail_id );
		}

		if ( ! $updated ) {
			return new WP_Error(
				'rest_not_updated',
				__( 'Sorry, the address could not be updated.', 'goodmeet' ),
				array( 'status' => 400 )
			);
		}
	}
}

if ( ! function_exists( 'goodmeet_get_gmt_offset' ) ) {
	/**
	 * Get the GMT offset and its value for a given timezone.
	 *
	 * @param string $timezone The timezone identifier, e.g., 'Asia/Dhaka'.
	 *
	 * @return array An array containing the GMT offset string and its value.
	 */
	function goodmeet_get_gmt_offset( $timezone ) {
		$dtz               = new DateTimeZone( $timezone );
		$offset_in_seconds = $dtz->getOffset( new DateTime() );
		$hours             = floor( abs( $offset_in_seconds ) / 3600 );
		$minutes           = floor( ( abs( $offset_in_seconds ) % 3600 ) / 60 );
		$gmt_offset        = ( $offset_in_seconds < 0 ? '-' : '+' ) . sprintf( '%02d:%02d', $hours, $minutes );

		list( $hours, $minutes ) = explode( ':', $gmt_offset );
		$gmt_offset_val          = ( $hours * 3600 ) + ( $minutes * 60 );

		return array(
			'gmt_offset'     => $gmt_offset,
			'gmt_offset_val' => $gmt_offset_val,
		);
	}
}

if ( ! function_exists( 'goodmeet_get_access_control_defaults' ) ) {
	/**
	 * Default values for the access control settings option.
	 *
	 * @return array
	 */
	function goodmeet_get_access_control_defaults() {
		return array(
			'meeting_visibility'    => 'public',
			'visibility_roles'      => array(),
			'default_cohost_users'  => array(),
			'default_cohost_emails' => array(),
		);
	}
}

if ( ! function_exists( 'goodmeet_get_access_control_settings' ) ) {
	/**
	 * Get global access control settings merged with defaults.
	 *
	 * @return array
	 */
	function goodmeet_get_access_control_settings() {
		$saved = get_option( 'goodmeet_access_control_settings', array() );
		if ( ! is_array( $saved ) ) {
			$saved = array();
		}
		return wp_parse_args( $saved, goodmeet_get_access_control_defaults() );
	}
}

if ( ! function_exists( 'goodmeet_user_has_any_role' ) ) {
	/**
	 * Check if a user has any of the given WP roles.
	 *
	 * @param int   $user_id WP user ID.
	 * @param array $roles   Role slugs.
	 * @return bool
	 */
	function goodmeet_user_has_any_role( $user_id, $roles ) {
		if ( empty( $user_id ) || empty( $roles ) || ! is_array( $roles ) ) {
			return false;
		}
		$user = get_userdata( $user_id );
		if ( ! $user || empty( $user->roles ) ) {
			return false;
		}
		return (bool) array_intersect( (array) $user->roles, $roles );
	}
}

if ( ! function_exists( 'goodmeet_get_meeting_settings_array' ) ) {
	/**
	 * Read unserialized meeting settings meta safely.
	 *
	 * @param int $post_id Meeting post ID.
	 * @return array
	 */
	function goodmeet_get_meeting_settings_array( $post_id ) {
		if ( empty( $post_id ) ) {
			return array();
		}
		$raw = get_post_meta( $post_id, 'goodmeet__meeting_settings', true );
		$arr = maybe_unserialize( $raw );
		return is_array( $arr ) ? $arr : array();
	}
}

if ( ! function_exists( 'goodmeet_check_meeting_visibility' ) ) {
	/**
	 * Resolve effective single-meeting-page visibility for a viewer.
	 *
	 * Host (settings.host) and site admins (manage_options) always pass.
	 *
	 * @param int $post_id Meeting post ID.
	 * @param int $user_id Viewer user ID (0 = guest).
	 * @return array { allowed: bool, reason: string }
	 */
	function goodmeet_check_meeting_visibility( $post_id, $user_id = 0 ) {
		$post_id = (int) $post_id;
		$user_id = (int) $user_id;

		$meeting_settings = goodmeet_get_meeting_settings_array( $post_id );

		// Host bypass.
		if ( $user_id > 0 && isset( $meeting_settings['host'] ) && (int) $meeting_settings['host'] === $user_id ) {
			return array(
				'allowed' => true,
				'reason'  => 'host_bypass',
			);
		}

		// Site admin bypass (for debugging / lockout recovery).
		if ( $user_id > 0 && user_can( $user_id, 'manage_options' ) ) {
			return array(
				'allowed' => true,
				'reason'  => 'admin_bypass',
			);
		}

		$per_meeting = isset( $meeting_settings['meeting_visibility'] ) ? $meeting_settings['meeting_visibility'] : 'inherit';
		$global      = goodmeet_get_access_control_settings();

		$effective_visibility = ( 'inherit' === $per_meeting || '' === $per_meeting )
			? $global['meeting_visibility']
			: $per_meeting;

		$effective_roles = ( 'inherit' === $per_meeting || '' === $per_meeting )
			? ( is_array( $global['visibility_roles'] ) ? $global['visibility_roles'] : array() )
			: ( isset( $meeting_settings['visibility_roles_custom'] ) && is_array( $meeting_settings['visibility_roles_custom'] ) ? $meeting_settings['visibility_roles_custom'] : array() );

		switch ( $effective_visibility ) {
			case 'logged_in':
				if ( $user_id <= 0 ) {
					return array(
						'allowed' => false,
						'reason'  => 'login_required',
					);
				}
				return array(
					'allowed' => true,
					'reason'  => 'logged_in_ok',
				);

			case 'role_based':
				if ( $user_id <= 0 ) {
					return array(
						'allowed' => false,
						'reason'  => 'login_required',
					);
				}
				if ( ! goodmeet_user_has_any_role( $user_id, $effective_roles ) ) {
					return array(
						'allowed' => false,
						'reason'  => 'role_denied',
					);
				}
				return array(
					'allowed' => true,
					'reason'  => 'role_ok',
				);

			case 'public':
			default:
				return array(
					'allowed' => true,
					'reason'  => 'public',
				);
		}
	}
}

if ( ! function_exists( 'goodmeet_prepare_google_meet_data' ) ) {
	/**
	 * Prepares meeting data for Webex API.
	 *
	 * @param string $title The title of the meeting.
	 * @param array  $meeting_settings Meeting settings including start time, agenda, password, and more.
	 * @param int    $duration The duration of the meeting in minutes.
	 *
	 * @return array Formatted meeting data for Webex API.
	 */
	function goodmeet_prepare_google_meet_data( $title, $meeting_settings, $duration ) {
		$gmt_array      = goodmeet_get_gmt_offset( $meeting_settings['meeting_timezone'] );
		$gmt_offset_val = $gmt_array['gmt_offset_val'];

		// Calculate timestamps.
		$start_timestamp    = strtotime( $meeting_settings['startDateTime'] ) + $gmt_offset_val;
		$iso_start_datetime = gmdate( 'Y-m-d\TH:i:sP', $start_timestamp );
		$duration_seconds   = $duration * 60;
		$end_timestamp      = $start_timestamp + $duration_seconds;
		$iso_end_datetime   = gmdate( 'Y-m-d\TH:i:sP', $end_timestamp );

		// Prepare meeting array.
		$meeting_arr = array(
			'summary'        => $title,
			'description'    => $meeting_settings['meeting_summary'],
			'start'          => array(
				'dateTime' => $iso_start_datetime,
				'timeZone' => $meeting_settings['meeting_timezone'],
			),
			'end'            => array(
				'dateTime' => $iso_end_datetime,
				'timeZone' => $meeting_settings['meeting_timezone'],
			),
			'timezone'       => $meeting_settings['meeting_timezone'],
			'attendees'      => isset( $meeting_settings['attendees'] ) ? $meeting_settings['attendees'] : array(),
			'reminders'      => array(
				'useDefault' => false,
				'overrides'  => array(
					array(
						'method'  => 'email',
						'minutes' => isset( $meeting_settings['reminder_time'] ) ? $meeting_settings['reminder_time'] : 30,
					),
					array(
						'method'  => 'popup',
						'minutes' => isset( $meeting_settings['reminder_time'] ) ? $meeting_settings['reminder_time'] : 30,
					),
				),
			),
			'sendUpdates'    => isset( $meeting_settings['send_updates'] ) ? $meeting_settings['send_updates'] : 'all',
			'transparency'   => isset( $meeting_settings['transparency'] ) ? $meeting_settings['transparency'] : 'transparent',
			'visibility'     => isset( $meeting_settings['event_visibility'] ) ? $meeting_settings['event_visibility'] : 'public',
			'status'         => isset( $meeting_settings['event_status'] ) ? $meeting_settings['event_status'] : 'confirmed',
			'conferenceData' => array(
				'createRequest' => array(
					'requestId' => 'meet_demo_' . microtime( true ),
				),
			),
		);

		return $meeting_arr;
	}

}
