<?php
/**
 * Plugin Name: FoodOrd
 * Description: Online food ordering and Table reservation plugin for WooCommerce
 * Plugin URI: https://foodord.com
 * Version: 1.5.4
 * Requires at least: 6.4
 * Tested up to: 7.0
 * Requires PHP: 8.0
 * Author: FoodOrd
 * Author URI: https://www.foodord.com
 * License: GPL v2 or later
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain: foodord
 * Domain Path: /languages
 *
 * @package FoodOrd
 */

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

// Basic constants.
define('FOODORD_VERSION', '1.5.4');
define('FOODORD_MIN_WP', '6.4');
define('FOODORD_MIN_PHP', '8.0');

define('FOODORD_FILE', __FILE__);
define('FOODORD_DIR', plugin_dir_path(__FILE__));
define('FOODORD_URL', plugin_dir_url(__FILE__));
define('FOODORD_CONFIG_DIR', FOODORD_DIR . 'config/');

if (!function_exists('foodord_get_table_ordering_token')) {
	/**
	 * Get the current table ordering token from the public URL.
	 */
	function foodord_get_table_ordering_token(): string
	{
		$token = filter_input(INPUT_GET, 'foodord_table_token', FILTER_SANITIZE_FULL_SPECIAL_CHARS);

		return is_string($token) ? sanitize_text_field(wp_unslash($token)) : '';
	}
}

if (!function_exists('foodord_is_table_ordering_request')) {
	/**
	 * Determine whether the current request is a table ordering URL.
	 */
	function foodord_is_table_ordering_request(): bool
	{
		return '' !== foodord_get_table_ordering_token();
	}
}

if (!function_exists('foodord_is_theme_active')) {
	/**
	 * Determine whether the FoodOrd theme or child theme is active.
	 */
	function foodord_is_theme_active(): bool
	{
		if (!function_exists('wp_get_theme')) {
			return false;
		}

		$theme = wp_get_theme();
		if (!$theme || !$theme->exists()) {
			return false;
		}

		$slug = $theme->get_stylesheet();
		$template = $theme->get_template();
		$parent = $theme->parent();
		$parent_slug = $parent ? $parent->get_stylesheet() : '';
		$parent_tpl = $parent ? $parent->get_template() : '';

		$valid = array('foodord-theme', 'foodord-child');

		return in_array($slug, $valid, true) || in_array($template, $valid, true) || in_array($parent_slug, $valid, true) || in_array($parent_tpl, $valid, true);
	}
}

if (!defined('FOODORD_THEME_ACTIVE')) {
	define('FOODORD_THEME_ACTIVE', foodord_is_theme_active());
}

if (!function_exists('foodord_should_wrap_card')) {
	/**
	 * Determine whether the cart sidebar should be wrapped in a fallback container.
	 */
	function foodord_should_wrap_card(): bool
	{
		if (is_admin()) {
			return false;
		}

		return !(defined('FOODORD_THEME_ACTIVE') && FOODORD_THEME_ACTIVE);
	}
}

if (!function_exists('foodord_wrap_card_markup')) {
	/**
	 * Wrap the cart markup with a fallback sidebar container for non-FoodOrd themes.
	 *
	 * @param string $html Cart markup.
	 */
	function foodord_wrap_card_markup(string $html): string
	{
		if ('' === trim($html) || !foodord_should_wrap_card()) {
			return $html;
		}

		$GLOBALS['foodord_force_sidebar_body_class'] = true;

		$default_classes = array('foodord-sidebar', 'foodord-sidebar');
		$classes = apply_filters('foodord_sidebar_wrapper_classes', $default_classes);
		$classes = array_filter(array_map('sanitize_html_class', (array) $classes));
		if (empty($classes)) {
			$classes = $default_classes;
		}

		$class_attr = implode(' ', array_unique($classes));

		return '<div class="' . esc_attr($class_attr) . '">' . $html . '</div>';
	}
}

if (!function_exists('foodord_admin_notice_requires_wc')) {
	/**
	 * Inform administrators that WooCommerce must be active for FoodOrd to operate.
	 */
	function foodord_admin_notice_requires_wc()
	{
		if (!is_admin() || !current_user_can('manage_options')) {
			return;
		}

		if (class_exists('WooCommerce') || function_exists('wc')) {
			return;
		}

		/* translators: %s: WooCommerce plugin name. */
		$message = sprintf(__('Foodord requires %s to be installed and active for ordering features to work.', 'foodord'), 'WooCommerce');

		printf('<div class="notice notice-error"><p>%s</p></div>', esc_html($message));
	}
}
add_action('admin_notices', 'foodord_admin_notice_requires_wc');

if (!function_exists('foodord_get_admin_parent_slug')) {
	/**
	 * Determine the parent slug used for FoodOrd admin pages.
	 */
	function foodord_get_admin_parent_slug(): string
	{
		return (defined('FOODORD_THEME_ACTIVE') && FOODORD_THEME_ACTIVE)
			? 'foodord-theme-settings'
			: 'foodord-settings';
	}
}

if (!function_exists('foodord_get_theme_download_url')) {
	/**
	 * Retrieve the public download URL for the optional FoodOrd Theme package.
	 */
	function foodord_get_theme_download_url(): string
	{
		$url = 'https://www.foodord.com/downloads/';

		/**
		 * Filter the FoodOrd Theme download URL shown in plugin onboarding flows.
		 *
		 * @param string $url Theme download URL.
		 */
		$url = apply_filters('foodord_theme_download_url', $url);

		return is_string($url) ? $url : 'https://www.foodord.com/downloads/';
	}
}

if (!function_exists('foodord_get_installed_theme_slug')) {
	/**
	 * Retrieve the installed FoodOrd theme slug, if available.
	 */
	function foodord_get_installed_theme_slug(): string
	{
		if (!function_exists('wp_get_theme')) {
			return '';
		}

		foreach (array('foodord-theme', 'foodord-child') as $slug) {
			$theme = wp_get_theme($slug);

			if ($theme && $theme->exists()) {
				return $slug;
			}
		}

		return '';
	}
}

if (!function_exists('foodord_is_theme_installed')) {
	/**
	 * Determine whether the FoodOrd theme package exists on this site.
	 */
	function foodord_is_theme_installed(): bool
	{
		return '' !== foodord_get_installed_theme_slug();
	}
}

if (!function_exists('foodord_get_theme_activation_url')) {
	/**
	 * Retrieve the activation URL for the installed FoodOrd theme.
	 */
	function foodord_get_theme_activation_url(): string
	{
		$slug = foodord_get_installed_theme_slug();

		if ('' === $slug) {
			return function_exists('foodord_get_theme_download_url') ? foodord_get_theme_download_url() : admin_url('themes.php');
		}

		$url = add_query_arg(
			array(
				'action' => 'activate',
				'stylesheet' => $slug,
			),
			admin_url('themes.php')
		);

		return wp_nonce_url($url, 'switch-theme_' . $slug);
	}
}

if (!function_exists('foodord_get_theme_admin_status')) {
	/**
	 * Retrieve the FoodOrd theme admin status.
	 */
	function foodord_get_theme_admin_status(): string
	{
		if (defined('FOODORD_THEME_ACTIVE') && FOODORD_THEME_ACTIVE) {
			return 'active';
		}

		return foodord_is_theme_installed() ? 'installed' : 'missing';
	}
}

if (!function_exists('foodord_page_has_order_components')) {
	/**
	 * Determine if current request is expected to render FoodOrd ordering components.
	 */
	function foodord_page_has_order_components(): bool
	{
		if (!empty($GLOBALS['foodord_has_card_block']) || !empty($GLOBALS['foodord_has_card_shortcode'])) {
			return true;
		}

		if (!empty($GLOBALS['foodord_has_products_block']) || !empty($GLOBALS['foodord_has_products_shortcode'])) {
			return true;
		}

		global $post;
		if (!$post instanceof WP_Post) {
			return false;
		}

		$content = (string) $post->post_content;
		if (function_exists('has_shortcode')) {
			if (has_shortcode($content, 'foodord_card') || has_shortcode($content, 'foodord_products')) {
				return true;
			}
		}

		if (function_exists('has_block')) {
			if (has_block('foodord/card', $content) || has_block('foodord/products', $content)) {
				return true;
			}
		}

		return false;
	}
}

if (!function_exists('foodord_page_has_card_component')) {
	/**
	 * Determine if current request contains the FoodOrd card component.
	 */
	function foodord_page_has_card_component(): bool
	{
		if (!empty($GLOBALS['foodord_has_card_block']) || !empty($GLOBALS['foodord_has_card_shortcode'])) {
			return true;
		}

		global $post;
		if (!$post instanceof WP_Post) {
			return false;
		}

		$content = (string) $post->post_content;
		if (function_exists('has_shortcode')) {
			if (has_shortcode($content, 'foodord_card')) {
				return true;
			}
		}

		if (function_exists('has_block')) {
			if (has_block('foodord/card', $content)) {
				return true;
			}
		}

		return false;
	}
}

if (!function_exists('foodord_page_has_products_component')) {
	/**
	 * Determine if current request contains the FoodOrd products component.
	 */
	function foodord_page_has_products_component(): bool
	{
		if (!empty($GLOBALS['foodord_has_products_block']) || !empty($GLOBALS['foodord_has_products_shortcode'])) {
			return true;
		}

		global $post;
		if (!$post instanceof WP_Post) {
			return false;
		}

		$content = (string) $post->post_content;
		if (function_exists('has_shortcode') && has_shortcode($content, 'foodord_products')) {
			return true;
		}

		if (function_exists('has_block') && has_block('foodord/products', $content)) {
			return true;
		}

		return false;
	}
}

if (!function_exists('foodord_get_product_card_layout')) {
	/**
	 * Retrieve the selected product card layout.
	 */
	function foodord_get_product_card_layout(): string
	{
		$layout = get_option('foodord_product_card_layout', 'streamline');
		$allowed = array('classic', 'grid', 'streamline', 'frosted');
		if (!in_array($layout, $allowed, true)) {
			$layout = 'streamline';
		}

		/**
		 * Filter the product card layout before usage.
		 *
		 * @param string $layout Selected layout.
		 */
		return apply_filters('foodord_product_card_layout', $layout);
	}
}

if (!function_exists('foodord_inject_mobile_mode_toggle_into_content')) {
	/**
	 * Inject the mobile delivery/pickup toggle slot above FoodOrd products output.
	 *
	 * @param string $content Post content HTML.
	 * @return string
	 */
	function foodord_inject_mobile_mode_toggle_into_content($content): string
	{
		static $did_inject = false;
		if ($did_inject) {
			return $content;
		}

		if (is_admin() || (function_exists('wp_doing_ajax') && wp_doing_ajax())) {
			return $content;
		}

		if (defined('FOODORD_THEME_ACTIVE') && FOODORD_THEME_ACTIVE) {
			return $content;
		}

		if (!is_singular() || !in_the_loop() || !is_main_query()) {
			return $content;
		}

		if (!function_exists('foodord_page_has_products_component') || !foodord_page_has_products_component()) {
			return $content;
		}

		if (false !== strpos((string) $content, 'data-foodord-mode-toggle="mobile"')) {
			return $content;
		}

		$did_inject = true;
		return '<div class="foodord-mode-toggle-mobile alignfull" data-foodord-mode-toggle="mobile"></div>' . $content;
	}
}

add_filter('the_content', 'foodord_inject_mobile_mode_toggle_into_content', 13);

if (!function_exists('foodord_get_settings_page_map')) {
	/**
	 * Retrieve the slug map for FoodOrd admin pages.
	 *
	 * @internal
	 *
	 * @return array<string, array{theme: string, plugin: string}>
	 */
	function foodord_get_settings_page_map(): array
	{
		static $map = null;
		if (null === $map) {
			$map = array(
				'dashboard' => array(
					'theme' => 'foodord-theme-settings-dashboard',
					'plugin' => 'foodord-dashboard',
				),
				'settings_hub' => array(
					'theme' => 'foodord-settings-hub',
					'plugin' => 'foodord-settings-hub',
				),
				'license' => array(
					'theme' => 'foodord-theme-settings-license',
					'plugin' => 'foodord-license',
				),
				'styling' => array(
					// Styling page is provided by the plugin, even when the theme is active.
					'theme' => 'foodord-styling',
					'plugin' => 'foodord-styling',
				),
				'delivery' => array(
					'theme' => 'foodord-theme-settings-delivery',
					'plugin' => 'foodord-delivery',
				),
				'pickup' => array(
					'theme' => 'foodord-theme-settings-pickup',
					'plugin' => 'foodord-pickup',
				),
				'toppings' => array(
					'theme' => 'foodord-theme-settings-toppings',
					'plugin' => 'foodord-toppings',
				),
				'layout' => array(
					'theme' => 'foodord-theme-settings-layout',
					'plugin' => 'foodord-layout',
				),
				'home_banner' => array(
					'theme' => 'foodord-theme-settings-home-banner',
					'plugin' => '',
				),
				'cookie_law' => array(
					'theme' => 'foodord-theme-settings-cookie-law',
					'plugin' => '',
				),
				'topping_sets' => array(
					'theme' => 'foodord-theme-settings-topping-sets',
					'plugin' => 'foodord-topping-sets',
				),
				'shortcodes' => array(
					'theme' => 'foodord-theme-settings-shortcodes',
					'plugin' => 'foodord-shortcodes',
				),
				'tweaks' => array(
					'theme' => 'foodord-theme-settings-tweaks',
					'plugin' => 'foodord-tweaks',
				),
				'integrations' => array(
					'theme' => 'foodord-theme-settings-integrations',
					'plugin' => 'foodord-integrations',
				),
				'reservations' => array(
					'theme' => 'foodord-theme-settings-reservations',
					'plugin' => 'foodord-reservations',
				),
				'live_orders' => array(
					'theme' => 'foodord-theme-settings-live-orders',
					'plugin' => 'foodord-live-orders',
				),
			);
		}

		return $map;
	}
}

