<?php
/**
 * AJAX Handlers — receive locker selection from JS popup, store in WC Session.
 *
 * Data flow: JS popup → AJAX POST → here → WC Session → order-save.php → Order Meta
 *
 * @package ParcelSelector
 */

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

// Hook registration
add_action( 'wp_ajax_parcselect_save_selection',        'parcselect_ajax_save_selection' );
add_action( 'wp_ajax_nopriv_parcselect_save_selection', 'parcselect_ajax_save_selection' );

add_action( 'wp_ajax_parcselect_clear_selection',        'parcselect_ajax_clear_selection' );
add_action( 'wp_ajax_nopriv_parcselect_clear_selection', 'parcselect_ajax_clear_selection' );

// Nonce refresh — JS calls this when nonce expires (HTTP 403 on ps_save_selection)
add_action( 'wp_ajax_parcselect_refresh_nonce',        'parcselect_ajax_refresh_nonce' );
add_action( 'wp_ajax_nopriv_parcselect_refresh_nonce', 'parcselect_ajax_refresh_nonce' );
// Dismiss activation notice (re-shows every 14 days)
add_action( 'wp_ajax_parcselect_dismiss_activation_notice', 'parcselect_ajax_dismiss_activation_notice' );
if ( ! function_exists( 'parcselect_ajax_dismiss_activation_notice' ) ) {
function parcselect_ajax_dismiss_activation_notice() {
	check_ajax_referer( 'parcselect_dismiss_notice', 'nonce' );
	if ( current_user_can( 'manage_options' ) ) {
		update_option( 'parcselect_activation_notice_dismissed', time() );
	}
	wp_send_json_success();
}
}


if ( ! function_exists( 'parcselect_ajax_refresh_nonce' ) ) {
function parcselect_ajax_refresh_nonce() {
	// No nonce check needed — this endpoint CREATES a new nonce.
	// Gate: WC session must exist (prevents unauthenticated harvesting).
	if ( ! function_exists( 'WC' ) || ! WC()->session ) {
		wp_send_json_error( array( 'message' => 'Session unavailable' ), 503 );
	}
	// Rate limit: max 10 refreshes per session per 5 minutes.
	$sid  = WC()->session->get_customer_id();
	$key  = 'parcselect_nonce_rl_' . md5( $sid );
	$cnt  = (int) get_transient( $key );
	if ( $cnt >= 10 ) {
		wp_send_json_error( array( 'message' => 'Rate limited' ), 429 );
	}
	set_transient( $key, $cnt + 1, 5 * MINUTE_IN_SECONDS );
	wp_send_json_success( array(
		'nonce' => wp_create_nonce( 'parcselect_ajax_nonce' ),
	) );
}
}

/**
 * AJAX handler — save locker selection to WC session.
 *
 * Expected POST: nonce, locker_name, locker_address, locker_city, locker_post_code, locker_country.
 */
