<?php
/**
 * LatePoint Update Booking Action
 *
 * Handles updating bookings in LatePoint through SureForms.
 *
 * @package SureForms
 * @since 1.13.0
 */

namespace SRFM_Pro\Inc\Pro\Native_Integrations\Integrations\LatePoint\Actions;

use SRFM_Pro\Inc\Pro\Native_Integrations\Integrations\LatePoint\LatePoint_Integration;
use SRFM_Pro\Inc\Pro\Native_Integrations\WordPress_Action;
use SRFM_Pro\Inc\Traits\Get_Instance;

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

/**
 * Update Booking Action Class
 *
 * @since 1.13.0
 */
class Update_Booking extends WordPress_Action {
	use Get_Instance;

	/**
	 * Integration name
	 *
	 * @var string
	 * @since 1.13.0
	 */
	protected $integration = 'latepoint';

	/**
	 * Action name
	 *
	 * @var string
	 * @since 1.13.0
	 */
	protected $action = 'update_booking';

	/**
	 * Execute the update booking action
	 *
	 * @param array $data Form submission data.
	 * @return array Action result.
	 * @throws \Exception If booking update fails.
	 * @since 1.13.0
	 */
	protected function execute( $data ) {
		try {
			$booking_id = isset( $data['booking_id'] ) ? intval( $data['booking_id'] ) : null;

			if ( ! $booking_id ) {
				throw new \Exception( 'Booking ID not provided.' );
			}

			$booking = new \OsBookingModel( $booking_id );

			if ( ! isset( $booking->id ) || ! $booking->id ) {
				throw new \Exception( 'Booking not found.' );
			}

			// Store original booking data for action hooks.
			$old_booking = clone $booking;

			// Convert time format to minutes.
			$convert_to_minutes = static function( $time ) {
				if ( $time ) {
					// Handle both 12-hour (HH:MM AM/PM) and 24-hour (HH:MM) formats.
					$time = trim( $time );

					// Try to parse as 12-hour format first (with AM/PM).
					if ( preg_match( '/^(\d{1,2}):(\d{2})\s*(AM|PM)$/i', $time, $matches ) ) {
						$hours   = (int) $matches[1];
						$minutes = (int) $matches[2];
						$period  = strtoupper( $matches[3] );

						// Convert to 24-hour format.
						if ( 'PM' === $period && 12 !== $hours ) {
							$hours += 12;
						} elseif ( 'AM' === $period && 12 === $hours ) {
							$hours = 0;
						}

						return ( $hours * 60 ) + $minutes;
					}

					// Try to parse as 24-hour format (HH:MM).
					if ( preg_match( '/^(\d{1,2}):(\d{2})$/', $time, $matches ) ) {
						$hours   = (int) $matches[1];
						$minutes = (int) $matches[2];

						// Validate 24-hour format.
						if ( $hours > 23 || $minutes > 59 ) {
							throw new \Exception( 'Invalid time values. Hours must be 0-23, minutes must be 0-59.' );
						}

						return ( $hours * 60 ) + $minutes;
					}

					throw new \Exception( 'Invalid time format. Expected HH:MM or HH:MM AM/PM format.' );
				}
				return null;
			};

			// Update booking parameters.
			$booking_params = [];

			if ( isset( $data['agent_id'] ) ) {
				$booking_params['agent_id'] = $data['agent_id'];
			}
			if ( isset( $data['location_id'] ) ) {
				$booking_params['location_id'] = $data['location_id'];
			}
			if ( isset( $data['service_id'] ) ) {
				$booking_params['service_id'] = $data['service_id'];
			}
			if ( isset( $data['status'] ) ) {
				$booking_params['status'] = $data['status'];
			}
			if ( isset( $data['start_date'] ) ) {
				$booking_params['start_date'] = gmdate( 'Y-m-d', strtotime( $data['start_date'] ) );
			}
			if ( isset( $data['start_time'] ) ) {
				$booking_params['start_time'] = $convert_to_minutes( $data['start_time'] );
			}
			if ( isset( $data['end_time'] ) ) {
				$booking_params['end_time'] = $convert_to_minutes( $data['end_time'] );
			}
			if ( isset( $data['total_attendees'] ) ) {
				$booking_params['total_attendees'] = $data['total_attendees'];
			}
			if ( isset( $data['customer_comment'] ) ) {
				$booking_params['customer_comment'] = $data['customer_comment'];
			}
			if ( isset( $data['buffer_before'] ) ) {
				$booking_params['buffer_before'] = $data['buffer_before'];
			}
			if ( isset( $data['buffer_after'] ) ) {
				$booking_params['buffer_after'] = $data['buffer_after'];
			}

			// Handle custom fields update.
			if ( isset( $data['booking_custom_fields'] ) ) {
				$booking_params['custom_fields'] = $data['booking_custom_fields'];
			}

			// Update booking data.
			if ( ! empty( $booking_params ) ) {
				$booking->set_data( $booking_params );
			}

			// Handle customer updates if provided.
			if ( isset( $data['customer_type'] ) ) {
				if ( 'new' === $data['customer_type'] ) {
					$customer_params = [
						'first_name' => $data['customer_first_name'] ?? '',
						'last_name'  => $data['customer_last_name'] ?? '',
						'email'      => $data['customer_email'] ?? '',
						'phone'      => $data['customer_phone'] ?? '',
						'notes'      => $data['customer_notes'] ?? '',
					];

					$customer          = new \OsCustomerModel();
					$existing_customer = $customer->where( [ 'email' => $customer_params['email'] ] )->set_limit( 1 )->get_results_as_models();

					if ( isset( $existing_customer->id ) && ! empty( $existing_customer->id ) ) {
						$customer = new \OsCustomerModel( $existing_customer->id );
					} else {
						$customer = new \OsCustomerModel();
					}

					// Handle customer custom fields.
					$customer_custom_fields = LatePoint_Integration::extract_customer_custom_fields( $data );
					if ( ! empty( $customer_custom_fields ) ) {
						$customer_params['custom_fields'] = $customer_custom_fields;
					}

					$customer->set_data( $customer_params );
					if ( ! $customer->save() ) {
						$errors    = $customer->get_error_messages();
						$error_msg = $errors[0] ?? 'Customer could not be updated.';
						throw new \Exception( $error_msg );
					}

					$booking->customer_id = $customer->id;
				} elseif ( 'existing' === $data['customer_type'] ) {
					$customer_email = $data['customer_email'] ?? null;
					if ( ! $customer_email ) {
						throw new \Exception( 'Customer email not provided for existing customer.' );
					}

					// Find existing customer by email.
					$customer_model    = new \OsCustomerModel();
					$existing_customer = $customer_model->where( [ 'email' => $customer_email ] )->set_limit( 1 )->get_results_as_models();

					if ( empty( $existing_customer ) ) {
						throw new \Exception( 'Customer with email "' . $customer_email . '" not found.' );
					}

					$booking->customer_id = $existing_customer->id;
				}
			}

			$booking->set_utc_datetimes();

			if ( ! $booking->save() ) {
				$errors    = $booking->get_error_messages();
				$error_msg = $errors[0] ?? 'Booking could not be updated.';
				throw new \Exception( $error_msg );
			}

			// Trigger LatePoint action for booking update.
			do_action( 'latepoint_booking_updated', $booking, $old_booking ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- LatePoint action.

			return [
				'success' => true,
				'message' => __( 'Booking updated successfully.', 'sureforms-pro' ),
				'data'    => $booking->get_data_vars(),
			];

		} catch ( \Exception $e ) {
			return [
				'success' => false,
				'message' => sprintf(
					// translators: %s: Error message.
					__( 'Failed to update booking: %s', 'sureforms-pro' ),
					$e->getMessage()
				),
			];
		}
	}

	/**
	 * Check if LatePoint plugin is active
	 *
	 * @return bool True if LatePoint is active, false otherwise.
	 * @since 1.13.0
	 */
	protected function is_plugin_active() {
		return class_exists( 'OsBookingModel' ) && class_exists( 'OsCustomerModel' );
	}

}

// Initialize the class.
Update_Booking::get_instance();