if (!function_exists('foodord_get_settings_page_slug')) {
	/**
	 * Get the admin page slug for the requested page key.
	 *
	 * @param string $page_key Slug key (license, delivery, etc.).
	 * @param string $context  Explicit context: 'current', 'theme', or 'plugin'.
	 */
	function foodord_get_settings_page_slug(string $page_key, string $context = 'current'): string
	{
		$page_key = strtolower($page_key);
		$context = strtolower($context);
		$map = foodord_get_settings_page_map();

		if ('theme' !== $context && 'plugin' !== $context) {
			$context = (defined('FOODORD_THEME_ACTIVE') && FOODORD_THEME_ACTIVE) ? 'theme' : 'plugin';
		}

		if (isset($map[$page_key][$context])) {
			return $map[$page_key][$context];
		}

		$prefix = ('theme' === $context) ? 'foodord-theme-settings-' : 'foodord-';
		return $prefix . $page_key;
	}
}

if (!function_exists('foodord_get_settings_page_slugs')) {
	/**
	 * Retrieve all possible slugs for a specific admin page key.
	 *
	 * @param string $page_key Slug key (license, delivery, etc.).
	 * @return string[]
	 */
	function foodord_get_settings_page_slugs(string $page_key): array
	{
		$page_key = strtolower($page_key);
		$map = foodord_get_settings_page_map();

		if (isset($map[$page_key])) {
			return array_values(array_filter($map[$page_key]));
		}

		return array(
			'foodord-theme-settings-' . $page_key,
			'foodord-' . $page_key,
		);
	}
}

if (!function_exists('foodord_get_admin_page_url')) {
	/**
	 * Helper to build admin URLs for FoodOrd settings pages.
	 *
	 * @param string $page_key Page key.
	 */
	function foodord_get_admin_page_url(string $page_key): string
	{
		return admin_url('admin.php?page=' . foodord_get_settings_page_slug($page_key));
	}
}

add_action(
	'init',
	static function () {
		/* translators: Mobile cart toggle label. */
		__('View Cart', 'foodord');
		/* translators: Mobile cart modal title. */
		__('Your order', 'foodord');
	}
);