if ( ! function_exists( 'parcselect_ajax_save_selection' ) ) {
function parcselect_ajax_save_selection() {
	// Nonce check
	if ( ! check_ajax_referer( 'parcselect_ajax_nonce', 'nonce', false ) ) {
		wp_send_json_error( array( 'message' => __( 'Security check failed. Please refresh the page.', 'parcel-selector' ) ), 403 );
	}

	// WooCommerce availability
	if ( ! function_exists( 'WC' ) || ! WC()->session ) {
		wp_send_json_error( array( 'message' => __( 'WooCommerce session not available.', 'parcel-selector' ) ), 503 );
	}

	// Sanitize inputs
	$name      = sanitize_text_field( isset( $_POST['locker_name'] )      ? wp_unslash( $_POST['locker_name'] )      : '' );
	$address   = sanitize_text_field( isset( $_POST['locker_address'] )   ? wp_unslash( $_POST['locker_address'] )   : '' );
	$city      = sanitize_text_field( isset( $_POST['locker_city'] )      ? wp_unslash( $_POST['locker_city'] )      : '' );
	$post_code = sanitize_text_field( isset( $_POST['locker_post_code'] ) ? wp_unslash( $_POST['locker_post_code'] ) : '' );
	$country          = sanitize_key( isset( $_POST['locker_country'] )    ? wp_unslash( $_POST['locker_country'] )   : 'pl' );
	$is_custom_pickup = ! empty( $_POST['is_custom_pickup'] ) && in_array( sanitize_key( wp_unslash( $_POST['is_custom_pickup'] ) ), array( '1', 'true', 'yes', 'on' ), true );
	$selection_time   = isset( $_POST['selection_time'] ) ? absint( $_POST['selection_time'] ) : 0;
	$total_time       = isset( $_POST['total_time'] ) ? absint( $_POST['total_time'] ) : 0;
	$device_type      = sanitize_text_field( isset( $_POST['device_type'] ) ? wp_unslash( $_POST['device_type'] ) : '' );
	$carrier          = sanitize_key( isset( $_POST['locker_carrier'] ) ? wp_unslash( $_POST['locker_carrier'] ) : '' );

	// Customer data (optional — sent by classic/INTRO_1 map)
	$cust_fn = sanitize_text_field( isset( $_POST['customer_first_name'] ) ? wp_unslash( $_POST['customer_first_name'] ) : '' );
	$cust_ln = sanitize_text_field( isset( $_POST['customer_last_name'] )  ? wp_unslash( $_POST['customer_last_name'] )  : '' );
	$cust_em = sanitize_email(       isset( $_POST['customer_email'] )      ? wp_unslash( $_POST['customer_email'] )      : '' );
	$cust_ph = sanitize_text_field( isset( $_POST['customer_phone'] )      ? wp_unslash( $_POST['customer_phone'] )      : '' );

	if ( empty( $name ) ) {
		wp_send_json_error( array( 'message' => __( 'Locker name is required.', 'parcel-selector' ) ), 400 );
	}

	// Auto-generate country_name
	$map          = parcselect_get_country_names_map();
	$country_name = isset( $map[ strtolower( $country ) ] ) ? $map[ strtolower( $country ) ] : strtoupper( $country );

	// Store in WC session
	WC()->session->set( 'parcselect_locker_name',      $name );
	WC()->session->set( 'parcselect_locker_address',   $address );
	WC()->session->set( 'parcselect_locker_city',      $city );
	WC()->session->set( 'parcselect_locker_post_code', $post_code );
	WC()->session->set( 'parcselect_locker_country',   strtolower( $country ) );
	WC()->session->set( 'parcselect_locker_country_name', $country_name );
	WC()->session->set( 'parcselect_is_custom_pickup',    $is_custom_pickup ? '1' : '0' );
	WC()->session->set( 'parcselect_selection_time',      $selection_time );
	WC()->session->set( 'parcselect_total_time',          $total_time );
	WC()->session->set( 'parcselect_device_type',         $device_type );
	WC()->session->set( 'parcselect_carrier',             $carrier );

	if ( ! empty( $cust_fn ) ) {
		WC()->session->set( 'parcselect_cust_first_name', $cust_fn );
		WC()->session->set( 'parcselect_cust_last_name',  $cust_ln );
		WC()->session->set( 'parcselect_cust_email',      $cust_em );
		WC()->session->set( 'parcselect_cust_phone',      $cust_ph );
	}

	parcselect_log( 'Locker saved: ' . $name . ', ' . $city . ', ' . $country );

	/**
	 * Fires after a parcel locker is selected and saved to WC session.
	 *
	 * @param string $name         Locker ID (e.g. "WAW01A").
	 * @param string $city         Locker city.
	 * @param string $country      Locker country code (lowercase, e.g. "pl").
	 * @param string $country_name Full country name (e.g. "Polska (Poland)").
	 * @param bool   $is_custom    True if this is a custom pickup point.
	 */
	do_action( 'parcselect_locker_selected', $name, $city, $country, $country_name, $is_custom_pickup );

	wp_send_json_success( array(
		'message' => 'Locker saved.',
		'locker'  => $name,
		'city'    => $city,
		'country' => $country_name,
	) );
}
}

/**
 * AJAX handler — clear locker selection from WC session.
 */
if ( ! function_exists( 'parcselect_ajax_clear_selection' ) ) {
function parcselect_ajax_clear_selection() {
	check_ajax_referer( 'parcselect_ajax_nonce', 'nonce' );

	if ( ! function_exists( 'WC' ) || ! WC()->session ) {
		wp_send_json_error( array( 'message' => __( 'WooCommerce session not available.', 'parcel-selector' ) ), 503 );
	}

	parcselect_clear_locker_session();
	wp_send_json_success( array( 'message' => 'Selection cleared.' ) );
}
}

