<?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
if ( ! defined( 'DROP_PRINT_LIVE_POSTAGE_HTTP_TIMEOUT_SECONDS' ) ) {
	define( 'DROP_PRINT_LIVE_POSTAGE_HTTP_TIMEOUT_SECONDS', 8 );
}
if ( ! defined( 'DROP_PRINT_LIVE_POSTAGE_WARM_TIMEOUT_SECONDS' ) ) {
	define( 'DROP_PRINT_LIVE_POSTAGE_WARM_TIMEOUT_SECONDS', 45 );
}
if ( ! function_exists( 'drop_print_cart_item_is_drop_print_item' ) ) {
	function drop_print_cart_item_is_drop_print_item( array $cart_item ): bool {
		if ( empty( $cart_item['data'] ) || ! is_object( $cart_item['data'] ) ) {
			return false;
		}
		$product   = $cart_item['data'];
		$parent_id = $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id();
		$dp_meta = get_post_meta( $parent_id, '_drop_print_meta', true );
		return is_array( $dp_meta ) && ! empty( $dp_meta['file'] );
	}
}
if ( ! function_exists( 'drop_print_live_postage_resolve_api_credentials' ) ) {
	function drop_print_live_postage_resolve_api_credentials() {
		if ( ! function_exists( 'drop_print_get_responsible_user_for_auto_production' ) || ! function_exists( 'drop_print_get_user_settings' ) ) {
			return null;
		}
		$user_id = drop_print_get_responsible_user_for_auto_production();
		if ( $user_id <= 0 ) {
			return null;
		}
		$settings = drop_print_get_user_settings( $user_id );
		$api_base = defined( 'DROP_PRINT_API_URI' ) ? DROP_PRINT_API_URI : '';
		$user_b64 = $settings['auth_username_b64'] ?? '';
		$pass_b64 = $settings['auth_password_b64'] ?? '';
		if ( empty( $api_base ) || empty( $user_b64 ) || empty( $pass_b64 ) ) {
			return null;
		}
		$api_username = base64_decode( $user_b64 );
		$api_password = base64_decode( $pass_b64 );
		if ( false === $api_username || false === $api_password ) {
			return null;
		}
		return array(
			'api_base'                => $api_base,
			'auth_header'             => 'Basic ' . base64_encode( $api_username . ':' . $api_password ),
			'default_shipping_method' => ! empty( $settings['default_shipping_method'] ) ? sanitize_key( (string) $settings['default_shipping_method'] ) : 'standard',
		);
	}
}
if ( ! function_exists( 'drop_print_live_postage_fetch_rate' ) ) {
	function drop_print_live_postage_fetch_rate( array $items, string $destination_country, string $currency, array $request_overrides = array() ) {
		$credentials = drop_print_live_postage_resolve_api_credentials();
		if ( null === $credentials ) {
			return new WP_Error( 'dp_live_postage_not_connected', __( 'Drop Print is not connected.', 'drop-print' ) );
		}
		$url  = trailingslashit( $credentials['api_base'] ) . 'shipping-rate';
		$body = wp_json_encode( array_merge(
			array(
				'items'       => $items,
				'destination' => array( 'country' => $destination_country ),
				'currency'    => $currency,
				'mode'        => 'live_multi_tier',
				'tier'        => $credentials['default_shipping_method'],
			),
			$request_overrides
		) );
		$response = wp_remote_post( $url, array(
			'method'  => 'POST',
			'headers' => array(
				'Authorization' => $credentials['auth_header'],
				'Content-Type'  => 'application/json; charset=utf-8',
				'Accept'        => 'application/json',
			),
			'body'    => $body,
			'timeout' => ! empty( $request_overrides['resolve_all'] )
				? (int) apply_filters( 'drop_print_live_postage_warm_http_timeout', DROP_PRINT_LIVE_POSTAGE_WARM_TIMEOUT_SECONDS )
				: (int) apply_filters( 'drop_print_live_postage_http_timeout', DROP_PRINT_LIVE_POSTAGE_HTTP_TIMEOUT_SECONDS ),
		) );
		if ( is_wp_error( $response ) ) {
			return $response;
		}
		$status_code = wp_remote_retrieve_response_code( $response );
		$decoded     = json_decode( wp_remote_retrieve_body( $response ), true );
		if ( 200 !== $status_code || ! is_array( $decoded ) || empty( $decoded['success'] ) || ! isset( $decoded['data'] ) ) {
			$reason = is_array( $decoded ) && isset( $decoded['message'] ) ? (string) $decoded['message'] : ( 'HTTP ' . $status_code );
			return new WP_Error( 'dp_live_postage_bad_response', $reason );
		}
		return $decoded['data'];
	}
}
if ( ! function_exists( 'drop_print_live_postage_build_items_from_package' ) ) {
	function drop_print_live_postage_build_items_from_package( array $package ): array {
		$items = array();
		if ( empty( $package['contents'] ) || ! is_array( $package['contents'] ) ) {
			return $items;
		}
		foreach ( $package['contents'] as $cart_item ) {
			if ( ! drop_print_cart_item_is_drop_print_item( $cart_item ) ) {
				continue;
			}
			$sku = drop_print_get_cart_item_sku( $cart_item );
			if ( '' === $sku ) {
				continue;
			}
			$qty = isset( $cart_item['quantity'] ) ? max( 1, absint( $cart_item['quantity'] ) ) : 1;
			$items[] = array(
				'sku' => $sku,
				'qty' => $qty,
			);
		}
		return $items;
	}
}
add_action( 'woocommerce_shipping_init', 'drop_print_define_live_shipping_method_class' );
function drop_print_define_live_shipping_method_class() {
	if ( class_exists( 'Drop_Print_Live_Shipping_Method' ) || ! class_exists( 'WC_Shipping_Method' ) ) {
		return;
	}
	class Drop_Print_Live_Shipping_Method extends WC_Shipping_Method {
		public function __construct( $instance_id = 0 ) {
			$this->id                 = 'drop_print_live_postage';
			$this->instance_id        = absint( $instance_id );
			$this->method_title       = __( 'Drop Print Live Postage', 'drop-print' );
			$this->method_description = __( 'Real-time, destination-accurate shipping for Drop Print items, computed by the Drop Print API at checkout. Add this to a shipping zone to enable it — it does nothing until then.', 'drop-print' );
			$this->supports            = array( 'shipping-zones', 'instance-settings' );
			$this->init();
		}
		public function init() {
			$this->init_form_fields();
			$this->init_settings();
			$this->title   = $this->get_option( 'title', __( 'Shipping', 'drop-print' ) );
			$this->enabled = $this->get_option( 'enabled', 'yes' );
			add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
		}
		public function init_form_fields() {
			$this->instance_form_fields = array(
				'title' => array(
					'title'       => __( 'Method Title', 'drop-print' ),
					'type'        => 'text',
					'description' => __( 'Shown to the customer at checkout.', 'drop-print' ),
					'default'     => __( 'Shipping', 'drop-print' ),
					'desc_tip'    => true,
				),
			);
		}
		private function add_tier_unavailable_notice( string $tier_label ) {
			if ( ! function_exists( 'wc_add_notice' ) ) {
				return;
			}
			$message = sprintf(
				__( '%s is not available for this order right now — we have put you back on your default delivery option.', 'drop-print' ),
				$tier_label
			);
			if ( function_exists( 'wc_has_notice' ) && wc_has_notice( $message, 'notice' ) ) {
				return;
			}
			wc_add_notice( $message, 'notice' );
		}
		private function add_unavailable_notice() {
			if ( ! function_exists( 'wc_add_notice' ) ) {
				return;
			}
			$message = __( 'Shipping is temporarily unavailable — please retry or refresh your cart in a moment.', 'drop-print' );
			if ( function_exists( 'wc_has_notice' ) && wc_has_notice( $message, 'notice' ) ) {
				return;
			}
			wc_add_notice( $message, 'notice' );
		}
		const KNOWN_TIERS = array( 'budget', 'standard', 'express', 'overnight' );
		const ESTIMATE_LABEL_FORMAT = '%s (estimated)';
		private function get_customer_chosen_tier(): string {
			if ( ! function_exists( 'WC' ) || ! WC()->session ) {
				return '';
			}
			$chosen = WC()->session->get( 'chosen_shipping_methods' );
			if ( ! is_array( $chosen ) ) {
				return '';
			}
			$prefix = $this->get_rate_id() . ':';
			foreach ( $chosen as $rate_id ) {
				if ( is_string( $rate_id ) && 0 === strpos( $rate_id, $prefix ) ) {
					$tier = sanitize_key( substr( $rate_id, strlen( $prefix ) ) );
					return in_array( $tier, self::KNOWN_TIERS, true ) ? $tier : '';
				}
			}
			return '';
		}
		private function is_destination_ready( array $destination ): bool {
			if ( ! function_exists( 'WC' ) || ! WC()->countries ) {
				return false;
			}
			$country = isset( $destination['country'] ) ? strtoupper( sanitize_text_field( (string) $destination['country'] ) ) : '';
			if ( '' === $country ) {
				return false;
			}
			$fields = WC()->countries->get_address_fields( $country, 'shipping_' );
			foreach ( array( 'postcode', 'state' ) as $field ) {
				$definition = $fields[ "shipping_{$field}" ] ?? array();
				$required   = ! isset( $definition['required'] ) || $definition['required'];
				if ( ! $required ) {
					continue;
				}
				$value = isset( $destination[ $field ] ) ? trim( (string) $destination[ $field ] ) : '';
				if ( '' === $value ) {
					return false;
				}
			}
			return true;
		}
		private function is_checkout_context(): bool {
			if ( function_exists( 'is_checkout' ) && is_checkout() ) {
				return true;
			}
			if ( function_exists( 'is_cart' ) && is_cart() ) {
				return false;
			}
			$referer = isset( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : '';
			if ( '' !== $referer && function_exists( 'wc_get_checkout_url' ) ) {
				$checkout_url = untrailingslashit( wc_get_checkout_url() );
				if ( '' !== $checkout_url && 0 === strpos( untrailingslashit( $referer ), $checkout_url ) ) {
					return true;
				}
			}
			return false;
		}
		public function calculate_shipping( $package = array() ) {
			$items = drop_print_live_postage_build_items_from_package( $package );
			if ( empty( $items ) ) {
				return;
			}
			if ( ! $this->is_checkout_context() ) {
				return;
			}
			$destination_country = isset( $package['destination']['country'] ) ? strtoupper( sanitize_text_field( $package['destination']['country'] ) ) : '';
			if ( strlen( $destination_country ) !== 2 ) {
				return;
			}
			if ( ! $this->is_destination_ready( is_array( $package['destination'] ?? null ) ? $package['destination'] : array() ) ) {
				return;
			}
			$currency    = get_woocommerce_currency();
			$chosen_tier = $this->get_customer_chosen_tier();
			$credentials             = drop_print_live_postage_resolve_api_credentials();
			$configured_default_tier = is_array( $credentials ) ? ( $credentials['default_shipping_method'] ?? 'standard' ) : 'standard';
			$peek_only    = ( '' === $chosen_tier );
			$fetch_extras = $peek_only ? array( 'peek_only' => true ) : array();
			$result       = drop_print_live_postage_fetch_rate( $items, $destination_country, $currency, $fetch_extras );
			$default_tier = is_array( $result ) ? (string) ( $result['default_tier'] ?? '' ) : '';
			$rates        = is_array( $result ) ? ( $result['rates'] ?? null ) : null;
			if ( is_wp_error( $result ) || '' === $default_tier || ! is_array( $rates ) ) {
				$this->add_unavailable_notice();
				return;
			}
			$added_any = false;
			$tier_order = array_keys( $rates );
			foreach ( $tier_order as $tier ) {
				$tier = sanitize_key( (string) $tier );
				$rate = $rates[ $tier ] ?? null;
				if ( '' === $tier || ! is_array( $rate ) ) {
					continue;
				}
				$label_for_tier = ! empty( $rate['label'] ) ? sanitize_text_field( (string) $rate['label'] ) : ucfirst( $tier );
				if ( $tier === $chosen_tier ) {
					if ( $tier === $configured_default_tier ) {
						$live = drop_print_live_postage_fetch_rate( $items, $destination_country, $currency, array(
							'mode' => 'live_multi_tier',
							'tier' => $configured_default_tier,
						) );
						$resolved_tier = is_array( $live ) ? (string) ( $live['default_tier'] ?? '' ) : '';
						$live_rate     = ( is_array( $live ) && '' !== $resolved_tier && ! empty( $live['rates'][ $resolved_tier ]['amount'] ) )
							? $live['rates'][ $resolved_tier ]
							: null;
					} else {
						$live = drop_print_live_postage_fetch_rate( $items, $destination_country, $currency, array(
							'mode' => 'live',
							'tier' => $tier,
						) );
						$live_rate = ( ! is_wp_error( $live ) && is_array( $live ) && ! empty( $live['rates'][0] ) ) ? $live['rates'][0] : null;
					}
					if ( null === $live_rate || ! isset( $live_rate['amount'] ) ) {
						if ( 'cached' === (string) ( $rate['status'] ?? '' ) && isset( $rate['amount_from'] ) ) {
							$this->add_rate( array(
								'id'      => $this->get_rate_id( $tier ),
								'label'   => sprintf( self::ESTIMATE_LABEL_FORMAT, $label_for_tier ),
								'cost'    => (float) $rate['amount_from'],
								'package' => $package,
							) );
							$added_any = true;
							continue;
						}
						$this->add_tier_unavailable_notice( $label_for_tier );
						continue;
					}
					$this->add_rate( array(
						'id'      => $this->get_rate_id( $tier ),
						'label'   => ! empty( $live_rate['label'] ) ? sanitize_text_field( (string) $live_rate['label'] ) : $this->title,
						'cost'    => (float) $live_rate['amount'],
						'package' => $package,
					) );
					$added_any = true;
					continue;
				}
				$status = (string) ( $rate['status'] ?? '' );
				$label  = ! empty( $rate['label'] ) ? sanitize_text_field( (string) $rate['label'] ) : ucfirst( $tier );
				if ( 'live' === $status && isset( $rate['amount'] ) ) {
					$this->add_rate( array(
						'id'      => $this->get_rate_id( $tier ),
						'label'   => $label,
						'cost'    => (float) $rate['amount'],
						'package' => $package,
					) );
					$added_any = true;
				} elseif ( 'cached' === $status && isset( $rate['amount_from'] ) ) {
					$this->add_rate( array(
						'id'      => $this->get_rate_id( $tier ),
						'label'   => sprintf( self::ESTIMATE_LABEL_FORMAT, $label ),
						'cost'    => (float) $rate['amount_from'],
						'package' => $package,
					) );
					$added_any = true;
				}
			}
			if ( ! $added_any ) {
				$this->add_unavailable_notice();
			}
		}
	}
}
add_filter( 'woocommerce_shipping_methods', 'drop_print_register_live_shipping_method' );
function drop_print_register_live_shipping_method( $methods ) {
	$methods['drop_print_live_postage'] = 'Drop_Print_Live_Shipping_Method';
	return $methods;
}
if ( ! function_exists( 'drop_print_live_postage_force_default_chosen_method' ) ) {
	function drop_print_live_postage_force_default_chosen_method( $default, $rates = array(), $chosen = '' ) {
		if ( ! is_array( $rates ) || empty( $rates ) ) {
			return $default;
		}
		if ( is_string( $chosen ) && '' !== $chosen && isset( $rates[ $chosen ] ) ) {
			return $chosen;
		}
		if ( ! function_exists( 'drop_print_live_postage_resolve_api_credentials' ) ) {
			return $default;
		}
		$credentials = drop_print_live_postage_resolve_api_credentials();
		$tier        = is_array( $credentials ) ? sanitize_key( (string) ( $credentials['default_shipping_method'] ?? '' ) ) : '';
		if ( '' === $tier ) {
			return $default;
		}
		foreach ( array_keys( $rates ) as $rate_id ) {
			if ( is_string( $rate_id ) && substr( $rate_id, -( strlen( $tier ) + 1 ) ) === ':' . $tier
				&& 0 === strpos( $rate_id, 'drop_print_live_postage' ) ) {
				return $rate_id;
			}
		}
		return $default;
	}
}
add_filter( 'woocommerce_shipping_chosen_method', 'drop_print_live_postage_force_default_chosen_method', 10, 3 );
if ( ! function_exists( 'drop_print_warm_shipping_tiers_ajax_handler' ) ) {
	function drop_print_warm_shipping_tiers_ajax_handler() {
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'drop_print_warm_shipping_tiers' ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed.', 'drop-print' ) ), 403 );
			return;
		}
		if ( ! function_exists( 'WC' ) || ! WC()->cart || ! WC()->session || ! WC()->customer ) {
			wp_send_json_error( array( 'message' => __( 'No active session.', 'drop-print' ) ), 400 );
			return;
		}
		$items = drop_print_live_postage_build_items_from_package(
			array( 'contents' => WC()->cart->get_cart() )
		);
		if ( empty( $items ) ) {
			wp_send_json_success( array( 'warmed' => false, 'reason' => 'no_drop_print_items' ) );
			return;
		}
		$destination = strtoupper( (string) WC()->customer->get_shipping_country() );
		if ( strlen( $destination ) !== 2 ) {
			wp_send_json_success( array( 'warmed' => false, 'reason' => 'no_destination' ) );
			return;
		}
		$signature = md5( wp_json_encode( $items ) . '|' . $destination );
		if ( (string) WC()->session->get( 'dp_live_postage_warmed_signature' ) === $signature ) {
			wp_send_json_success( array( 'warmed' => false, 'reason' => 'already_warmed' ) );
			return;
		}
		WC()->session->set( 'dp_live_postage_warmed_signature', $signature );
		$result = drop_print_live_postage_fetch_rate(
			$items,
			$destination,
			get_woocommerce_currency(),
			array( 'resolve_all' => true )
		);
		if ( is_wp_error( $result ) ) {
			WC()->session->set( 'dp_live_postage_warmed_signature', '' );
			wp_send_json_success( array( 'warmed' => false, 'reason' => $result->get_error_code() ) );
			return;
		}
		wp_send_json_success( array( 'warmed' => true ) );
	}
}
add_action( 'wp_ajax_drop_print_warm_shipping_tiers', 'drop_print_warm_shipping_tiers_ajax_handler' );
add_action( 'wp_ajax_nopriv_drop_print_warm_shipping_tiers', 'drop_print_warm_shipping_tiers_ajax_handler' );