// Redirect legacy admin page slug to the new plugin-provided styling page.
add_action(
	'admin_init',
	static function () {
		if (!is_admin()) {
			return;
		}

		$page_raw = filter_input(INPUT_GET, 'page', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
		$page = is_string($page_raw) ? sanitize_text_field($page_raw) : '';
		if ('' === $page) {
			return;
		}
		if ('foodord-theme-settings-styling' !== $page) {
			return;
		}

		wp_safe_redirect(admin_url('admin.php?page=foodord-styling'));
		exit;
	}
);


if (!function_exists('foodord_is_license_active')) {
	/**
	 * Determine if the stored FoodOrd license is active.
	 */
	function foodord_is_license_active(): bool
	{
		return 'active' === get_option('foodord_license_status', 'inactive');
	}
}

if (!function_exists('foodord_normalize_license_domain')) {
	/**
	 * Normalize a domain value for comparisons.
	 *
	 * @param string $value Raw domain or URL.
	 */
	function foodord_normalize_license_domain(string $value): string
	{
		$value = trim($value);

		if ('' === $value) {
			return '';
		}

		$host = wp_parse_url($value, PHP_URL_HOST);

		if (false === $host || null === $host) {
			$host = $value;
		}

		$host = strtolower(trim((string) $host));

		if (0 === strpos($host, 'www.')) {
			$host = substr($host, 4);
		}

		return $host;
	}
}

if (!function_exists('foodord_get_license_service_config_values')) {
	/**
	 * Resolve effective license service configuration.
	 *
	 * @return array{endpoint:string,api_key:string}
	 */
	function foodord_get_license_service_config_values(): array
	{
		$default_endpoint = 'https://foodord.com/wp-json/foodord-cloud/v1/license/verify';
		$endpoint = defined('FOODORD_LICENSE_SERVICE_ENDPOINT')
			? trim((string) FOODORD_LICENSE_SERVICE_ENDPOINT)
			: trim((string) get_option('foodord_license_service_endpoint', $default_endpoint));
		$api_key = defined('FOODORD_LICENSE_SERVICE_KEY')
			? trim((string) FOODORD_LICENSE_SERVICE_KEY)
			: trim((string) get_option('foodord_license_service_key', ''));

		return array(
			'endpoint' => '' !== $endpoint ? untrailingslashit($endpoint) : '',
			'api_key' => $api_key,
		);
	}
}

if (!function_exists('foodord_sync_license_status')) {
	/**
	 * Sync stored license state with the central license server.
	 *
	 * @param bool $force Bypass the cache window when true.
	 */
	function foodord_sync_license_status(bool $force = false): bool
	{
		$license_key = trim((string) get_option('foodord_license_key', ''));

		if ('' === $license_key) {
			update_option('foodord_license_status', 'inactive');
			delete_option('foodord_license_details');
			delete_option('foodord_license_last_checked_at');

			return false;
		}

		$cache_ttl = 300;
		$last_checked = absint(get_option('foodord_license_last_checked_at', 0));
		$now = time();

		if (!$force && $last_checked > 0 && ($now - $last_checked) < $cache_ttl) {
			return foodord_is_license_active();
		}

		$config = foodord_get_license_service_config_values();

		if ('' === $config['endpoint']) {
			return foodord_is_license_active();
		}

		$domain = foodord_normalize_license_domain((string) wp_parse_url(home_url(), PHP_URL_HOST));
		$args = array(
			'timeout' => 20,
			'headers' => array(
				'content-type' => 'application/json',
				'accept' => 'application/json',
			),
			'body' => wp_json_encode(
				array(
					'purchaseCode' => $license_key,
					'domain' => $domain,
					'siteUrl' => home_url(),
				)
			),
			'method' => 'POST',
		);

		if ('' !== $config['api_key']) {
			$args['headers']['x-foodord-license-key'] = $config['api_key'];
		}

		$response = wp_remote_request($config['endpoint'], $args);

		if (is_wp_error($response)) {
			return foodord_is_license_active();
		}

		$status_code = wp_remote_retrieve_response_code($response);
		$body = wp_remote_retrieve_body($response);
		$data = json_decode($body, true);

		if (!is_array($data)) {
			return foodord_is_license_active();
		}

		update_option('foodord_license_last_checked_at', $now);

		$reason = isset($data['reason']) ? strtolower(trim((string) $data['reason'])) : '';
		$service_status = isset($data['license']['status']) ? strtolower(trim((string) $data['license']['status'])) : '';
		$hard_inactive_reasons = array(
			'domain_mismatch',
			'invalid_status',
			'payment_required',
			'invalid_expiry',
			'not_found',
		);

		if ($status_code >= 400 || (isset($data['valid']) && false === (bool) $data['valid'])) {
			if (
				'inactive' === $service_status ||
				('' !== $reason && in_array($reason, $hard_inactive_reasons, true))
			) {
				update_option('foodord_license_status', 'inactive');

				if (isset($data['license']) && is_array($data['license'])) {
					update_option(
						'foodord_license_details',
						array(
							'license' => $data['license'],
							'billing' => isset($data['billing']) && is_array($data['billing']) ? $data['billing'] : array(),
						)
					);
				}

				return false;
			}

			return foodord_is_license_active();
		}

		if (!isset($data['valid']) || true !== (bool) $data['valid']) {
			return foodord_is_license_active();
		}

		$details = array();

		if (isset($data['license']) && is_array($data['license'])) {
			$details['license'] = $data['license'];
		}

		if (isset($data['billing']) && is_array($data['billing'])) {
			$details['billing'] = $data['billing'];
		}

		if (!empty($details)) {
			update_option('foodord_license_details', $details);
		}

		update_option('foodord_license_status', 'active');

		return true;
	}
}

$foodord_license_config_path = FOODORD_CONFIG_DIR . 'license-config.php';
if (file_exists($foodord_license_config_path)) {
	$foodord_license_config = include $foodord_license_config_path;

	if (is_array($foodord_license_config)) {
		$foodord_service_config = isset($foodord_license_config['license_service']) && is_array($foodord_license_config['license_service'])
			? $foodord_license_config['license_service']
			: array();

		$foodord_license_endpoint = $foodord_service_config['endpoint'] ?? '';
		$foodord_license_key = $foodord_service_config['api_key'] ?? '';

		if (is_scalar($foodord_license_endpoint)) {
			$foodord_license_endpoint = trim((string) $foodord_license_endpoint);
		} else {
			$foodord_license_endpoint = '';
		}

		if (is_scalar($foodord_license_key)) {
			$foodord_license_key = trim((string) $foodord_license_key);
		} else {
			$foodord_license_key = '';
		}

		if ('' !== $foodord_license_endpoint && !defined('FOODORD_LICENSE_SERVICE_ENDPOINT')) {
			define('FOODORD_LICENSE_SERVICE_ENDPOINT', $foodord_license_endpoint);
		}

		if ('' !== $foodord_license_key && !defined('FOODORD_LICENSE_SERVICE_KEY')) {
			define('FOODORD_LICENSE_SERVICE_KEY', $foodord_license_key);
		}
	}
}

if (!function_exists('foodord_get_order_mode')) {
	/**
	 * Determine the current order mode with session → cookie fallback.
	 */
	function foodord_get_order_mode(): string
	{
		$mode = 'delivery';

		if (function_exists('WC') && WC()->session) {
			$session_mode = (string) WC()->session->get('foodord_order_mode', '');
			if (in_array($session_mode, array('delivery', 'pickup'), true)) {
				return $session_mode;
			}
		}

		return $mode;
	}
}

if (!function_exists('foodord_reset_order_mode_cache')) {
	/**
	 * Reset persisted order mode and timing caches back to delivery.
	 */
	function foodord_reset_order_mode_cache(): void
	{
		if (function_exists('WC') && WC()->session) {
			WC()->session->set('foodord_order_mode', 'delivery');
			WC()->session->__unset('foodord_delivery_time');
			WC()->session->__unset('foodord_pickup_time');
			WC()->session->__unset('foodord_delivery_date');
			WC()->session->__unset('foodord_pickup_date');
			if (method_exists(WC()->session, 'save_data')) {
				WC()->session->save_data();
			}
		}

		$expired = time() - DAY_IN_SECONDS;

		if (function_exists('wc_setcookie')) {
			wc_setcookie('foodord_order_mode', '', $expired);
			wc_setcookie('foodord_delivery_time', '', $expired);
			wc_setcookie('foodord_pickup_time', '', $expired);
			wc_setcookie('foodord_delivery_date', '', $expired);
			wc_setcookie('foodord_pickup_date', '', $expired);
		} else {
			$cookie_path = defined('COOKIEPATH') ? COOKIEPATH : '/';
			$cookie_domain = defined('COOKIE_DOMAIN') ? COOKIE_DOMAIN : '';
			setcookie('foodord_order_mode', '', $expired, $cookie_path, $cookie_domain, is_ssl(), true);
			setcookie('foodord_delivery_time', '', $expired, $cookie_path, $cookie_domain, is_ssl(), true);
			setcookie('foodord_pickup_time', '', $expired, $cookie_path, $cookie_domain, is_ssl(), true);
			setcookie('foodord_delivery_date', '', $expired, $cookie_path, $cookie_domain, is_ssl(), true);
			setcookie('foodord_pickup_date', '', $expired, $cookie_path, $cookie_domain, is_ssl(), true);
		}
	}
}

if (!function_exists('foodord_track_delivery_fee')) {
	/**
	 * Persist the last calculated delivery fee amount in the WooCommerce session.
	 *
	 * @param float $amount Delivery fee amount.
	 */
	function foodord_track_delivery_fee(float $amount): void
	{
		if (function_exists('WC') && WC()->session) {
			WC()->session->set('foodord_delivery_fee_amount', max(0.0, $amount));
		}
	}
}

if (!function_exists('foodord_get_cart_note_labels')) {
	/**
	 * Provide translatable labels for cart notes scripts.
	 *
	 * @return array<string,string>
	 */
	function foodord_get_cart_note_labels(): array
	{
		return array(
			'addToggle' => __('Add note', 'foodord'),
			'editToggle' => __('Edit note', 'foodord'),
			'addButton' => __('Add', 'foodord'),
			'cancelButton' => __('Cancel', 'foodord'),
			'deleteButton' => __('Delete', 'foodord'),
			'displayLabel' => __('Note', 'foodord'),
			'placeholder' => __('Add a note (max {max} characters)', 'foodord'),
			'error' => __('Could not update the note. Please try again.', 'foodord'),
		);
	}
}

// RTL Mode Support.
add_filter(
	'body_class',
	function ($classes) {
		if (get_option('foodord_enable_rtl', false)) {
			$classes[] = 'rtl';
			$classes[] = 'foodord-rtl-mode';
		}

		if (defined('FOODORD_THEME_ACTIVE') && FOODORD_THEME_ACTIVE) {
			$classes[] = 'foodord-theme-active';
		}

		$sidebar_active = !empty($GLOBALS['foodord_force_sidebar_body_class']);
		if (!$sidebar_active && !(defined('FOODORD_THEME_ACTIVE') && FOODORD_THEME_ACTIVE)) {
			$sidebar_active = function_exists('foodord_page_has_card_component') && foodord_page_has_card_component();
		}

		if ($sidebar_active) {
			$classes[] = 'has-foodord-sidebar';
			$classes[] = 'foodord-sidebar-active';
		}

		if (foodord_page_has_order_components()) {
			$classes[] = 'foodord-order-page';
		}
		return $classes;
	}
);

add_filter(
	'is_rtl',
	function ($is_rtl) {
		return get_option('foodord_enable_rtl', false) ? true : $is_rtl;
	}
);

// Admin styles.
add_action(
	'admin_enqueue_scripts',
	function () {
		wp_enqueue_style(
			'foodord-admin',
			FOODORD_URL . 'admin/css/wrc-admin.css',
			array(),
			FOODORD_VERSION,
			'all'
		);
	}
);

// Frontend styles - loaded conditionally.
if (!function_exists('foodord_enqueue_touch_styles')) {
	/**
	 * Enqueue shared touch-device interaction styles for FoodOrd frontend components.
	 */
	function foodord_enqueue_touch_styles(): void
	{
		if (is_admin() || (function_exists('wp_doing_ajax') && wp_doing_ajax())) {
			return;
		}

		wp_enqueue_style(
			'foodord-touch',
			FOODORD_URL . 'public/css/foodord-touch.css',
			array(),
			FOODORD_VERSION,
			'all'
		);
	}
}

if (!function_exists('foodord_enqueue_frontend_styles')) {
	/**
	 * Enqueue frontend styles only when plugin components are used.
	 */
	function foodord_enqueue_frontend_styles(): void
	{
		if (function_exists('foodord_enqueue_touch_styles')) {
			foodord_enqueue_touch_styles();
		}

		wp_enqueue_style(
			'foodord-frontend',
			FOODORD_URL . 'public/css/wrc-frontend.css',
			array('foodord-touch'),
			FOODORD_VERSION,
			'all'
		);

		if (get_option('foodord_enable_rtl', false)) {
			wp_enqueue_style(
				'foodord-frontend-rtl',
				FOODORD_URL . 'public/css/wrc-frontend-rtl.css',
				array('foodord-frontend'),
				FOODORD_VERSION,
				'all'
			);
		}
	}
}

add_action(
	'wp_enqueue_scripts',
	function (): void {
		if (function_exists('foodord_page_has_order_components') && foodord_page_has_order_components()) {
			foodord_enqueue_touch_styles();
		}
	},
	8
);

/**
 * Enqueue Integrations assets for both Admin and Frontend.
 */
function foodord_enqueue_integrations_assets(): void
{
	if (is_admin()) {
		return;
	}

	wp_enqueue_style(
		'foodord-integrations',
		FOODORD_URL . 'admin/css/foodord-integrations.css',
		array(),
		FOODORD_VERSION,
		'all'
	);
}
add_action('wp_enqueue_scripts', 'foodord_enqueue_integrations_assets', 25);

// FoodOrd Theme look-and-feel compatibility for third-party themes.
if (!function_exists('foodord_enqueue_theme_compat_assets')) {
	/**
	 * Enqueue compatibility assets to mimic FoodOrd Theme ordering layout
	 * when the FoodOrd Theme is not active.
	 */
	function foodord_enqueue_theme_compat_assets(): void
	{
		if (is_admin() || (function_exists('wp_doing_ajax') && wp_doing_ajax())) {
			return;
		}

		if (defined('FOODORD_THEME_ACTIVE') && FOODORD_THEME_ACTIVE) {
			return;
		}

		if (function_exists('foodord_page_has_order_components') && !foodord_page_has_order_components()) {
			return;
		}

		if (function_exists('foodord_enqueue_frontend_styles')) {
			foodord_enqueue_frontend_styles();
		}

		wp_enqueue_style(
			'foodord-theme-compat',
			FOODORD_URL . 'public/css/foodord-theme-compat.css',
			array('foodord-frontend'),
			FOODORD_VERSION,
			'all'
		);
	}
}

add_action('wp_enqueue_scripts', 'foodord_enqueue_theme_compat_assets', 20);

// Activation hook.
register_activation_hook(
	__FILE__,
	function () {
		if (!class_exists('Foodord_Table_Reservations')) {
			require_once FOODORD_DIR . 'includes/class-foodord-table-reservations.php';
		}
		if (class_exists('Foodord_Table_Reservations')) {
			Foodord_Table_Reservations::install();
			Foodord_Table_Reservations::init_status_automation();
		}
		if (!class_exists('Foodord_Table_Reservation_Preorders')) {
			require_once FOODORD_DIR . 'includes/class-foodord-table-reservation-preorders.php';
		}
		if (class_exists('Foodord_Table_Reservation_Preorders')) {
			Foodord_Table_Reservation_Preorders::install();
		}

		if ('yes' === get_option('foodord_onboarding_complete')) {
			if (class_exists('Foodord_Diagnostics')) {
				Foodord_Diagnostics::schedule_monthly_event();
			}

			return;
		}

		update_option('foodord_onboarding_redirect', '1');

		if (class_exists('Foodord_Diagnostics')) {
			Foodord_Diagnostics::schedule_monthly_event();
		}
	}
);

// Deactivation hook.
register_deactivation_hook(
	__FILE__,
	function () {
		if (class_exists('Foodord_Diagnostics')) {
			Foodord_Diagnostics::clear_monthly_event();
		}
		if (class_exists('Foodord_Table_Reservations')) {
			Foodord_Table_Reservations::clear_status_automation();
		}

		// Future: cleanup runtime only. No destructive operations.
	}
);

add_action(
	'init',
	static function () {
		if (empty($_SERVER['REQUEST_URI'])) {
			return;
		}

		$request_uri = sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI']));

		if (false === strpos($request_uri, '/wp-json/foodord/')) {
			return;
		}

		if (!defined('FOODORD_DONOTCACHEPAGE')) {
			define('FOODORD_DONOTCACHEPAGE', true);
		}

		if (!defined('FOODORD_DONOTCACHEOBJECT')) {
			define('FOODORD_DONOTCACHEOBJECT', true);
		}

		if (!defined('FOODORD_DONOTCACHEDB')) {
			define('FOODORD_DONOTCACHEDB', true);
		}
	}
);


// Load shortcode and block classes.
require_once FOODORD_DIR . 'includes/class-foodord-business-hours.php';
require_once FOODORD_DIR . 'includes/class-foodord-timed-products.php';
require_once FOODORD_DIR . 'includes/class-foodord-product-availability.php';
require_once FOODORD_DIR . 'includes/class-foodord-product-labels.php';
require_once FOODORD_DIR . 'includes/class-foodord-product-pricing.php';
require_once FOODORD_DIR . 'includes/class-foodord-pwa-language.php';
require_once FOODORD_DIR . 'includes/class-foodord-pwa.php';
require_once FOODORD_DIR . 'includes/class-foodord-reservation-quota.php';
require_once FOODORD_DIR . 'includes/class-foodord-live-orders-quota.php';
require_once FOODORD_DIR . 'includes/class-foodord-table-reservations.php';

Foodord_Live_Orders_Quota::init();
require_once FOODORD_DIR . 'includes/class-foodord-table-reservation-preorders.php';
require_once FOODORD_DIR . 'includes/class-foodord-table-reservation-calendar.php';
require_once FOODORD_DIR . 'includes/class-foodord-table-reservation-emails.php';
require_once FOODORD_DIR . 'includes/class-foodord-table-reservation-operations.php';
require_once FOODORD_DIR . 'includes/class-foodord-table-reservation-deposits.php';
require_once FOODORD_DIR . 'includes/class-foodord-diagnostics.php';
require_once FOODORD_DIR . 'includes/foodord-lazy-images.php';
require_once FOODORD_DIR . 'includes/class-foodord-products-renderer.php';
require_once FOODORD_DIR . 'includes/class-foodord-products-shortcode.php';
require_once FOODORD_DIR . 'includes/class-foodord-products-block.php';
require_once FOODORD_DIR . 'includes/class-foodord-card-shortcode.php';
require_once FOODORD_DIR . 'includes/class-foodord-card-block.php';
require_once FOODORD_DIR . 'includes/class-foodord-table-reservations-block.php';
require_once FOODORD_DIR . 'includes/class-foodord-mobile-cart.php';
require_once FOODORD_DIR . 'includes/class-foodord-location-service.php';
require_once FOODORD_DIR . 'includes/class-foodord-location-service.php';
require_once FOODORD_DIR . 'includes/class-foodord-email-order-actions.php';
require_once FOODORD_DIR . 'includes/class-foodord-theme-demo-importer.php';
require_once FOODORD_DIR . 'includes/foodord-order-status-filters.php';
require_once FOODORD_DIR . 'includes/integrations/class-foodord-google-login.php';
require_once FOODORD_DIR . 'admin/class-foodord-integrations.php';

Foodord_Diagnostics::init();
Foodord_Pwa_Language::init();
Foodord_Pwa::init();
Foodord_Table_Reservations::init_status_automation();
Foodord_Table_Reservation_Calendar::init();

require_once FOODORD_DIR . 'public/class-foodord-checkout-validator.php';
require_once FOODORD_DIR . 'public/class-foodord-table-reservations-frontend.php';

add_action('plugins_loaded', function () {
	if (class_exists('Foodord_Integrations')) {
		$integrations = new Foodord_Integrations();
		$integrations->init();
	}

	if (class_exists('Foodord_Google_Login')) {
		$google_login = new Foodord_Google_Login();
		$google_login->init();
	}

	if (class_exists('Foodord_Table_Reservations_Frontend')) {
		$foodord_table_reservations_frontend = new Foodord_Table_Reservations_Frontend();
		$foodord_table_reservations_frontend->init();
	}

	if (class_exists('Foodord_Table_Reservation_Deposits')) {
		$foodord_table_reservation_deposits = new Foodord_Table_Reservation_Deposits();
		$foodord_table_reservation_deposits->init();
	}
});

add_filter(
	'woocommerce_is_purchasable',
	function ($is_purchasable, $product) {
		if (!class_exists('Foodord_Product_Availability') || !class_exists('WC_Product') || !$product instanceof WC_Product) {
			return $is_purchasable;
		}

		$product_id = (int) $product->get_id();
		$parent_id = (int) $product->get_parent_id();

		if ($product_id > 0 && !Foodord_Product_Availability::is_available($product_id)) {
			return false;
		}

		if ($parent_id > 0 && !Foodord_Product_Availability::is_available($parent_id)) {
			return false;
		}

		return $is_purchasable;
	},
	10,
	2
);

add_filter(
	'woocommerce_variation_is_purchasable',
	function ($is_purchasable, $product) {
		if (!class_exists('Foodord_Product_Availability') || !class_exists('WC_Product') || !$product instanceof WC_Product) {
			return $is_purchasable;
		}

		$product_id = (int) $product->get_id();
		$parent_id = (int) $product->get_parent_id();

		if ($product_id > 0 && !Foodord_Product_Availability::is_available($product_id)) {
			return false;
		}

		if ($parent_id > 0 && !Foodord_Product_Availability::is_available($parent_id)) {
			return false;
		}

		return $is_purchasable;
	},
	10,
	2
);

if (!function_exists('foodord_cart_mode_is_unavailable')) {
	/**
	 * Determine if the selected order mode should block cart additions.
	 */
	function foodord_cart_mode_is_unavailable(): bool
	{
		if (!class_exists('Foodord_Business_Hours')) {
			return false;
		}

		$mode = function_exists('foodord_get_order_mode') ? foodord_get_order_mode() : 'delivery';
		$mode = ('pickup' === $mode) ? 'pickup' : 'delivery';

		$status = Foodord_Business_Hours::get_status_payload();
		if (!isset($status['modes'][$mode]) || !is_array($status['modes'][$mode])) {
			return false;
		}

		$mode_status = $status['modes'][$mode];
		if (!empty($mode_status['manual_locked']) || !empty($mode_status['locked']) || !empty($mode_status['custom_closed'])) {
			return true;
		}

		if (array_key_exists('is_open', $mode_status)) {
			return empty($mode_status['is_open']);
		}

		return false;
	}
}

add_filter(
	'woocommerce_add_to_cart_validation',
	function ($passed, $product_id, $quantity, $variation_id = 0, $variations = array ()) {
		unset($quantity, $variations);
		if (!$passed) {
			return $passed;
		}

		if (foodord_cart_mode_is_unavailable()) {
			if (function_exists('wc_add_notice')) {
				wc_add_notice(__('We are currently closed. Please try again later.', 'foodord'), 'error');
			}
			return false;
		}

		if (!class_exists('Foodord_Product_Availability')) {
			return $passed;
		}

		$check_ids = array((int) $product_id);
		if ($variation_id) {
			$check_ids[] = (int) $variation_id;
		}

		foreach ($check_ids as $check_id) {
			if ($check_id > 0 && !Foodord_Product_Availability::is_available($check_id)) {
				if (function_exists('wc_add_notice')) {
					wc_add_notice(__('This product is currently unavailable.', 'foodord'), 'error');
				}
				return false;
			}
		}

		return $passed;
	},
	10,
	5
);

// REST API for Electron App.
require_once FOODORD_DIR . 'includes/class-foodord-rest-api.php';
require_once FOODORD_DIR . 'includes/class-foodord-table-reservations-rest-controller.php';
require_once FOODORD_DIR . 'includes/class-foodord-table-ordering.php';

// Initialize shortcodes and blocks.
add_action(
	'plugins_loaded',
	function () {
		if (is_admin() && class_exists('Foodord_Theme_Demo_Importer')) {
			$theme_demo_importer = new Foodord_Theme_Demo_Importer();
			$theme_demo_importer->init();
		}

		new Foodord_Products_Shortcode();
		new Foodord_Products_Block();
		new Foodord_Card_Shortcode();
		new Foodord_Card_Block();
		new Foodord_Table_Reservations_Block();
		new Foodord_Mobile_Cart();
		new Foodord_Email_Order_Actions();

		// Initialize REST API for Electron App.
		$foodord_rest_api = new Foodord_Rest_Api();
		$foodord_rest_api->init();

		$foodord_table_reservations_rest = new Foodord_Table_Reservations_Rest_Controller(
			array( $foodord_rest_api, 'check_authentication' )
		);
		$foodord_table_reservations_rest->init();

		$foodord_table_ordering = new Foodord_Table_Ordering();
		$foodord_table_ordering->init();
	}
);

// Admin bootstrap.
require_once FOODORD_DIR . 'admin/foodord-admin-faq.php';
require_once FOODORD_DIR . 'admin/class-foodord-admin-nav.php';
require_once FOODORD_DIR . 'admin/class-foodord-product-layout.php';
require_once FOODORD_DIR . 'admin/class-foodord-admin.php';
require_once FOODORD_DIR . 'admin/class-foodord-deactivation-feedback.php';
require_once FOODORD_DIR . 'admin/class-foodord-setup-wizard.php';
require_once FOODORD_DIR . 'admin/class-foodord-styling.php';
require_once FOODORD_DIR . 'admin/class-foodord-shortcodes.php';
require_once FOODORD_DIR . 'admin/class-foodord-license.php';
require_once FOODORD_DIR . 'admin/class-foodord-delivery.php';
require_once FOODORD_DIR . 'admin/class-foodord-pickup.php';
require_once FOODORD_DIR . 'admin/class-foodord-toppings.php';
require_once FOODORD_DIR . 'admin/class-foodord-topping-groups.php';
require_once FOODORD_DIR . 'admin/class-foodord-topping-items.php';
require_once FOODORD_DIR . 'admin/class-foodord-topping-sets.php';
require_once FOODORD_DIR . 'admin/class-foodord-tweaks.php';
require_once FOODORD_DIR . 'admin/class-foodord-allergy-info.php';
require_once FOODORD_DIR . 'admin/class-foodord-timed-products-admin.php';
require_once FOODORD_DIR . 'admin/class-foodord-table-reservations-admin.php';
require_once FOODORD_DIR . 'admin/class-foodord-live-orders.php';
require_once FOODORD_DIR . 'admin/class-foodord-theme-recommendation-notice.php';
require_once FOODORD_DIR . 'admin/product-data/class-foodord-product-data-topping-sets.php';
require_once FOODORD_DIR . 'admin/product-data/class-foodord-product-data-allergens.php';
require_once FOODORD_DIR . 'admin/product-data/class-foodord-product-data-labels.php';
require_once FOODORD_DIR . 'admin/product-data/class-foodord-product-data-preorders.php';
add_action(
	'plugins_loaded',
	function () {
		if (is_admin()) {
			$setup_wizard = new Foodord_Setup_Wizard();
			$setup_wizard->init();

			$foodord_admin = new Foodord_Admin();
			$foodord_admin->init();

			$foodord_deactivation_feedback = new Foodord_Deactivation_Feedback();
			$foodord_deactivation_feedback->init();

			$foodord_tweaks = new Foodord_Tweaks();
			$foodord_tweaks->init();

			// Initialize Topping Sets.
			$foodord_topping_sets = new Foodord_Topping_Sets();
			$foodord_topping_sets->init();

			// Initialize Toppings (handles JavaScript enqueuing).
			$foodord_toppings = new Foodord_Toppings();

			// Initialize Topping Groups.
			$foodord_topping_groups = new Foodord_Topping_Groups();

			// Initialize WooCommerce product data tab for topping sets.
			$foodord_product_data_topping_sets = new Foodord_Product_Data_Topping_Sets();
			$foodord_product_data_topping_sets->init();

			// Initialize WooCommerce product data tab for allergens.
			$foodord_product_data_allergens = new Foodord_Product_Data_Allergens();
			$foodord_product_data_allergens->init();

			// Initialize WooCommerce product data tab for product labels.
			$foodord_product_data_labels = new Foodord_Product_Data_Labels();
			$foodord_product_data_labels->init();

			// Initialize WooCommerce product data tab for reservation pre-orders.
			$foodord_product_data_preorders = new Foodord_Product_Data_Preorders();
			$foodord_product_data_preorders->init();

			$foodord_timed_products_admin = new Foodord_Timed_Products_Admin();
			$foodord_timed_products_admin->init();

			$foodord_table_reservations_admin = new Foodord_Table_Reservations_Admin();
			$foodord_table_reservations_admin->init();

			$foodord_live_orders_admin = new Foodord_Live_Orders_Admin();
			$foodord_live_orders_admin->init();

			$foodord_theme_recommendation_notice = new Foodord_Theme_Recommendation_Notice();
			$foodord_theme_recommendation_notice->init();
		}
	}
);

add_action(
	'admin_init',
	static function () {
		if (class_exists('Foodord_Table_Reservations')) {
			Foodord_Table_Reservations::maybe_install();
		}
	}
);

// Core admin features.
require_once FOODORD_DIR . 'admin/class-foodord-allergy-info.php';

// Frontend dynamic CSS for Back to Top button.
require_once FOODORD_DIR . 'public/class-foodord-back-to-top-customizer.php';

// Frontend styling overrides (admin-controlled).
require_once FOODORD_DIR . 'public/class-foodord-styling-frontend.php';

// Ensure default color migration runs once in ALL contexts (admin + frontend).
add_action(
	'init',
	function () {
		$customizer = new Foodord_Back_To_Top_Customizer();
		$customizer->maybe_migrate_old_defaults();
	}
);

// Initialize runtime hooks (enqueue etc.) for frontend only.
add_action(
	'plugins_loaded',
	function () {
		if (!is_admin()) {
			$customizer = new Foodord_Back_To_Top_Customizer();
			$customizer->init();

			$styling_frontend = new Foodord_Styling_Frontend();
			$styling_frontend->init();
		}

		$foodord_timed_products_frontend = new Foodord_Timed_Products_Frontend();
		$foodord_timed_products_frontend->init();
	}
);


add_action(
	'plugins_loaded',
	function () {
		// Initialize Allergy Info - must be called regardless of is_admin
		// because AJAX requests need the hooks registered in init_frontend.
		// The method itself handles is_admin check for frontend-only hooks.
		$allergy_info_frontend = new Foodord_Allergy_Info();
		$allergy_info_frontend->init_frontend();
	}
);

// Product Modal System.
require_once FOODORD_DIR . 'public/class-foodord-product-modal-upsells.php';
require_once FOODORD_DIR . 'public/class-foodord-card-upsells.php';
require_once FOODORD_DIR . 'public/class-foodord-product-modal.php';
require_once FOODORD_DIR . 'public/class-foodord-timed-products-frontend.php';
add_action(
	'init',
	function () {
		$product_modal = new Foodord_Product_Modal();
		$product_modal->init();
	}
);

require_once FOODORD_DIR . 'public/class-foodord-location-modal.php';
add_action(
	'init',
	function () {
		if (class_exists('Foodord_Location_Modal')) {
			Foodord_Location_Modal::register_ajax();
		}
	}
);
add_action(
	'init',
	function () {
		if (!is_admin() && class_exists('Foodord_Location_Modal')) {
			$foodord_location_modal = new Foodord_Location_Modal();
			$foodord_location_modal->init();
		}
	}
);


// Initialize Checkout Validator.
add_action(
	'init',
	function () {
		if (class_exists('WooCommerce') && class_exists('Foodord_Checkout_Validator')) {
			$checkout_validator = new Foodord_Checkout_Validator();
			$checkout_validator->init();
		}
	}
);

// Scroll Categories Navigation under banner (frontend).
require_once FOODORD_DIR . 'public/class-foodord-scroll-categories-nav.php';
add_action(
	'init',
	function () {
		if (!is_admin()) {
			$foodord_scroll_nav = new Foodord_Scroll_Categories_Nav();
			$foodord_scroll_nav->init();
		}
	}
);

// Delivery/Pickup mode toggle above cart header (frontend).
require_once FOODORD_DIR . 'public/class-foodord-delivery-pickup-toggle.php';
add_action(
	'init',
	function () {
		if (!is_admin()) {
			$foodord_dp_toggle = new Foodord_Delivery_Pickup_Toggle();
			$foodord_dp_toggle->init();
		}
	}
);

// Checkout Country/Region toggle (frontend).
require_once FOODORD_DIR . 'public/class-foodord-checkout-country-toggle.php';
add_action(
	'init',
	function () {
		if (!is_admin()) {
			$foodord_checkout_country_toggle = new Foodord_Checkout_Country_Toggle();
			$foodord_checkout_country_toggle->init();
		}
	}
);

// Checkout: Lock City and Postcode inputs (frontend; classic + blocks via JS).
require_once FOODORD_DIR . 'public/class-foodord-checkout-lock-address.php';
add_action(
	'init',
	function () {
		if (!is_admin()) {
			$foodord_lock_address = new Foodord_Checkout_Lock_Address();
			$foodord_lock_address->init();
		}
	}
);

// Checkout: Time To Deliver dropdown (frontend; classic + blocks via JS).
require_once FOODORD_DIR . 'public/class-foodord-time-to-deliver-frontend.php';
add_action(
	'init',
	function () {
		if (!is_admin() && class_exists('Foodord_Time_To_Deliver_Frontend')) {
			$foodord_ttd_frontend = new Foodord_Time_To_Deliver_Frontend();
			$foodord_ttd_frontend->init();
		}
	}
);

// Checkout: Time To Pickup dropdown (frontend; classic + blocks via JS).
require_once FOODORD_DIR . 'public/class-foodord-time-to-pickup-frontend.php';
add_action(
	'init',
	function () {
		if (!is_admin() && class_exists('Foodord_Time_To_Pickup_Frontend')) {
			$foodord_ttp_frontend = new Foodord_Time_To_Pickup_Frontend();
			$foodord_ttp_frontend->init();
		}
	}
);

// Delivery Fee integration (respect card mode: skip when pickup is selected).
	add_action(
		'woocommerce_cart_calculate_fees',
		function ($cart) {
			if (foodord_is_table_ordering_request()) {
				foodord_track_delivery_fee(0.0);
				return;
			}

		if (!$cart || !method_exists($cart, 'get_cart_contents_count')) {
			foodord_track_delivery_fee(0.0);
			return;
		}
		// Do not add any fee if cart is empty.
		if (0 === (int) $cart->get_cart_contents_count()) {
			foodord_track_delivery_fee(0.0);
			return;
		}

		// Read mode from WooCommerce session (set by card toggle): default 'delivery'.
		$mode = 'delivery';
		if (function_exists('WC') && WC()->session) {
			$session_mode = (string) WC()->session->get('foodord_order_mode', 'delivery');
			if (in_array($session_mode, array('delivery', 'pickup'), true)) {
				$mode = $session_mode;
			}
		}
		if ('pickup' === $mode) {
			foodord_track_delivery_fee(0.0);
			return; // No delivery fee for pickup mode.
		}

		$type = get_option('foodord_delivery_fee_type', 'fixed');
		$amount = 0.0;

		// Require a valid allowed address in delivery mode for any delivery fee.
		$session = class_exists('Foodord_Location_Service') ? Foodord_Location_Service::get_session() : array();

		$has_allowed = !empty($session['allowed']);
		if (!$has_allowed) {
			foodord_track_delivery_fee(0.0);
			return; // No address set/allowed: do not add any delivery fee.
		}

		if ('fixed' === $type) {
			$raw = get_option('foodord_delivery_fee_fixed', '0');
			if (function_exists('wc_format_decimal')) {
				$amount = (float) wc_format_decimal($raw);
			} else {
				$amount = (float) $raw;
			}
		} elseif ('distance' === $type && class_exists('Foodord_Location_Service')) {
			$delivery_mode = Foodord_Location_Service::get_delivery_mode();
			$session_fee = isset($session['fee']) ? (float) $session['fee'] : 0.0;
			$radius_zone = 'radius' === $delivery_mode ? Foodord_Location_Service::sync_current_radius_zone_for_cart($cart) : null;
			if (is_array($radius_zone)) {
				$amount = isset($radius_zone['fee']) ? max(0.0, (float) $radius_zone['fee']) : 0.0;
				$debug_ctx['source'] = 'radius_tier';
				$debug_ctx['amount'] = $amount;
				$debug_ctx['radius'] = isset($radius_zone['radius']) ? (float) $radius_zone['radius'] : 0.0;
				$debug_ctx['tier_minimum'] = isset($radius_zone['tier_minimum']) ? (float) $radius_zone['tier_minimum'] : 0.0;
			} elseif ($session_fee > 0) {
				$amount = max(0.0, $session_fee);
				$debug_ctx['source'] = 'session_fee';
				$debug_ctx['amount'] = $amount;
			} elseif ('postal' === $delivery_mode) {
				$city = isset($session['city']) ? (string) $session['city'] : '';
				$postal = isset($session['postal']) ? (string) $session['postal'] : '';
				if ('' !== $city) {
					$amount = Foodord_Location_Service::fee_for_city_postal($city, $postal);
					$debug_ctx['source'] = 'session_lookup';
					$debug_ctx['lookup_fee'] = $amount;
				}
			}
		} else {
			return;
		}
		foodord_track_delivery_fee($amount);
		if ($amount > 0) {
			$cart->add_fee(__('Delivery fee', 'foodord'), $amount, false, '');
		}
	},
	20
);

if (!function_exists('foodord_handle_order_mode_ajax')) {
	/**
	 * Common handler that persists mode in session + cookie (front + guests).
	 */
	function foodord_handle_order_mode_ajax(): void
	{
		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
		if (!wp_verify_nonce($nonce, 'foodord_order_mode')) {
			wp_send_json_error(array('message' => 'Invalid nonce'), 403);
		}

		$mode = isset($_POST['mode']) ? sanitize_text_field(wp_unslash($_POST['mode'])) : 'delivery';
		$mode = in_array($mode, array('delivery', 'pickup'), true) ? $mode : 'delivery';

		$session = null;
		$session_had_cookie = null;
		if (function_exists('WC') && WC()->session) {
			$session = WC()->session;

			$session_had_cookie = method_exists($session, 'has_session') ? (bool) $session->has_session() : null;
			if (method_exists($session, 'set_customer_session_cookie') && (null === $session_had_cookie || !$session_had_cookie)) {
				$session->set_customer_session_cookie(true);
			}
			$session->set('foodord_order_mode', $mode);

			// When switching between pickup/delivery, any cached toppings base price can become stale
			// (e.g. pickup-only discounts). Force a fresh recomputation on the next totals calculation.
			if (function_exists('WC') && WC()->cart && isset(WC()->cart->cart_contents) && is_array(WC()->cart->cart_contents)) {
				foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
					if (!isset(WC()->cart->cart_contents[$cart_item_key]) || !is_array(WC()->cart->cart_contents[$cart_item_key])) {
						continue;
					}
					if (!empty($cart_item['foodord_toppings']) && is_array($cart_item['foodord_toppings']) && isset(WC()->cart->cart_contents[$cart_item_key]['foodord_toppings_base_price'])) {
						unset(WC()->cart->cart_contents[$cart_item_key]['foodord_toppings_base_price']);
					}
				}
			}

			if (method_exists($session, 'save_data')) {
				$session->save_data();
			}
			if (WC()->cart) {
				WC()->cart->calculate_totals();
			}
		}

		$expired = time() - DAY_IN_SECONDS;
		if (function_exists('wc_setcookie')) {
			wc_setcookie('foodord_order_mode', '', $expired);
		} else {
			$cookie_path = defined('COOKIEPATH') ? COOKIEPATH : '/';
			$cookie_domain = defined('COOKIE_DOMAIN') ? COOKIE_DOMAIN : '';
			setcookie('foodord_order_mode', '', $expired, $cookie_path, $cookie_domain, is_ssl(), true);
		}

		wp_send_json_success(array('mode' => $mode));
	}
}

