<?php
/**
 * Class GoogleIntegrationHook
 *
 * Handles the integration with Google Calendar and Google Meet for the booking system.
 */
namespace RadiusTheme\RadiusBooking\Hooks;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}
use DateTime;
use DateTimeZone;
use RadiusTheme\RadiusBooking\Core\Container\Container;
use RadiusTheme\RadiusBooking\Helpers\SettingsHelper;
use RadiusTheme\RadiusBooking\Integrations\GoogleCalendarMeetIntegration;
use RadiusTheme\RadiusBooking\Models\MeetingType;
use RadiusTheme\RadiusBooking\Models\Service;
use RadiusTheme\RadiusBooking\Models\User;
use RadiusTheme\RadiusBooking\Services\AppointmentIntegrationService;

/**
 * Class GoogleIntegrationHook
 *
 * Handles the integration with Google services such as Google Calendar and Google Meet.
 * Hooks into booking-related events to create calendar events and manage service integrations.
 */
class GoogleIntegrationHook {


	/**
	 * Constructor method that sets up actions for Google integration and settings mapping.
	 *
	 * @return void
	 */
	public function __construct() {
		add_action( 'radius_booking_after_create_bookings', array( $this, 'integrate_google' ), 10, 3 );
		add_action( 'radius_booking_meeting_booked', array( $this, 'integrate_google_for_meeting' ), 10, 3 );
		add_action( 'radius_booking_settings_data', array( $this, 'mapGoogleAuthLink' ), 10, 1 );
	}

	/**
	 * Maps the Google authentication link to the settings data.
	 *
	 * @param array $settings_data The existing settings data to be updated with Google authentication link.
	 *
	 * @return array The updated settings data including the Google authentication link.
	 */
	public function mapGoogleAuthLink( $settings_data ) {
		$google = new GoogleCalendarMeetIntegration();

		$settings_data['integrations']['googleCalendar']['auth_url']    = $google->get_auth_url();
		$settings_data['integrations']['googleCalendar']['redirectUri'] = admin_url( 'admin.php?page=radius-booking' );
		$settings_data['integrations']['googleCalendar']['oauth_nonce'] = wp_create_nonce( 'rtrb_google_oauth' );

		return $settings_data;
	}


	/**
	 * Integrates a booking with Google Calendar and Google Meet, creating a calendar event
	 * and updating integration details in the system.
	 *
	 * @param array $bookings The list of booking data, including customer information.
	 * @param array $data The associated data for the appointment, such as service and employee IDs.
	 * @param int $appointment_id The unique identifier of the appointment being processed.
	 *
	 * @return void
	 */
	public function integrate_google( $bookings, $data, $appointment_id ) {

		$settings    = SettingsHelper::get_setting( 'integrations' );
		$is_calender = $settings['googleCalendar']['enabled'] ?? false;
		if ( ! $is_calender ) {
			return;
		}

		// ✅ Validate required data
		if ( empty( $data['service_id'] ) || empty( $data['employee_id'] ) || empty( $bookings[0]['customer_info']['email'] ) ) {
			return;
		}

		$service_id  = $data['service_id'];
		$employee_id = $data['employee_id'];

		// ✅ Load service and settings
		$service = Service::find( $service_id );
		if ( ! $service ) {
			return;
		}

		$settings                   = $service->integrations();
		$is_google_calendar_enabled = ! empty( $settings['googleCalender'] );
		$is_meet_enabled            = ! empty( $settings['googleMeet'] );
		// ✅ Only continue if both Google Calendar & Meet are enabled
		if ( ! $is_google_calendar_enabled && ! $is_meet_enabled ) {
			return;
		}

		// ✅ Load employee & customer info
		$employee = User::find( $employee_id );
		if ( ! $employee ) {
			return;
		}

		$employee_email = $employee->get_email() ?? '';
		$customer_email = $bookings[0]['customer_info']['email'] ?? '';

		if ( empty( $employee_email ) || empty( $customer_email ) ) {
			return;
		}

		// ✅ Get employee name (fixing wrong variable used for profile)
		$profile            = $employee->profile()->get();
		$employee_full_name = trim( ( $profile->first_name ?? '' ) . ' ' . ( $profile->last_name ?? '' ) );
		$customer_full_name = $bookings[0]['customer_info']['first_name'] . ' ' . $bookings[0]['customer_info']['last_name'];
		$duration           = $service->get_duration();

		// ✅ Prepare Google Calendar data
		$tz = wp_timezone_string() ?? 'UTC';

		try {
			$start = new DateTime( "{$data['appointment_date']} {$data['start_time']}", new DateTimeZone( $tz ) );
			$end   = new DateTime( "{$data['appointment_date']} {$data['end_time']}", new DateTimeZone( $tz ) );
		} catch ( Exception $e ) {
			error_log( 'Google integration time parse failed: ' . $e->getMessage() );

			return;
		}

		$start_date = $start->format( 'Y-m-d\TH:i:sP' );
		$end_date   = $end->format( 'Y-m-d\TH:i:sP' );

		// ✅ Create Google Calendar event
		$google = new GoogleCalendarMeetIntegration();

		try {
			$title = sprintf( '%s Appointment #%d', $service->get_name(), $appointment_id );

			$description = sprintf(
				"Appointment Details:\nService: %s\nEmployee: %s\nCustomer: %s\nDate: %s\nDuration: %s minutes\n\nBooked via Radius Booking.",
				$service->get_name(),
				$employee_full_name,
				$customer_full_name,
				wp_date( 'F j, Y g:i A', strtotime( $start_date ) ),
				$duration / 60
			);
			$event       = $google->create_event(
				$is_meet_enabled,
				'primary',
				$title,
				$start_date,
				$end_date,
				$description,
				array( $employee_email, $customer_email )
			);
			if ( $event ) {
				$integrateService = Container::resolve( AppointmentIntegrationService::class );
				$payload          = array(
					'provider'             => 'google_calendar',
					'external_event_id'    => $event['id'] ?? null,
					'external_calendar_id' => $event['organizer']['email'] ?? null,
					'meeting_url'          => $event['hangoutLink'] ?? null,
					'join_url'             => $event['hangoutLink'] ?? null,
					'start_url'            => $event['hangoutLink'] ?? null,
					'meta'                 => maybe_serialize( $event ?? array() ),
					'status'               => $event['status'] ?? 'created',
				);
				$integrateService->storeOrUpdate( $appointment_id, 'google_calendar', $payload );
			}
		} catch ( Exception $e ) {
			error_log( 'Google Calendar event creation failed: ' . $e->getMessage() );
		}
	}