/**
 * Clear all locker data from WC session.
 * Shared by AJAX handler and PHP shipping-change hook.
 */
if ( ! function_exists( 'parcselect_clear_locker_session' ) ) {
function parcselect_clear_locker_session() {
	if ( ! function_exists( 'WC' ) || ! WC()->session ) return;
	$keys = array(
		'parcselect_locker_name', 'parcselect_locker_address', 'parcselect_locker_city',
		'parcselect_locker_post_code', 'parcselect_locker_country', 'parcselect_locker_country_name',
		'parcselect_carrier', // Must clear carrier to prevent a stale value on re-selection.
		'parcselect_is_custom_pickup', 'parcselect_device_type', 'parcselect_selection_time', 'parcselect_total_time',
		'parcselect_cust_first_name', 'parcselect_cust_last_name', 'parcselect_cust_email', 'parcselect_cust_phone',
	);
	foreach ( $keys as $key ) {
		WC()->session->set( $key, null );
	}
}
}

/**
 * PHP-side: when customer changes shipping method to non-InPost,
 * clear the locker session to prevent stale data reaching the order.
 *
 * Fires on: woocommerce_checkout_update_order_review (AJAX refresh)
 */
add_action( 'woocommerce_checkout_update_order_review', 'parcselect_maybe_clear_on_method_change' );
if ( ! function_exists( 'parcselect_maybe_clear_on_method_change' ) ) {
function parcselect_maybe_clear_on_method_change( $posted_data ) {
	if ( ! function_exists( 'WC' ) || ! WC()->session ) return;

	// Parse posted shipping method
	$shipping_method = '';
	if ( ! empty( $posted_data ) ) {
		parse_str( $posted_data, $parsed );
		if ( isset( $parsed['shipping_method'] ) ) {
			$methods = (array) $parsed['shipping_method'];
			$shipping_method = reset( $methods );
		}
	}

	// If we have a method and it's NOT InPost, clear locker session
	if ( ! empty( $shipping_method ) && false === strpos( $shipping_method, 'parcselect_inpost_paczkomat' ) ) {
		$has_locker = WC()->session->get( 'parcselect_locker_name', '' );
		if ( ! empty( $has_locker ) ) {
			parcselect_clear_locker_session();
			parcselect_log( 'Session cleared: shipping method changed to ' . $shipping_method );
		}
	}
}
}

/**
 * Validate locker selection at checkout.
 * Hooked to: woocommerce_checkout_process
 */
add_action( 'woocommerce_checkout_process', 'parcselect_validate_locker_selection' );

if ( ! function_exists( 'parcselect_validate_locker_selection' ) ) {
function parcselect_validate_locker_selection() {
	if ( ! function_exists( 'WC' ) || ! WC()->session ) {
		return;
	}

	// Check if our shipping method is selected
	$chosen = WC()->session->get( 'chosen_shipping_methods' );
	if ( ! is_array( $chosen ) ) {
		return;
	}

	$uses_ps = false;
	foreach ( $chosen as $method ) {
		if ( false !== strpos( $method, 'parcselect_inpost_paczkomat' ) ) {
			$uses_ps = true;
			break;
		}
	}

	if ( ! $uses_ps ) {
		return;
	}

	$locker     = WC()->session->get( 'parcselect_locker_name' );
	$_pickup    = get_option( 'parcselect_custom_pickup', array() );
	$has_pickup = ! empty( $_pickup['enabled'] ) && 'yes' === $_pickup['enabled'] && ! empty( $_pickup['lat'] );

	if ( empty( $locker ) ) {
		$msg = $has_pickup
			? __( 'Please select a parcel locker or pickup point on the map to continue.', 'parcel-selector' )
			: __( 'Please select a parcel locker on the map to continue.', 'parcel-selector' );

		// wc_add_notice() is only available on frontend requests — guard against REST/AJAX calls
		if ( function_exists( 'wc_add_notice' ) ) {
			wc_add_notice( $msg, 'error' );
		}
	}
}
}