// AJAX: persist order mode (logged-in + guests).
add_action('wp_ajax_foodord_set_order_mode', 'foodord_handle_order_mode_ajax');
add_action('wp_ajax_nopriv_foodord_set_order_mode', 'foodord_handle_order_mode_ajax');

if (!function_exists('foodord_sanitize_scheduled_date_value')) {
	/**
	 * Sanitize a scheduled date value (YYYY-MM-DD) and ensure it is within allowed range.
	 *
	 * Returns empty string when invalid or when the feature is disabled for the mode.
	 *
	 * @param string $date Raw date.
	 * @param string $mode Mode slug ('delivery'|'pickup').
	 * @return string
	 */
	function foodord_sanitize_scheduled_date_value(string $date, string $mode): string
	{
		$mode = ('pickup' === $mode) ? 'pickup' : 'delivery';

		$enabled = 'yes' === get_option('foodord_scheduled_date_enabled_' . $mode, 'no');
		if (!$enabled) {
			return '';
		}

		$date = sanitize_text_field($date);
		if ('' === $date) {
			return '';
		}

		if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
			return '';
		}

		$max_days = absint(get_option('foodord_scheduled_date_max_days_' . $mode, 7));
		if ($max_days < 1 || $max_days > 365) {
			$max_days = 7;
		}

		$timezone = wp_timezone();
		$today = wp_date('Y-m-d', time(), $timezone);

		try {
			$max_date_dt = new DateTimeImmutable($today, $timezone);
			$max_date_dt = $max_date_dt->modify('+' . $max_days . ' days');
			$max_date = $max_date_dt->format('Y-m-d');
		} catch (Exception $e) {
			unset($e);
			$max_date = $today;
		}

		// YYYY-MM-DD can be compared lexicographically.
		if ($date < $today || $date > $max_date) {
			return '';
		}

		return $date;
	}
}