	/**
	 * Integrates a meeting booking with Google Calendar and Google Meet.
	 *
	 * @param object $appointment  The created appointment.
	 * @param object $meeting_type The meeting type.
	 * @param array  $data         The original booking data.
	 *
	 * @return void
	 */
	public function integrate_google_for_meeting( $appointment, $meeting_type, $data ) {
		$settings    = SettingsHelper::get_setting( 'integrations' );
		$is_calender = $settings['googleCalendar']['enabled'] ?? false;
		if ( ! $is_calender ) {
			return;
		}

		// Check meeting type integration settings (handle both model and stdClass).
		$mt_settings                = $this->getMeetingTypeIntegrations( $meeting_type );
		$is_google_calendar_enabled = ! empty( $mt_settings['googleCalender'] );
		$is_meet_enabled            = ! empty( $mt_settings['googleMeet'] );

		if ( ! $is_google_calendar_enabled && ! $is_meet_enabled ) {
			return;
		}

		$employee_id = $meeting_type->employee_id;
		$employee    = User::find( $employee_id );
		if ( ! $employee ) {
			return;
		}

		$employee_email = $employee->get_email() ?? '';
		$customer_email = sanitize_email( $data['email'] ?? '' );

		if ( empty( $employee_email ) || empty( $customer_email ) ) {
			return;
		}

		$profile            = $employee->profile()->get();
		$employee_full_name = trim( ( $profile->first_name ?? '' ) . ' ' . ( $profile->last_name ?? '' ) );
		$customer_full_name = trim(
			sanitize_text_field( $data['first_name'] ?? '' ) . ' ' .
			sanitize_text_field( $data['last_name'] ?? '' )
		);

		$appointment_id = $appointment->get_id();
		$tz             = wp_timezone_string() ?? 'UTC';

		try {
			$start = new DateTime(
				"{$appointment->appointment_date} {$appointment->start_time}",
				new DateTimeZone( $tz )
			);
			$end = new DateTime(
				"{$appointment->appointment_date} {$appointment->end_time}",
				new DateTimeZone( $tz )
			);
		} catch ( \Exception $e ) {
			error_log( 'Google meeting integration time parse failed: ' . $e->getMessage() );
			return;
		}

		$start_date = $start->format( 'Y-m-d\TH:i:sP' );
		$end_date   = $end->format( 'Y-m-d\TH:i:sP' );

		$google = new GoogleCalendarMeetIntegration();

		try {
			$title = sprintf( '%s Meeting #%d', $meeting_type->get_name(), $appointment_id );

			$description = sprintf(
				"Meeting Details:\nMeeting Type: %s\nHost: %s\nGuest: %s\nDate: %s\nDuration: %s minutes\n\nBooked via Radius Booking.",
				$meeting_type->get_name(),
				$employee_full_name,
				$customer_full_name,
				wp_date( 'F j, Y g:i A', strtotime( $start_date ) ),
				$meeting_type->get_duration()
			);

			$event = $google->create_event(
				$is_meet_enabled,
				'primary',
				$title,
				$start_date,
				$end_date,
				$description,
				array( $employee_email, $customer_email )
			);

			if ( $event ) {
				$integrateService = Container::resolve( AppointmentIntegrationService::class );
				$payload          = array(
					'provider'             => 'google_calendar',
					'external_event_id'    => $event['id'] ?? null,
					'external_calendar_id' => $event['organizer']['email'] ?? null,
					'meeting_url'          => $event['hangoutLink'] ?? null,
					'join_url'             => $event['hangoutLink'] ?? null,
					'start_url'            => $event['hangoutLink'] ?? null,
					'meta'                 => maybe_serialize( $event ?? array() ),
					'status'               => $event['status'] ?? 'created',
				);
				$integrateService->storeOrUpdate( $appointment_id, 'google_calendar', $payload );
			}
		} catch ( \Exception $e ) {
			error_log( 'Google Calendar meeting event creation failed: ' . $e->getMessage() );
		}
	}

	/**
	 * Safely get integration settings from a MeetingType model or stdClass.
	 *
	 * @param object $meeting_type Model or stdClass.
	 *
	 * @return array
	 */
	private function getMeetingTypeIntegrations( $meeting_type ): array {
		if ( method_exists( $meeting_type, 'integrations' ) ) {
			return $meeting_type->integrations();
		}

		$raw = $meeting_type->settings ?? null;
		if ( is_string( $raw ) && ! empty( $raw ) ) {
			$decoded = json_decode( $raw, true );
			if ( is_array( $decoded ) ) {
				return $decoded['integrations'] ?? array();
			}
			$unserialized = maybe_unserialize( $raw );
			if ( is_array( $unserialized ) ) {
				return $unserialized['integrations'] ?? array();
			}
		}
		if ( is_array( $raw ) ) {
			return $raw['integrations'] ?? array();
		}

		return array();
	}
}
