<?php
/**
 * Hooks into Classified Listing frontend templates to render the booking button and form.
 *
 * @package RadiusTheme\RadiusBooking\Integrations\ClassifiedListing
 */

namespace RadiusTheme\RadiusBooking\Integrations\ClassifiedListing;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use RadiusTheme\RadiusBooking\Helpers\SettingsHelper;
use RadiusTheme\RadiusBooking\Models\EmployeeService;
use RadiusTheme\RadiusBooking\Models\Service;
use RadiusTheme\RadiusBooking\Models\UserProfile;

/**
 * Class ListingFrontendHooks
 *
 * Renders the "Book Now" button and booking form container on single listing pages.
 * Uses multiple hook points to ensure compatibility across all CL themes.
 */
class ListingFrontendHooks {

	/**
	 * Track whether we already rendered each element to avoid duplicates.
	 *
	 * @var bool
	 */
	private static $button_rendered = false;

	/**
	 * @var bool
	 */
	private static $form_rendered = false;

	/**
	 * Register hooks into CL template actions.
	 * Uses multiple hooks to ensure rendering across different themes.
	 */
	public static function init() {
		// Primary hooks (core CL template).
		add_action( 'rtcl_single_listing_sidebar', array( __CLASS__, 'renderBookNowButton' ), 30 );
		add_action( 'rtcl_after_single_listing', array( __CLASS__, 'renderBookingFormContainer' ) );

		// Fallback hooks used by various themes.
		add_action( 'rtcl_after_single_listing_sidebar', array( __CLASS__, 'renderBookNowButton' ), 30 );
		add_action( 'rtcl_single_listing_inner_sidebar', array( __CLASS__, 'renderBookNowButton' ), 30 );

		// wp_footer: guarantee the shared modal shell renders (works for both
		// hook-based buttons and Single Layout template buttons).
		add_action( 'wp_footer', array( __CLASS__, 'renderBookingFormContainerFooter' ), 5 );
	}

	/**
	 * Get the booking data for the current single listing, or null.
	 *
	 * Thin wrapper around {@see self::resolveBookingData()} that scopes the
	 * automatic hooks to the single listing page.
	 *
	 * @return array|null
	 */
	private static function getBookingData() {
		if ( ! is_singular( 'rtcl_listing' ) ) {
			return null;
		}

		return self::resolveBookingData( (int) get_the_ID() );
	}

	/**
	 * Resolve the booking data for a given listing if it is bookable.
	 *
	 * Reusable across the single listing page, archive loops and any custom
	 * placement via the rtrb_cl_booking_button() template function.
	 *
	 * @param int $listing_id Listing post ID.
	 *
	 * @return array|null Array with 'listing_id', 'service', 'employee_id', 'button_text' or null.
	 */
	public static function resolveBookingData( $listing_id ) {
		$listing_id = (int) $listing_id;
		if ( ! $listing_id || ! ListingServiceSync::normalizeBookingEnabled( get_post_meta( $listing_id, '_rtrb_booking_enabled', true ) ) ) {
			return null;
		}

		$cl_settings   = ListingFormBuilder::getEffectiveSettings( $listing_id );
		$is_staff_mode = ( $cl_settings['listingMappingMode'] ?? 'service' ) === 'staff';
		$button_text   = $cl_settings['bookNowButtonText'] ?? __( 'Book Now', 'radius-booking' );

		if ( $is_staff_mode ) {
			// Staff mode: find employee by listing_id, service is the shared default.
			$profile = UserProfile::where( 'listing_id', $listing_id )->first();
			if ( ! $profile ) {
				return null;
			}

			$default_service_id = (int) get_option( 'rtrb_cl_default_service_id', 0 );
			$service = $default_service_id ? Service::find( $default_service_id ) : null;
			if ( ! $service || 'visible' !== $service->status || ! $service->is_visible ) {
				return null;
			}

			// Only pre-select the default service when it's the staff's ONLY
			// service. If the staff offers multiple services, leave service_id
			// empty so the staff_first flow renders the service chooser instead
			// of auto-advancing past it (ServicesStep `bothPreSelected`).
			$service_id_for_button = (int) $service->id;
			$staff_service_count   = (int) EmployeeService::where( 'user_id', $profile->user_id )->count();
			if ( $staff_service_count > 1 ) {
				$service_id_for_button = '';
			}

			return array(
				'listing_id'  => $listing_id,
				'service'     => $service,
				'service_id'  => $service_id_for_button,
				'employee_id' => $profile->user_id,
				'button_text' => $button_text,
				// Listing represents a single staff member — anchor the form on staff.
				'flow'        => 'staff_first',
			);
		}

		// Service mode: find service by listing_id.
		$service = Service::where( 'listing_id', $listing_id )->first();
		if ( ! $service || 'visible' !== $service->status || ! $service->is_visible ) {
			return null;
		}

		// Only pre-select an employee when exactly one is assigned to the service.
		// With multiple staff, leave empty so the booking form's choose-staff
		// step is visible (the frontend skips that step unconditionally whenever
		// both service_id and employee_id are pre-selected — see ServicesStep
		// `bothPreSelected`).
		$employee_id    = '';
		$employee_count = (int) EmployeeService::where( 'service_id', $service->id )->count();
		if ( 1 === $employee_count ) {
			$employee_service = EmployeeService::where( 'service_id', $service->id )->first();
			$employee_id      = $employee_service ? $employee_service->user_id : '';
		}

		return array(
			'listing_id'  => $listing_id,
			'service'     => $service,
			'service_id'  => (int) $service->id,
			'employee_id' => $employee_id,
			'button_text' => $button_text,
			// Listing represents a single service — anchor the form on service.
			'flow'        => 'service_first',
		);
	}

	/**
	 * Render the "Book Now" button. Only renders once.
	 * Skips if Single Layout already rendered it.
	 */
	public static function renderBookNowButton() {
		if ( self::$button_rendered || defined( 'RTRB_SL_BOOKING_RENDERED' ) ) {
			return;
		}

		$data = self::getBookingData();
		if ( ! $data ) {
			return;
		}

		self::$button_rendered = true;

		// Single source of truth: the global template function. Keeps the
		// single-page button and any developer-placed archive button identical.
		echo rtrb_cl_get_booking_button( array( 'listing_id' => (int) $data['listing_id'] ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped inside the template function.
	}

	/**
	 * Render the shared, empty booking modal shell. Only renders once.
	 *
	 * The modal starts empty; cl-booking.js injects a fresh booking-form
	 * container (with the clicked listing's service/employee) on demand, so a
	 * single shell serves any number of listings on archive pages.
	 */
	public static function renderBookingFormContainer() {
		if ( self::$form_rendered ) {
			return;
		}

		// Render the shell when a button was emitted (single or archive), or
		// when we're on a bookable single listing (Single Layout themes that
		// render the button from their own template, bypassing our hook).
		$needed = function_exists( 'rtrb_cl_booking_modal_needed' ) && rtrb_cl_booking_modal_needed();
		if ( ! $needed && ! self::getBookingData() ) {
			return;
		}

		self::$form_rendered = true;
		?>
		<div id="rtrb-cl-booking-modal" style="display:none; position:fixed; inset:0; z-index:999999; background:rgba(0,0,0,0.6); align-items:center; justify-content:center; padding:20px;">
			<div class="rtrb-cl-booking-modal-inner" style="position:relative; width:100%; max-width:820px;"></div>
		</div>
		<?php
	}

	/**
	 * wp_footer fallback: render the shared modal shell if not yet rendered.
	 */
	public static function renderBookingFormContainerFooter() {
		self::renderBookingFormContainer();
	}
}