// AJAX: persist selected delivery date in WooCommerce session.
add_action(
	'wp_ajax_foodord_set_delivery_date',
	function () {
		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
		if (!wp_verify_nonce($nonce, 'foodord_delivery_date')) {
			wp_send_json_error(array('message' => 'Invalid nonce'), 403);
		}

		$date = isset($_POST['date']) ? sanitize_text_field(wp_unslash($_POST['date'])) : '';
		$date = foodord_sanitize_scheduled_date_value($date, 'delivery');

		if (function_exists('WC') && WC()->session) {
			WC()->session->set('foodord_delivery_date', $date);
		}

		wp_send_json_success(array('date' => $date));
	}
);
add_action(
	'wp_ajax_nopriv_foodord_set_delivery_date',
	function () {
		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
		if (!wp_verify_nonce($nonce, 'foodord_delivery_date')) {
			wp_send_json_error(array('message' => 'Invalid nonce'), 403);
		}

		$date = isset($_POST['date']) ? sanitize_text_field(wp_unslash($_POST['date'])) : '';
		$date = foodord_sanitize_scheduled_date_value($date, 'delivery');

		if (function_exists('WC') && WC()->session) {
			WC()->session->set('foodord_delivery_date', $date);
		}

		wp_send_json_success(array('date' => $date));
	}
);

// AJAX: persist selected pickup date in WooCommerce session.
add_action(
	'wp_ajax_foodord_set_pickup_date',
	function () {
		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
		if (!wp_verify_nonce($nonce, 'foodord_pickup_date')) {
			wp_send_json_error(array('message' => 'Invalid nonce'), 403);
		}

		$date = isset($_POST['date']) ? sanitize_text_field(wp_unslash($_POST['date'])) : '';
		$date = foodord_sanitize_scheduled_date_value($date, 'pickup');

		if (function_exists('WC') && WC()->session) {
			WC()->session->set('foodord_pickup_date', $date);
		}

		wp_send_json_success(array('date' => $date));
	}
);
add_action(
	'wp_ajax_nopriv_foodord_set_pickup_date',
	function () {
		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
		if (!wp_verify_nonce($nonce, 'foodord_pickup_date')) {
			wp_send_json_error(array('message' => 'Invalid nonce'), 403);
		}

		$date = isset($_POST['date']) ? sanitize_text_field(wp_unslash($_POST['date'])) : '';
		$date = foodord_sanitize_scheduled_date_value($date, 'pickup');

		if (function_exists('WC') && WC()->session) {
			WC()->session->set('foodord_pickup_date', $date);
		}

		wp_send_json_success(array('date' => $date));
	}
);

// AJAX: fetch time slot options for a selected delivery date.
add_action(
	'wp_ajax_foodord_get_delivery_slots',
	function () {
		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
		if (!wp_verify_nonce($nonce, 'foodord_delivery_slots')) {
			wp_send_json_error(array('message' => 'Invalid nonce'), 403);
		}

		$date = isset($_POST['date']) ? sanitize_text_field(wp_unslash($_POST['date'])) : '';
		$date = foodord_sanitize_scheduled_date_value($date, 'delivery');
		if ('' === $date) {
			wp_send_json_error(array('message' => 'Invalid date'), 400);
		}

		$timezone = wp_timezone();
		$today = wp_date('Y-m-d', time(), $timezone);
		$is_today = ($date === $today);

		$slots = array('options' => array());
		if (class_exists('Foodord_Business_Hours')) {
			if ($is_today) {
				$slots = Foodord_Business_Hours::get_mode_slots('delivery');
			} else {
				try {
					$ref = new DateTimeImmutable($date . ' 00:00:00', $timezone);
					$slots = Foodord_Business_Hours::get_mode_slots('delivery', $ref, false);
				} catch (Exception $e) {
					unset($e);
					$slots = array('options' => array());
				}
			}
		}

		$allow_asap = false;
		$preorder_enabled = false;
		$preorder_open = false;
		$is_open = false;
		if ($is_today && class_exists('Foodord_Business_Hours')) {
			$status = Foodord_Business_Hours::get_status_payload();
			if (isset($status['modes']['delivery']) && is_array($status['modes']['delivery'])) {
				$mode_status = $status['modes']['delivery'];
				if (isset($mode_status['is_open'])) {
					$is_open = (bool) $mode_status['is_open'];
				}
				if (isset($mode_status['regular_open'])) {
					$allow_asap = (bool) $mode_status['regular_open'];
				}
				if (!empty($mode_status['manual_locked']) || !empty($mode_status['custom_closed'])) {
					$allow_asap = false;
				}
				if (isset($mode_status['preorder_enabled'])) {
					$preorder_enabled = (bool) $mode_status['preorder_enabled'];
				}
				if (isset($mode_status['preorder_open'])) {
					$preorder_open = (bool) $mode_status['preorder_open'];
				}
			}
		}

		wp_send_json_success(
			array(
				'date' => $date,
				'isToday' => $is_today,
				'options' => isset($slots['options']) && is_array($slots['options']) ? $slots['options'] : array(),
				'isOpen' => $is_open,
				'allowAsap' => $allow_asap,
				'preorderEnabled' => $preorder_enabled,
				'preorderOpen' => $preorder_open,
			)
		);
	}
);
add_action(
	'wp_ajax_nopriv_foodord_get_delivery_slots',
	function () {
		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
		if (!wp_verify_nonce($nonce, 'foodord_delivery_slots')) {
			wp_send_json_error(array('message' => 'Invalid nonce'), 403);
		}

		$date = isset($_POST['date']) ? sanitize_text_field(wp_unslash($_POST['date'])) : '';
		$date = foodord_sanitize_scheduled_date_value($date, 'delivery');
		if ('' === $date) {
			wp_send_json_error(array('message' => 'Invalid date'), 400);
		}

		$timezone = wp_timezone();
		$today = wp_date('Y-m-d', time(), $timezone);
		$is_today = ($date === $today);

		$slots = array('options' => array());
		if (class_exists('Foodord_Business_Hours')) {
			if ($is_today) {
				$slots = Foodord_Business_Hours::get_mode_slots('delivery');
			} else {
				try {
					$ref = new DateTimeImmutable($date . ' 00:00:00', $timezone);
					$slots = Foodord_Business_Hours::get_mode_slots('delivery', $ref, false);
				} catch (Exception $e) {
					unset($e);
					$slots = array('options' => array());
				}
			}
		}

		$allow_asap = false;
		$preorder_enabled = false;
		$preorder_open = false;
		$is_open = false;
		if ($is_today && class_exists('Foodord_Business_Hours')) {
			$status = Foodord_Business_Hours::get_status_payload();
			if (isset($status['modes']['delivery']) && is_array($status['modes']['delivery'])) {
				$mode_status = $status['modes']['delivery'];
				if (isset($mode_status['is_open'])) {
					$is_open = (bool) $mode_status['is_open'];
				}
				if (isset($mode_status['regular_open'])) {
					$allow_asap = (bool) $mode_status['regular_open'];
				}
				if (!empty($mode_status['manual_locked']) || !empty($mode_status['custom_closed'])) {
					$allow_asap = false;
				}
				if (isset($mode_status['preorder_enabled'])) {
					$preorder_enabled = (bool) $mode_status['preorder_enabled'];
				}
				if (isset($mode_status['preorder_open'])) {
					$preorder_open = (bool) $mode_status['preorder_open'];
				}
			}
		}

		wp_send_json_success(
			array(
				'date' => $date,
				'isToday' => $is_today,
				'options' => isset($slots['options']) && is_array($slots['options']) ? $slots['options'] : array(),
				'isOpen' => $is_open,
				'allowAsap' => $allow_asap,
				'preorderEnabled' => $preorder_enabled,
				'preorderOpen' => $preorder_open,
			)
		);
	}
);

// AJAX: fetch time slot options for a selected pickup date.
add_action(
	'wp_ajax_foodord_get_pickup_slots',
	function () {
		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
		if (!wp_verify_nonce($nonce, 'foodord_pickup_slots')) {
			wp_send_json_error(array('message' => 'Invalid nonce'), 403);
		}

		$date = isset($_POST['date']) ? sanitize_text_field(wp_unslash($_POST['date'])) : '';
		$date = foodord_sanitize_scheduled_date_value($date, 'pickup');
		if ('' === $date) {
			wp_send_json_error(array('message' => 'Invalid date'), 400);
		}

		$timezone = wp_timezone();
		$today = wp_date('Y-m-d', time(), $timezone);
		$is_today = ($date === $today);

		$slots = array('options' => array());
		if (class_exists('Foodord_Business_Hours')) {
			if ($is_today) {
				$slots = Foodord_Business_Hours::get_mode_slots('pickup');
			} else {
				try {
					$ref = new DateTimeImmutable($date . ' 00:00:00', $timezone);
					$slots = Foodord_Business_Hours::get_mode_slots('pickup', $ref, false);
				} catch (Exception $e) {
					unset($e);
					$slots = array('options' => array());
				}
			}
		}

		$allow_asap = false;
		$preorder_enabled = false;
		$preorder_open = false;
		$is_open = false;
		if ($is_today && class_exists('Foodord_Business_Hours')) {
			$status = Foodord_Business_Hours::get_status_payload();
			if (isset($status['modes']['pickup']) && is_array($status['modes']['pickup'])) {
				$mode_status = $status['modes']['pickup'];
				if (isset($mode_status['is_open'])) {
					$is_open = (bool) $mode_status['is_open'];
				}
				if (isset($mode_status['regular_open'])) {
					$allow_asap = (bool) $mode_status['regular_open'];
				}
				if (!empty($mode_status['manual_locked']) || !empty($mode_status['custom_closed'])) {
					$allow_asap = false;
				}
				if (isset($mode_status['preorder_enabled'])) {
					$preorder_enabled = (bool) $mode_status['preorder_enabled'];
				}
				if (isset($mode_status['preorder_open'])) {
					$preorder_open = (bool) $mode_status['preorder_open'];
				}
			}
		}

		wp_send_json_success(
			array(
				'date' => $date,
				'isToday' => $is_today,
				'options' => isset($slots['options']) && is_array($slots['options']) ? $slots['options'] : array(),
				'isOpen' => $is_open,
				'allowAsap' => $allow_asap,
				'preorderEnabled' => $preorder_enabled,
				'preorderOpen' => $preorder_open,
			)
		);
	}
);
add_action(
	'wp_ajax_nopriv_foodord_get_pickup_slots',
	function () {
		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
		if (!wp_verify_nonce($nonce, 'foodord_pickup_slots')) {
			wp_send_json_error(array('message' => 'Invalid nonce'), 403);
		}

		$date = isset($_POST['date']) ? sanitize_text_field(wp_unslash($_POST['date'])) : '';
		$date = foodord_sanitize_scheduled_date_value($date, 'pickup');
		if ('' === $date) {
			wp_send_json_error(array('message' => 'Invalid date'), 400);
		}

		$timezone = wp_timezone();
		$today = wp_date('Y-m-d', time(), $timezone);
		$is_today = ($date === $today);

		$slots = array('options' => array());
		if (class_exists('Foodord_Business_Hours')) {
			if ($is_today) {
				$slots = Foodord_Business_Hours::get_mode_slots('pickup');
			} else {
				try {
					$ref = new DateTimeImmutable($date . ' 00:00:00', $timezone);
					$slots = Foodord_Business_Hours::get_mode_slots('pickup', $ref, false);
				} catch (Exception $e) {
					unset($e);
					$slots = array('options' => array());
				}
			}
		}

		$allow_asap = false;
		$preorder_enabled = false;
		$preorder_open = false;
		$is_open = false;
		if ($is_today && class_exists('Foodord_Business_Hours')) {
			$status = Foodord_Business_Hours::get_status_payload();
			if (isset($status['modes']['pickup']) && is_array($status['modes']['pickup'])) {
				$mode_status = $status['modes']['pickup'];
				if (isset($mode_status['is_open'])) {
					$is_open = (bool) $mode_status['is_open'];
				}
				if (isset($mode_status['regular_open'])) {
					$allow_asap = (bool) $mode_status['regular_open'];
				}
				if (!empty($mode_status['manual_locked']) || !empty($mode_status['custom_closed'])) {
					$allow_asap = false;
				}
				if (isset($mode_status['preorder_enabled'])) {
					$preorder_enabled = (bool) $mode_status['preorder_enabled'];
				}
				if (isset($mode_status['preorder_open'])) {
					$preorder_open = (bool) $mode_status['preorder_open'];
				}
			}
		}

		wp_send_json_success(
			array(
				'date' => $date,
				'isToday' => $is_today,
				'options' => isset($slots['options']) && is_array($slots['options']) ? $slots['options'] : array(),
				'isOpen' => $is_open,
				'allowAsap' => $allow_asap,
				'preorderEnabled' => $preorder_enabled,
				'preorderOpen' => $preorder_open,
			)
		);
	}
);

