<?php
/**
 * LatePoint Create Booking Action
 *
 * Handles creating 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.
}

/**
 * Create Booking Action Class
 *
 * @since 1.13.0
 */
class Create_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 = 'create_booking';

	/**
	 * Execute the create booking action
	 *
	 * @param array $data Form submission data.
	 * @return array Action result.
	 * @throws \Exception If booking creation fails.
	 * @since 1.13.0
	 */
	protected function execute( $data ) {
		try {
			// 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;
			};

			$start_date = isset( $data['start_date'] ) ? gmdate( 'Y-m-d', strtotime( $data['start_date'] ) ) : '';
			$start_time = isset( $data['start_time'] ) ? $convert_to_minutes( $data['start_time'] ) : null;
			$end_time   = isset( $data['end_time'] ) ? $convert_to_minutes( $data['end_time'] ) : null;

			$customer_type  = $data['customer_type'] ?? 'new';
			$customer_email = '';

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

			// Create new booking.
			$booking = new \OsBookingModel();

			$booking_params = [
				'agent_id'         => $data['agent_id'] ?? null,
				'location_id'      => $data['location_id'] ?? 1,
				'status'           => $data['status'] ?? 'confirmed',
				'total_attendees'  => $data['total_attendees'] ?? 1,
				'service_id'       => $data['service_id'] ?? null,
				'start_date'       => $start_date,
				'start_time'       => $start_time,
				'end_time'         => $end_time,
				'customer_comment' => $data['customer_comment'] ?? '',
				'payment_status'   => 'not_paid',
				'buffer_before'    => $data['buffer_before'] ?? 0,
				'buffer_after'     => $data['buffer_after'] ?? 0,
				'source_url'       => site_url(),
			];

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

			$booking->set_data( $booking_params );

			// Handle customer creation or selection.
			if ( 'new' === $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 created.';
					throw new \Exception( $error_msg );
				}
			} else {
				// 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.' );
				}

				$customer = new \OsCustomerModel( $existing_customer->id );
			}

			// Create order.
			$order                     = new \OsOrderModel();
			$order->status             = $data['order_status'] ?? \OsOrdersHelper::get_default_order_status();
			$order->fulfillment_status = $order->get_default_fulfillment_status();
			$order->customer_comment   = $data['customer_comment'] ?? '';
			$order->customer_id        = $customer->id;
			$order->payment_status     = 'not_paid';

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

			// Create order item.
			$order_item_model           = new \OsOrderItemModel();
			$order_item_model->variant  = 'booking';
			$order_item_model->order_id = $order->id;

			if ( $order_item_model->save() ) {
				$booking->customer_id   = $order->customer_id;
				$booking->order_item_id = $order_item_model->id;
				if ( $booking->save() ) {
					$order_item_model->item_data = $booking->generate_item_data();
					$order_item_model->recalculate_prices();
					$order->total    = $order_item_model->total;
					$order->subtotal = $order_item_model->subtotal;
					$order->save();
					$order_item_model->save();
				}
			} else {
				$errors    = $order_item_model->get_error_messages();
				$error_msg = $errors[0] ?? 'Order Item could not be created.';
				throw new \Exception( $error_msg );
			}

			$booking->set_utc_datetimes();

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

			// Trigger actions.
			do_action( 'latepoint_booking_created', $booking ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- LatePoint action.
			do_action( 'latepoint_order_created', $order ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- LatePoint action.

			$return_data                    = $booking->get_data_vars();
			$return_data['order']           = $order->get_data_vars();
			$return_data['total_attendees'] = $data['total_attendees'] ?? 1;

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

		} catch ( \Exception $e ) {
			return [
				'success' => false,
				'message' => sprintf(
					// translators: %s: Error message.
					__( 'Failed to create 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' ) && class_exists( 'OsOrderModel' );
	}

}

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