<?php

declare(strict_types=1);

namespace Simplyin\Simplyin_W_Plugin\Shipping_Mapping\Integration\Apaczka;

use WC_Shipping_Method;

class Apaczka_Helper {

	/**
	 * Pattern that matches both "method:instance" and "method_instance" rate-ids.
	 * Capture group 1 – method slug, group 2 – numeric instance id.
	 */
	private const RATE_ID_PATTERN = '/^([a-zA-Z0-9\-_]+)[:_](\d+)$/';

	/**
	 * Attempt to detect all carrier/provider ids (e.g. inpost, dhl, dpd) that are
	 * linked with a concrete Apaczka shipping-method instance.
	 *
	 * @param string $shipping_method_rate_id Rate id formatted like "flat_rate:4" or "apaczka:12".
	 * @return string[] List of unique logistic provider slugs in lower-case.
	 */
	public function find_apaczka_providers(string $shipping_method_rate_id):array {
		// 1. Parse the rate-id and validate.
		if ( ! preg_match( self::RATE_ID_PATTERN, $shipping_method_rate_id, $matches ) ) {
			return [];
		}

		$instance_id = absint( $matches[2] );
		if ( 0 === $instance_id ) {
			return [];
		}

		// 2. Resolve the WC_Shipping_Method for the instance.
		$method = $this->get_wc_shipping_method_instance( $instance_id );
		if ( null === $method ) {
			return [];
		}

		$service_id = (int) ( $method->instance_settings['service'] ?? 0 );

		// 3. No explicit service chosen ⇒ return **все** провайдеры pickup-point.
		if ( 0 === $service_id ) {
			return $this->get_all_pickup_providers();
		}

		// 4. If service_id is not related to issue points - ignore.
		if ( ! $this->is_pickup_service( $service_id ) ) {
			return [];
		}

		// 5. Convert service_id → supplier slug.
		$providers = $this->map_service_to_provider( $service_id );

		$providers = $providers ?: [ 'apaczka' ];

		return $providers;
	}

	/**
	 * Locate WC_Shipping_Method instance by its instance id across all zones.
	 *
	 * @param int $instance_id
	 * @return WC_Shipping_Method|null
	 */
	private function get_wc_shipping_method_instance(int $instance_id): ?WC_Shipping_Method {
		foreach ( \WC_Shipping_Zones::get_zones() as $zone ) {
			$zoneObj = new \WC_Shipping_Zone( $zone['id'] );
			foreach ( $zoneObj->get_shipping_methods() as $method ) {
				if ( $method->get_instance_id() === $instance_id ) {
					return $method;
				}
			}
		}

		// Check "Rest of the world" zone (0)
		$zoneObj = new \WC_Shipping_Zone( 0 );
		foreach ( $zoneObj->get_shipping_methods() as $method ) {
			if ( $method->get_instance_id() === $instance_id ) {
				return $method;
			}
		}

		return null;
	}

	/**
	 * Return true if the service represents a parcel-locker / pickup-point.
	 */
	private function is_pickup_service( int $service_id ): bool {
		$map = $this->get_parcel_lockers_map();

		return isset( $map[ $service_id ] );
	}

	/**
	 * Map single service id → provider slug.
	 *
	 * @return string[]|null
	 */
	private function map_service_to_provider( int $service_id ): array {
		$map = $this->get_parcel_lockers_map();

		if ( isset( $map[ $service_id ] ) ) {
			return [ strtolower( $map[ $service_id ] ) ];
		}

		// Fallback – pull from dynamic service structure helper.
		if ( class_exists( '\\Inspire_Labs\\Apaczka_Woocommerce\\Service_Structure_Helper' ) ) {
			$services = ( new \Inspire_Labs\Apaczka_Woocommerce\Service_Structure_Helper() )->get_services();
			foreach ( $services as $srv ) {
				if ( (int) $srv->service_id === $service_id && ! empty( $srv->supplier ) ) {
					return [ strtolower( $srv->supplier ) ];
				}
			}
		}

		return [];
	}

	/**
	 * Full list of pickup-point providers from the Apaczka constant.
	 *
	 * @return string[]
	 */
	private function get_all_pickup_providers(): array {
		$map = $this->get_parcel_lockers_map();

		if ( empty( $map ) ) {
			return [ 'apaczka' ];
		}

		return array_values( array_unique( array_map( 'strtolower', array_values( $map ) ) ) );
	}

	/**
	 * Retrieve the PARCEL_LOCKER_GEOWIDGET_IDS map if the plugin defines it.
	 */
	private function get_parcel_lockers_map(): array {
		if ( defined( '\\Inspire_Labs\\Apaczka_Woocommerce\\Shipping_Method_Apaczka::PARCEL_LOCKER_GEOWIDGET_IDS' ) ) {
			/** @var array<int,string> $map */
			$map = \Inspire_Labs\Apaczka_Woocommerce\Shipping_Method_Apaczka::PARCEL_LOCKER_GEOWIDGET_IDS;

			return $map;
		}

		return [];
	}
}