// AJAX: persist selected delivery time in WooCommerce session.
add_action(
	'wp_ajax_foodord_set_delivery_time',
	function () {
		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
		if (!wp_verify_nonce($nonce, 'foodord_delivery_time')) {
			wp_send_json_error(array('message' => 'Invalid nonce'), 403);
		}
		$time = isset($_POST['time']) ? sanitize_text_field(wp_unslash($_POST['time'])) : '';
		$upper = strtoupper((string) $time);
		if (!is_string($time) || (!preg_match('/^\d{2}:\d{2}$/', $time) && 'ASAP' !== $upper)) {
			$time = '';
		} else {
			$time = ('ASAP' === $upper) ? 'ASAP' : $time;
		}
		if (function_exists('WC') && WC()->session) {
			WC()->session->set('foodord_delivery_time', $time);
		}
		wp_send_json_success(array('time' => $time));
	}
);

// AJAX: persist selected pickup time in WooCommerce session.
add_action(
	'wp_ajax_foodord_set_pickup_time',
	function () {
		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
		if (!wp_verify_nonce($nonce, 'foodord_pickup_time')) {
			wp_send_json_error(array('message' => 'Invalid nonce'), 403);
		}
		$time = isset($_POST['time']) ? sanitize_text_field(wp_unslash($_POST['time'])) : '';
		$upper = strtoupper((string) $time);
		if (!is_string($time) || (!preg_match('/^\d{2}:\d{2}$/', $time) && 'ASAP' !== $upper)) {
			$time = '';
		} else {
			$time = ('ASAP' === $upper) ? 'ASAP' : $time;
		}
		if (function_exists('WC') && WC()->session) {
			WC()->session->set('foodord_pickup_time', $time);
		}
		wp_send_json_success(array('time' => $time));
	}
);

// AJAX (nopriv): persist selected pickup time in WooCommerce session.
add_action(
	'wp_ajax_nopriv_foodord_set_pickup_time',
	function () {
		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
		if (!wp_verify_nonce($nonce, 'foodord_pickup_time')) {
			wp_send_json_error(array('message' => 'Invalid nonce'), 403);
		}
		$time = isset($_POST['time']) ? sanitize_text_field(wp_unslash($_POST['time'])) : '';
		$upper = strtoupper((string) $time);
		if (!is_string($time) || (!preg_match('/^\d{2}:\d{2}$/', $time) && 'ASAP' !== $upper)) {
			$time = '';
		} else {
			$time = ('ASAP' === $upper) ? 'ASAP' : $time;
		}
		if (function_exists('WC') && WC()->session) {
			WC()->session->set('foodord_pickup_time', $time);
		}
		wp_send_json_success(array('time' => $time));
	}
);

// Persist order mode on the order for thank you / account views.
add_action(
	'woocommerce_checkout_create_order',
	function ($order, $data) {
		if (!is_a($order, 'WC_Order')) {
			return;
		}

		$mode = 'delivery';
		// Prefer provided $data array (classic checkout data).
		if (is_array($data) && isset($data['foodord_order_mode'])) {
			$posted_mode = sanitize_text_field($data['foodord_order_mode']);
			if (in_array($posted_mode, array('delivery', 'pickup'), true)) {
				$mode = $posted_mode;
			}
		} elseif (function_exists('WC') && WC()->session) {
			$session_mode = (string) WC()->session->get('foodord_order_mode', 'delivery');
			if (in_array($session_mode, array('delivery', 'pickup'), true)) {
				$mode = $session_mode;
			}
		}

		$order->update_meta_data('_foodord_order_mode', $mode);
		$order->update_meta_data('foodord_order_mode', $mode); // Mirror for template consumption.
	
		$timezone = wp_timezone();
		$order_created = $order->get_date_created();
		$order_created_ts = $order_created ? $order_created->getTimestamp() : time();
		$order_created_day = wp_date('Y-m-d', $order_created_ts, $timezone);

		// Classic checkout (delivery): ensure shipping address is present.
		// Some classic checkout flows only persist billing address, leaving shipping empty.
		$ship_to_different = false;
		if (is_array($data) && isset($data['ship_to_different_address'])) {
			$ship_to_different = !empty($data['ship_to_different_address']) && '0' !== (string) $data['ship_to_different_address'];
		} elseif (
			isset($_POST['ship_to_different_address'], $_POST['woocommerce-process-checkout-nonce'])
			&& wp_verify_nonce(
				sanitize_text_field(wp_unslash($_POST['woocommerce-process-checkout-nonce'])),
				'woocommerce-process_checkout'
			)
		) {
			$ship_to_different = !empty($_POST['ship_to_different_address']) && '0' !== (string) sanitize_text_field(wp_unslash($_POST['ship_to_different_address']));
		}

		$billing_has_address = (bool) ($order->get_billing_address_1() || $order->get_billing_city() || $order->get_billing_postcode());
		$shipping_has_address = (bool) ($order->get_shipping_address_1() || $order->get_shipping_city() || $order->get_shipping_postcode());
		if ('delivery' === $mode && !$ship_to_different && !$shipping_has_address && $billing_has_address) {
			$order->set_shipping_first_name($order->get_billing_first_name());
			$order->set_shipping_last_name($order->get_billing_last_name());
			$order->set_shipping_company($order->get_billing_company());
			$order->set_shipping_address_1($order->get_billing_address_1());
			$order->set_shipping_address_2($order->get_billing_address_2());
			$order->set_shipping_city($order->get_billing_city());
			$order->set_shipping_state($order->get_billing_state());
			$order->set_shipping_postcode($order->get_billing_postcode());
			$order->set_shipping_country($order->get_billing_country());
		}

		// Persist selected delivery time from classic checkout submission.
		$time = '';
		if (is_array($data) && isset($data['foodord_delivery_time'])) {
			$raw_time = sanitize_text_field($data['foodord_delivery_time']);
			$upper = strtoupper($raw_time);
			if (preg_match('/^\d{2}:\d{2}$/', $raw_time) || 'ASAP' === $upper) {
				$time = ('ASAP' === $upper) ? 'ASAP' : $raw_time;
			}
		} elseif (
			isset($_POST['foodord_delivery_time'], $_POST['woocommerce-process-checkout-nonce'])
			&& wp_verify_nonce(
				sanitize_text_field(wp_unslash($_POST['woocommerce-process-checkout-nonce'])),
				'woocommerce-process_checkout'
			)
		) {
			$raw_time = sanitize_text_field(wp_unslash($_POST['foodord_delivery_time']));
			$upper = strtoupper($raw_time);
			if (preg_match('/^\d{2}:\d{2}$/', $raw_time) || 'ASAP' === $upper) {
				$time = ('ASAP' === $upper) ? 'ASAP' : $raw_time;
			}
		} elseif (function_exists('WC') && WC()->session) {
			$session_time = (string) WC()->session->get('foodord_delivery_time', '');
			$upper = strtoupper($session_time);
			if (preg_match('/^\d{2}:\d{2}$/', $session_time) || 'ASAP' === $upper) {
				$time = ('ASAP' === $upper) ? 'ASAP' : $session_time;
			}
		}
		if ('delivery' === $mode && $time) {
			$order->update_meta_data('_foodord_delivery_time', $time);
			$order->update_meta_data('foodord_delivery_time', $time);
		}

		// Persist selected pickup time from classic checkout submission or session.
		$pickup_time = '';
		if (is_array($data) && isset($data['foodord_pickup_time'])) {
			$raw_time = sanitize_text_field($data['foodord_pickup_time']);
			$upper = strtoupper($raw_time);
			if (preg_match('/^\d{2}:\d{2}$/', $raw_time) || 'ASAP' === $upper) {
				$pickup_time = ('ASAP' === $upper) ? 'ASAP' : $raw_time;
			}
		} elseif (
			isset($_POST['foodord_pickup_time'], $_POST['woocommerce-process-checkout-nonce'])
			&& wp_verify_nonce(
				sanitize_text_field(wp_unslash($_POST['woocommerce-process-checkout-nonce'])),
				'woocommerce-process_checkout'
			)
		) {
			$raw_time = sanitize_text_field(wp_unslash($_POST['foodord_pickup_time']));
			$upper = strtoupper($raw_time);
			if (preg_match('/^\d{2}:\d{2}$/', $raw_time) || 'ASAP' === $upper) {
				$pickup_time = ('ASAP' === $upper) ? 'ASAP' : $raw_time;
			}
		} elseif (function_exists('WC') && WC()->session) {
			$session_pickup = (string) WC()->session->get('foodord_pickup_time', '');
			if (is_string($session_pickup)) {
				$upper = strtoupper($session_pickup);
				if (preg_match('/^\d{2}:\d{2}$/', $session_pickup) || 'ASAP' === $upper) {
					$pickup_time = ('ASAP' === $upper) ? 'ASAP' : $session_pickup;
				}
			}
		}
		if ('pickup' === $mode && $pickup_time) {
			$order->update_meta_data('_foodord_pickup_time', $pickup_time);
			$order->update_meta_data('foodord_pickup_time', $pickup_time);
		}

		// Persist scheduled dates (only when scheduled for a future day).
		$delivery_date = '';
		if (is_array($data) && isset($data['foodord_delivery_date'])) {
			$raw_date = sanitize_text_field((string) $data['foodord_delivery_date']);
			$delivery_date = foodord_sanitize_scheduled_date_value($raw_date, 'delivery');
		} elseif (
			isset($_POST['foodord_delivery_date'], $_POST['woocommerce-process-checkout-nonce'])
			&& wp_verify_nonce(
				sanitize_text_field(wp_unslash($_POST['woocommerce-process-checkout-nonce'])),
				'woocommerce-process_checkout'
			)
		) {
			$raw_date = sanitize_text_field(wp_unslash($_POST['foodord_delivery_date']));
			$delivery_date = foodord_sanitize_scheduled_date_value($raw_date, 'delivery');
		} elseif (function_exists('WC') && WC()->session) {
			$session_date = (string) WC()->session->get('foodord_delivery_date', '');
			$delivery_date = foodord_sanitize_scheduled_date_value($session_date, 'delivery');
		}

		$pickup_date = '';
		if (is_array($data) && isset($data['foodord_pickup_date'])) {
			$raw_date = sanitize_text_field((string) $data['foodord_pickup_date']);
			$pickup_date = foodord_sanitize_scheduled_date_value($raw_date, 'pickup');
		} elseif (
			isset($_POST['foodord_pickup_date'], $_POST['woocommerce-process-checkout-nonce'])
			&& wp_verify_nonce(
				sanitize_text_field(wp_unslash($_POST['woocommerce-process-checkout-nonce'])),
				'woocommerce-process_checkout'
			)
		) {
			$raw_date = sanitize_text_field(wp_unslash($_POST['foodord_pickup_date']));
			$pickup_date = foodord_sanitize_scheduled_date_value($raw_date, 'pickup');
		} elseif (function_exists('WC') && WC()->session) {
			$session_date = (string) WC()->session->get('foodord_pickup_date', '');
			$pickup_date = foodord_sanitize_scheduled_date_value($session_date, 'pickup');
		}

		if ('delivery' === $mode) {
			if ($delivery_date && $delivery_date > $order_created_day) {
				$order->update_meta_data('_foodord_delivery_date', $delivery_date);
				$order->update_meta_data('foodord_delivery_date', $delivery_date);
			} else {
				$order->delete_meta_data('_foodord_delivery_date');
				$order->delete_meta_data('foodord_delivery_date');
			}

			$order->delete_meta_data('_foodord_pickup_date');
			$order->delete_meta_data('foodord_pickup_date');
			$order->delete_meta_data('_foodord_pickup_time');
			$order->delete_meta_data('foodord_pickup_time');
		} else {
			if ($pickup_date && $pickup_date > $order_created_day) {
				$order->update_meta_data('_foodord_pickup_date', $pickup_date);
				$order->update_meta_data('foodord_pickup_date', $pickup_date);
			} else {
				$order->delete_meta_data('_foodord_pickup_date');
				$order->delete_meta_data('foodord_pickup_date');
			}

			$order->delete_meta_data('_foodord_delivery_date');
			$order->delete_meta_data('foodord_delivery_date');
			$order->delete_meta_data('_foodord_delivery_time');
			$order->delete_meta_data('foodord_delivery_time');
		}
	},
	20,
	2
);

add_action(
	'woocommerce_checkout_create_order',
	function ($order) {
		if (!is_a($order, 'WC_Order')) {
			return;
		}

		$amount = 0.0;
		if (function_exists('WC') && WC()->session) {
			$amount = (float) WC()->session->get('foodord_delivery_fee_amount', 0.0);
		}

		if ($amount > 0) {
			$order->update_meta_data('delivery_fee', $amount);
			$order->update_meta_data('_delivery_fee', $amount);
			return;
		}

		$order->delete_meta_data('delivery_fee');
		$order->delete_meta_data('_delivery_fee');
	},
	40
);

add_filter(
	'woocommerce_store_api_checkout_update_order_from_request',
	function ($order, $request) {
		unset($request);
		if (!is_a($order, 'WC_Order')) {
			return $order;
		}

		$mode = function_exists('foodord_get_order_mode') ? foodord_get_order_mode() : 'delivery';

		$timezone = wp_timezone();
		$order_created = $order->get_date_created();
		$order_created_ts = $order_created ? $order_created->getTimestamp() : time();
		$order_created_day = wp_date('Y-m-d', $order_created_ts, $timezone);

		if ('pickup' === $mode) {
			$order->update_meta_data('_foodord_order_mode', 'pickup');
			$order->update_meta_data('foodord_order_mode', 'pickup');

			$pickup_time = '';
			if (function_exists('WC') && WC()->session) {
				$session_pickup = (string) WC()->session->get('foodord_pickup_time', '');
				if ($session_pickup) {
					$upper = strtoupper($session_pickup);
					if (preg_match('/^\d{2}:\d{2}$/', $session_pickup) || 'ASAP' === $upper) {
						$pickup_time = ('ASAP' === $upper) ? 'ASAP' : $session_pickup;
					}
				}
			}
			if ($pickup_time) {
				$order->update_meta_data('_foodord_pickup_time', $pickup_time);
				$order->update_meta_data('foodord_pickup_time', $pickup_time);
			}

			$pickup_date = '';
			if (function_exists('WC') && WC()->session) {
				$session_date = (string) WC()->session->get('foodord_pickup_date', '');
				$pickup_date = foodord_sanitize_scheduled_date_value($session_date, 'pickup');
			}
			if ($pickup_date && $pickup_date > $order_created_day) {
				$order->update_meta_data('_foodord_pickup_date', $pickup_date);
				$order->update_meta_data('foodord_pickup_date', $pickup_date);
			} else {
				$order->delete_meta_data('_foodord_pickup_date');
				$order->delete_meta_data('foodord_pickup_date');
			}

			$order->delete_meta_data('_foodord_delivery_time');
			$order->delete_meta_data('foodord_delivery_time');
			$order->delete_meta_data('_foodord_delivery_date');
			$order->delete_meta_data('foodord_delivery_date');
		} else {
			$order->update_meta_data('_foodord_order_mode', 'delivery');
			$order->update_meta_data('foodord_order_mode', 'delivery');
			$order->delete_meta_data('_foodord_pickup_time');
			$order->delete_meta_data('foodord_pickup_time');
			$order->delete_meta_data('_foodord_pickup_date');
			$order->delete_meta_data('foodord_pickup_date');
		}

		return $order;
	},
	20,
	2
);

// Store API (Blocks checkout): persist order mode after checkout processes via Store API.
add_action(
	'woocommerce_store_api_checkout_order_processed',
	function ($order) {
		if (!is_a($order, 'WC_Order')) {
			return;
		}
		$mode = 'delivery';
		$time = '';
		if (function_exists('WC') && WC()->session) {
			$session_mode = (string) WC()->session->get('foodord_order_mode', 'delivery');
			if (in_array($session_mode, array('delivery', 'pickup'), true)) {
				$mode = $session_mode;
			}
			$session_time = (string) WC()->session->get('foodord_delivery_time', '');
			if (is_string($session_time)) {
				$upper = strtoupper($session_time);
				if (preg_match('/^\d{2}:\d{2}$/', $session_time) || 'ASAP' === $upper) {
					$time = ('ASAP' === $upper) ? 'ASAP' : $session_time;
				}
			}
		}
		$order->update_meta_data('_foodord_order_mode', $mode);
		$order->update_meta_data('foodord_order_mode', $mode);

		$timezone = wp_timezone();
		$order_created = $order->get_date_created();
		$order_created_ts = $order_created ? $order_created->getTimestamp() : time();
		$order_created_day = wp_date('Y-m-d', $order_created_ts, $timezone);

		// Safety net: ensure shipping address is present for delivery orders.
		$billing_has_address = (bool) ($order->get_billing_address_1() || $order->get_billing_city() || $order->get_billing_postcode());
		$shipping_has_address = (bool) ($order->get_shipping_address_1() || $order->get_shipping_city() || $order->get_shipping_postcode());
		if ('delivery' === $mode && !$shipping_has_address && $billing_has_address) {
			$order->set_shipping_first_name($order->get_billing_first_name());
			$order->set_shipping_last_name($order->get_billing_last_name());
			$order->set_shipping_company($order->get_billing_company());
			$order->set_shipping_address_1($order->get_billing_address_1());
			$order->set_shipping_address_2($order->get_billing_address_2());
			$order->set_shipping_city($order->get_billing_city());
			$order->set_shipping_state($order->get_billing_state());
			$order->set_shipping_postcode($order->get_billing_postcode());
			$order->set_shipping_country($order->get_billing_country());
		}
		if ('delivery' === $mode && $time) {
			$order->update_meta_data('_foodord_delivery_time', $time);
			$order->update_meta_data('foodord_delivery_time', $time);
		}

		// Persist selected pickup time from session.
		$pickup_time = '';
		if (function_exists('WC') && WC()->session) {
			$session_pickup = (string) WC()->session->get('foodord_pickup_time', '');
			if (is_string($session_pickup)) {
				$upper = strtoupper($session_pickup);
				if (preg_match('/^\d{2}:\d{2}$/', $session_pickup) || 'ASAP' === $upper) {
					$pickup_time = ('ASAP' === $upper) ? 'ASAP' : $session_pickup;
				}
			}
		}
		if ('pickup' === $mode && $pickup_time) {
			$order->update_meta_data('_foodord_pickup_time', $pickup_time);
			$order->update_meta_data('foodord_pickup_time', $pickup_time);
		}

		// Persist scheduled dates (only when scheduled for a future day).
		$delivery_date = '';
		$pickup_date = '';
		if (function_exists('WC') && WC()->session) {
			$delivery_date = foodord_sanitize_scheduled_date_value((string) WC()->session->get('foodord_delivery_date', ''), 'delivery');
			$pickup_date = foodord_sanitize_scheduled_date_value((string) WC()->session->get('foodord_pickup_date', ''), 'pickup');
		}

		if ('delivery' === $mode) {
			if ($delivery_date && $delivery_date > $order_created_day) {
				$order->update_meta_data('_foodord_delivery_date', $delivery_date);
				$order->update_meta_data('foodord_delivery_date', $delivery_date);
			} else {
				$order->delete_meta_data('_foodord_delivery_date');
				$order->delete_meta_data('foodord_delivery_date');
			}

			$order->delete_meta_data('_foodord_pickup_time');
			$order->delete_meta_data('foodord_pickup_time');
			$order->delete_meta_data('_foodord_pickup_date');
			$order->delete_meta_data('foodord_pickup_date');
		} else {
			if ($pickup_date && $pickup_date > $order_created_day) {
				$order->update_meta_data('_foodord_pickup_date', $pickup_date);
				$order->update_meta_data('foodord_pickup_date', $pickup_date);
			} else {
				$order->delete_meta_data('_foodord_pickup_date');
				$order->delete_meta_data('foodord_pickup_date');
			}

			$order->delete_meta_data('_foodord_delivery_time');
			$order->delete_meta_data('foodord_delivery_time');
			$order->delete_meta_data('_foodord_delivery_date');
			$order->delete_meta_data('foodord_delivery_date');
		}

		$order->save();
		// Clear session copy to avoid stale reuse.
		if (function_exists('WC') && WC()->session) {
			WC()->session->__unset('foodord_delivery_time');
			WC()->session->__unset('foodord_pickup_time');
			WC()->session->__unset('foodord_delivery_date');
			WC()->session->__unset('foodord_pickup_date');
		}

		foodord_reset_order_mode_cache();
	},
	20
);

add_action(
	'woocommerce_thankyou',
	function ($order_id) {
		unset($order_id);
		foodord_reset_order_mode_cache();
	},
	5
);

add_action(
	'woocommerce_thankyou',
	function ($order_id) {
		$order = wc_get_order($order_id);
		if (!$order) {
			return;
		}

		$order_key = $order->get_order_key();
		if (!$order_key) {
			return;
		}

		$ajax_url = admin_url('admin-ajax.php');
		$nonce = wp_create_nonce('foodord_confirm_status_' . $order_key);
		$interval = apply_filters('foodord_confirm_status_interval', 15000);
		$messages = array(
			'pending' => esc_html__('Pending confirmation…', 'foodord'),
			/* translators: %s: confirmation time or status */
			'confirmed' => esc_html__('Restaurant confirmation: %s', 'foodord'),
		);
		$payload = array(
			'ajaxUrl' => $ajax_url,
			'orderKey' => $order_key,
			'nonce' => $nonce,
			'interval' => max(2000, absint($interval)),
			'messages' => $messages,
		);

		$handle = 'foodord-confirm-status-inline';
		$ver = FOODORD_VERSION;
		$script_path = plugins_url('public/js/foodord-confirm-status.js', __FILE__);
		wp_register_script($handle, $script_path, array(), $ver, true);
		wp_add_inline_script($handle, 'window.foodordConfirmStatus = ' . wp_json_encode($payload) . ';', 'before');
		wp_enqueue_script($handle);
	},
	20
);

// Safety net: ensure order meta is set even if previous hook was bypassed.
add_action(
	'woocommerce_checkout_update_order_meta',
	function ($order_id) {
		$order = wc_get_order($order_id);
		if (!$order) {
			return;
		}
		$existing = (string) $order->get_meta('_foodord_order_mode', true);
		if (in_array($existing, array('delivery', 'pickup'), true)) {
			return; // already set correctly.
		}
		$mode = 'delivery';
		if (function_exists('WC') && WC()->session) {
			$session_mode = (string) WC()->session->get('foodord_order_mode', 'delivery');
			if (in_array($session_mode, array('delivery', 'pickup'), true)) {
				$mode = $session_mode;
			}
		}
		$order->update_meta_data('_foodord_order_mode', $mode);
		$order->update_meta_data('foodord_order_mode', $mode); // mirror for template consumption.
	
		$timezone = wp_timezone();
		$order_created = $order->get_date_created();
		$order_created_ts = $order_created ? $order_created->getTimestamp() : time();
		$order_created_day = wp_date('Y-m-d', $order_created_ts, $timezone);

		if (function_exists('WC') && WC()->session) {
			$delivery_time = '';
			$pickup_time = '';

			$session_delivery = (string) WC()->session->get('foodord_delivery_time', '');
			$upper = strtoupper($session_delivery);
			if (preg_match('/^\d{2}:\d{2}$/', $session_delivery) || 'ASAP' === $upper) {
				$delivery_time = ('ASAP' === $upper) ? 'ASAP' : $session_delivery;
			}

			$session_pickup = (string) WC()->session->get('foodord_pickup_time', '');
			$upper = strtoupper($session_pickup);
			if (preg_match('/^\d{2}:\d{2}$/', $session_pickup) || 'ASAP' === $upper) {
				$pickup_time = ('ASAP' === $upper) ? 'ASAP' : $session_pickup;
			}

			$delivery_date = foodord_sanitize_scheduled_date_value((string) WC()->session->get('foodord_delivery_date', ''), 'delivery');
			$pickup_date = foodord_sanitize_scheduled_date_value((string) WC()->session->get('foodord_pickup_date', ''), 'pickup');

			if ('pickup' === $mode) {
				if ($pickup_time) {
					$order->update_meta_data('_foodord_pickup_time', $pickup_time);
					$order->update_meta_data('foodord_pickup_time', $pickup_time);
				}
				if ($pickup_date && $pickup_date > $order_created_day) {
					$order->update_meta_data('_foodord_pickup_date', $pickup_date);
					$order->update_meta_data('foodord_pickup_date', $pickup_date);
				}

				$order->delete_meta_data('_foodord_delivery_time');
				$order->delete_meta_data('foodord_delivery_time');
				$order->delete_meta_data('_foodord_delivery_date');
				$order->delete_meta_data('foodord_delivery_date');
			} else {
				if ($delivery_time) {
					$order->update_meta_data('_foodord_delivery_time', $delivery_time);
					$order->update_meta_data('foodord_delivery_time', $delivery_time);
				}
				if ($delivery_date && $delivery_date > $order_created_day) {
					$order->update_meta_data('_foodord_delivery_date', $delivery_date);
					$order->update_meta_data('foodord_delivery_date', $delivery_date);
				}

				$order->delete_meta_data('_foodord_pickup_time');
				$order->delete_meta_data('foodord_pickup_time');
				$order->delete_meta_data('_foodord_pickup_date');
				$order->delete_meta_data('foodord_pickup_date');
			}
		}

		$order->save();
	},
	20
);

// Add hidden checkout field to persist order mode reliably via POST.
add_filter(
	'woocommerce_checkout_fields',
	function ($fields) {
		$mode = 'delivery';
		if (function_exists('WC') && WC()->session) {
			$session_mode = (string) WC()->session->get('foodord_order_mode', 'delivery');
			if (in_array($session_mode, array('delivery', 'pickup'), true)) {
				$mode = $session_mode;
			}
		}

		$fields['billing']['foodord_order_mode'] = array(
			'type' => 'hidden',
			'label' => '',
			'required' => false,
			'default' => $mode,
			'priority' => 1,
			'class' => array(),
			'input_class' => array(),
			'custom_attributes' => array(),
		);

		return $fields;
	}
);

add_action(
	'wp',
	function () {
		if (!function_exists('is_order_received_page') || !is_order_received_page()) {
			return;
		}

		add_action(
			'wp_enqueue_scripts',
			function () {
				$ver = FOODORD_VERSION;
				$script_path = plugins_url('public/js/foodord-order-mode-reset.js', __FILE__);
				wp_register_script('foodord-inline-reset', $script_path, array(), $ver, true);
				wp_enqueue_script('foodord-inline-reset');
			},
			5
		);
	}
);

// As a safety net, hide formatted addresses on thank you / view-order for pickup.
add_filter(
	'woocommerce_order_formatted_billing_address',
	function ($address, $order) {
		if (!is_a($order, 'WC_Order')) {
			return $address;
		}
		$mode = (string) $order->get_meta('_foodord_order_mode', true);
		if ('delivery' === $mode) {
			return $address;
		}
		if (function_exists('is_order_received_page') && is_order_received_page()) {
			return array();
		}
		if (function_exists('is_account_page') && is_account_page() && function_exists('is_wc_endpoint_url') && is_wc_endpoint_url('view-order')) {
			return array();
		}
		return $address;
	},
	10,
	2
);
if (!function_exists('foodord_get_order_created_day')) {
	/**
	 * Get order created day in site timezone (YYYY-MM-DD).
	 *
	 * @param WC_Order|mixed $order Order instance.
	 * @return string
	 */
	function foodord_get_order_created_day($order): string
	{
		$timezone = wp_timezone();
		$ts = time();

		if ($order && is_a($order, 'WC_Order')) {
			$created = $order->get_date_created();
			if ($created && is_object($created) && method_exists($created, 'getTimestamp')) {
				$ts = (int) $created->getTimestamp();
			}
		}

		return wp_date('Y-m-d', $ts, $timezone);
	}
}

if (!function_exists('foodord_get_future_scheduled_date_for_order')) {
	/**
	 * Get scheduled date meta for an order, only when it is a future day.
	 *
	 * @param WC_Order|mixed $order Order instance.
	 * @param string         $mode Mode slug ('delivery'|'pickup').
	 * @return string
	 */
	function foodord_get_future_scheduled_date_for_order($order, string $mode): string
	{
		if (!$order || !is_a($order, 'WC_Order')) {
			return '';
		}

		$mode = ('pickup' === $mode) ? 'pickup' : 'delivery';
		$key = ('pickup' === $mode) ? 'foodord_pickup_date' : 'foodord_delivery_date';

		$date = (string) $order->get_meta($key, true);
		$date = sanitize_text_field($date);
		if ('' === $date) {
			return '';
		}
		if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
			return '';
		}

		$order_day = foodord_get_order_created_day($order);
		if ('' === $order_day || $date <= $order_day) {
			return '';
		}

		return $date;
	}
}

if (!function_exists('foodord_format_scheduled_date_display')) {
	/**
	 * Format scheduled date (YYYY-MM-DD) for display.
	 *
	 * @param string $date Scheduled date.
	 * @return string
	 */
	function foodord_format_scheduled_date_display(string $date): string
	{
		$date = sanitize_text_field($date);
		if ('' === $date) {
			return '';
		}
		if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
			return '';
		}

		$timezone = wp_timezone();
		try {
			$dt = new DateTimeImmutable($date . ' 00:00:00', $timezone);
		} catch (Exception $e) {
			unset($e);
			return '';
		}

		$format = function_exists('wc_date_format') ? wc_date_format() : (string) get_option('date_format');
		return wp_date($format, $dt->getTimestamp(), $timezone);
	}
}

// Display delivery/pickup time in order totals (thank you page, emails, view order).
add_filter(
	'woocommerce_get_order_item_totals',
	function ($totals, $order) {
		if (!is_a($order, 'WC_Order')) {
			return $totals;
		}

		// Check order mode first.
		$mode = (string) $order->get_meta('_foodord_order_mode', true);
		if (!$mode) {
			$mode = (string) $order->get_meta('foodord_order_mode', true);
		}

		$time = '';
		$label = '';
		$date = '';
		$display = '';

		if ('pickup' === $mode) {
			$time = (string) $order->get_meta('foodord_pickup_time', true);
			$date = foodord_get_future_scheduled_date_for_order($order, 'pickup');
			$label = esc_html__('Pickup time:', 'foodord');
		} else {
			$time = (string) $order->get_meta('foodord_delivery_time', true);
			$date = foodord_get_future_scheduled_date_for_order($order, 'delivery');
			$label = esc_html__('Delivery time:', 'foodord');
		}

		$time_display = '';
		if ($time) {
			if (preg_match('/^\d{2}:\d{2}$/', $time)) {
				$time_display = $time;
			} elseif ('ASAP' === strtoupper($time)) {
				$time_display = esc_html__('As soon as possible', 'foodord');
			}
		}

		$date_display = $date ? foodord_format_scheduled_date_display($date) : '';
		if ($date_display && $time_display) {
			$display = $date_display . ' ' . $time_display;
		} elseif ($date_display) {
			$display = $date_display;
		} else {
			$display = $time_display;
		}

		if ($display) {
			$injected = array(
				'delivery_pickup_time' => array(
					'label' => $label,
					'value' => esc_html($display),
				),
			);
			$new_totals = array();
			$added = false;
			foreach ((array) $totals as $key => $row) {
				if ('payment_method' === $key && !$added) {
					$new_totals = $new_totals + $injected;
					$added = true;
				}
				$new_totals[$key] = $row;
			}
			if (!$added) {
				$new_totals = $new_totals + $injected;
			}
			$totals = $new_totals;
		}
		return $totals;
	},
	10,
	2
);

// Admin order details: show delivery/pickup time under billing address.
add_action(
	'woocommerce_admin_order_data_after_billing_address',
	function ($order) {
		if (!is_a($order, 'WC_Order')) {
			return;
		}

		// Check order mode.
		$mode = (string) $order->get_meta('_foodord_order_mode', true);
		if (!$mode) {
			$mode = (string) $order->get_meta('foodord_order_mode', true);
		}

		$time = '';
		$label = '';
		$date = '';

		if ('pickup' === $mode) {
			$time = (string) $order->get_meta('foodord_pickup_time', true);
			$date = foodord_get_future_scheduled_date_for_order($order, 'pickup');
			$label = esc_html__('Pickup time:', 'foodord');
		} else {
			$time = (string) $order->get_meta('foodord_delivery_time', true);
			$date = foodord_get_future_scheduled_date_for_order($order, 'delivery');
			$label = esc_html__('Delivery time:', 'foodord');
		}

		$time_display = '';
		if ($time) {
			if (preg_match('/^\d{2}:\d{2}$/', $time)) {
				$time_display = $time;
			} elseif ('ASAP' === strtoupper($time)) {
				$time_display = esc_html__('As soon as possible', 'foodord');
			}
		}

		$date_display = $date ? foodord_format_scheduled_date_display($date) : '';
		$display = '';
		if ($date_display && $time_display) {
			$display = $date_display . ' ' . $time_display;
		} elseif ($date_display) {
			$display = $date_display;
		} else {
			$display = $time_display;
		}

		if ($display) {
			echo '<p class="foodord-time"><strong>' . esc_html($label) . '</strong> ' . esc_html($display) . '</p>';
		}
	},
	10
);

add_filter(
	'woocommerce_order_formatted_shipping_address',
	function ($address, $order) {
		if (!is_a($order, 'WC_Order')) {
			return $address;
		}
		$mode = (string) $order->get_meta('_foodord_order_mode', true);
		if ('delivery' === $mode) {
			return $address;
		}
		if (function_exists('is_order_received_page') && is_order_received_page()) {
			return array();
		}
		if (function_exists('is_account_page') && is_account_page() && function_exists('is_wc_endpoint_url') && is_wc_endpoint_url('view-order')) {
			return array();
		}
		return $address;
	},
	10,
	2
);
// AJAX (nopriv): persist selected delivery time in WooCommerce session.
add_action(
	'wp_ajax_nopriv_foodord_set_delivery_time',
	function () {
		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
		if (!wp_verify_nonce($nonce, 'foodord_delivery_time')) {
			wp_send_json_error(array('message' => 'Invalid nonce'), 403);
		}
		$time = isset($_POST['time']) ? sanitize_text_field(wp_unslash($_POST['time'])) : '';
		$upper = strtoupper((string) $time);
		if (!is_string($time) || (!preg_match('/^\d{2}:\d{2}$/', $time) && 'ASAP' !== $upper)) {
			$time = '';
		} else {
			$time = ('ASAP' === $upper) ? 'ASAP' : $time;
		}
		if (function_exists('WC') && WC()->session) {
			WC()->session->set('foodord_delivery_time', $time);
		}
		wp_send_json_success(array('time' => $time));
	}
);

if (!function_exists('foodord_handle_confirm_status')) {
	/**
	 * Handle AJAX request for order confirmation status.
	 *
	 * @return void
	 */
	function foodord_handle_confirm_status()
	{
		$order_key = isset($_POST['order_key']) ? sanitize_text_field(wp_unslash($_POST['order_key'])) : ''; // wp_verify_nonce verified below.
		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : ''; // wp_verify_nonce verified below.

		if ('' === $order_key || '' === $nonce) {
			wp_send_json_error(array('message' => 'invalid_request'), 400);
		}

		if (!wp_verify_nonce($nonce, 'foodord_confirm_status_' . $order_key)) {
			wp_send_json_error(array('message' => 'invalid_nonce'), 403);
		}

		$order_id = wc_get_order_id_by_order_key($order_key);
		if (!$order_id) {
			wp_send_json_error(array('message' => 'order_not_found'), 404);
		}

		$order = wc_get_order($order_id);
		if (!$order) {
			wp_send_json_error(array('message' => 'order_not_found'), 404);
		}

		$confirmation = Foodord_Rest_Api::build_order_confirmation_payload($order);
		$progress = Foodord_Rest_Api::build_order_stage_payload($order);

		if (empty($confirmation['confirmed'])) {
			wp_send_json_success(
				array(
					'status' => 'pending',
					'progress' => $progress,
				)
			);
		}

		wp_send_json_success(
			array(
				'status' => 'confirmed',
				'confirmed_at' => $confirmation['confirmed_at'],
				'confirmed_at_local' => $confirmation['confirmed_at_local'],
				'confirmed_slot' => $confirmation['confirmed_slot'],
				'confirmed_slot_local' => $confirmation['confirmed_slot_local'],
				'confirmed_minutes' => $confirmation['confirmed_minutes'],
				'confirmed_display' => $confirmation['confirmed_display'],
				'type' => $confirmation['type'],
				'progress' => $progress,
			)
		);
	}
}

add_action('wp_ajax_foodord_confirm_status', 'foodord_handle_confirm_status');
add_action('wp_ajax_nopriv_foodord_confirm_status', 'foodord_handle_confirm_status');

// Hide cart images when Tweaks setting is disabled.
add_action(
	'init',
	function () {
		$show_images = get_option('foodord_show_product_card_images', 'yes');
		if ('no' === $show_images) {
			// Filter for classic cart/mini-cart.
			add_filter('woocommerce_cart_item_thumbnail', '__return_empty_string', 999);
		}
	}
);

// Conditionally add a body class to hide cart images via foodord-card.css rules.
add_filter(
	'body_class',
	function ($classes) {
		if (!is_admin() && get_option('foodord_show_product_card_images', 'yes') === 'no') {
			$classes[] = 'foodord-hide-cart-images';
		}
		return $classes;
	}
);

// Toggle topping group labels visibility globally for frontend templates.
add_filter(
	'body_class',
	function ($classes) {
		if (is_admin()) {
			return $classes;
		}
		if ('no' === get_option('foodord_show_topping_group_label', 'yes')) {
			$classes[] = 'foodord-hide-topping-labels';
		}
		return $classes;
	}
);

add_action(
	'wp_enqueue_scripts',
	static function () {
		if (is_admin()) {
			return;
		}
		if ('no' !== get_option('foodord_show_topping_group_label', 'yes')) {
			return;
		}
		if (!function_exists('is_cart') || !function_exists('is_checkout')) {
			return;
		}
		if (!is_cart() && !is_checkout()) {
			return;
		}
		wp_enqueue_script(
			'foodord-topping-labels',
			FOODORD_URL . 'public/js/foodord-topping-labels.js',
			array(),
			FOODORD_VERSION,
			true
		);
	}
);

// On first frontend load, if only one mode is within regular working hours,
// set it as the default order mode in WooCommerce session (if not set yet).
add_action(
	'init',
	function () {
		if (is_admin()) {
			return;
		}
		if (!class_exists('Foodord_Business_Hours')) {
			return;
		}
		if (!function_exists('WC') || !WC()->session) {
			return;
		}

		$existing = WC()->session->get('foodord_order_mode', null);
		if (is_string($existing) && in_array($existing, array('delivery', 'pickup'), true)) {
			return; // respect existing session selection.
		}

		$status = Foodord_Business_Hours::get_status_payload();
		$delivery_open = isset($status['modes']['delivery']['regular_open']) ? (bool) $status['modes']['delivery']['regular_open'] : false;
		$pickup_open = isset($status['modes']['pickup']['regular_open']) ? (bool) $status['modes']['pickup']['regular_open'] : false;

		if ($delivery_open && !$pickup_open) {
			WC()->session->set('foodord_order_mode', 'delivery');
		} elseif ($pickup_open && !$delivery_open) {
			WC()->session->set('foodord_order_mode', 'pickup');
		}
	},
	9
);

/**
 * Override WooCommerce placeholder image to use the same SVG as product cards.
 * This ensures cart (shortcode) and WooCommerce Blocks use the identical
 * placeholder when a product image is missing.
 */
/**
 * Filter placeholder image URL to use theme-consistent SVG.
 *
 * @param string $src Original placeholder image URL.
 * @return string New placeholder image URL.
 */
function foodord_placeholder_img_src($src)
{
	if (is_admin() && !(function_exists('wp_doing_ajax') && wp_doing_ajax())) {
		return $src;
	}

	return FOODORD_URL . 'public/images/no-picture.svg';
}
add_filter('woocommerce_placeholder_img_src', 'foodord_placeholder_img_src');
