<?php
/**
 * Class DhlInstanceSettings
 *
 * @package DhlPolska\ShippingMethod
 */

namespace DhlPolska\ShippingMethod;

use DhlPolska\SettingsFields;
use DhlPolska\Shipment\DhlServices;
use DhlPolska\Shipment\ShipmentData;
use DhlPolska\Shipment\ShipmentTypes;
use DhlPolska\WooCommerceSettings\Templates\TemplatesRepository;
use DhlPolska\WooCommerceSettings\WooCommerceDHLPolskaSettings;

/**
 * DHL Instance Settings.
 */
class DhlInstanceSettings implements SettingsFields {
	public const OPTION_TITLE      = 'title';
	public const OPTION_SHOW_LOGO  = 'show_logo';
	public const OPTION_TAX_STATUS = 'tax_status';
	public const OPTION_SERVICE    = 'service';
	public const OPTION_POINT_TYPE = 'point_type';
	public const OPTION_TEMPLATE   = 'template_id';
	public const OPTION_COST       = 'cost';

	private TemplatesRepository $templates_repository;

	private ShipmentTypes $shipment_types;

	private ?int $instance_id;

	public function __construct( ?TemplatesRepository $templates_repository = null, ?ShipmentTypes $shipment_types = null, ?int $instance_id = null ) {
		$this->shipment_types       = $shipment_types ?? new ShipmentTypes();
		$this->templates_repository = $templates_repository ?? new TemplatesRepository( new WooCommerceDHLPolskaSettings(), $this->shipment_types );
		$this->instance_id          = $instance_id;
	}

	/**
	 * @return array<int|string, array<string, array<string, float|int|string>|bool|float|int|string>>
	 */
	public function get_settings_fields(): array {
		$fields = [
			'dhl_start'             => [
				'type' => 'title',
			],
			self::OPTION_TITLE      => [
				'title'    => __( 'Nazwa metody', 'dhl-polska' ),
				'type'     => 'text',
				'desc_tip' => __( 'Wyświetlana w koszyku i kasie.', 'dhl-polska' ),
			],
			self::OPTION_SHOW_LOGO  => [
				'title'   => __( 'Logo DHL', 'dhl-polska' ),
				'type'    => 'checkbox',
				'label'   => __( 'Wyświetl logo DHL pod nazwą metody wysyłki.', 'dhl-polska' ),
				'default' => 'no',
			],
			self::OPTION_TAX_STATUS => [
				'title'    => __( 'Status podatku', 'dhl-polska' ),
				'type'     => 'select',
				'default'  => 'taxable',
				'options'  => [
					'taxable' => __( 'Opodatkowany', 'dhl-polska' ),
					'none'    => _x( 'Brak', 'Tax status', 'dhl-polska' ),
				],
				'desc_tip' =>
					sprintf(
					// Translators: open strong tag, close strong tag.
						__(
							'Po wybraniu opodatkowania zastosowane będą stawki z %1$sWooCommerce → Ustawienia → Podatki%2$s.',
							'dhl-polska'
						),
						'<strong>',
						'</strong>'
					),
			],
			self::OPTION_SERVICE    => [
				'title'   => __( 'Usługa DHL', 'dhl-polska' ),
				'type'    => 'select',
				'options' => ( new DhlServices() )->get_all_services(),
				'class'   => 'js--dhl-polska-service',
			],
		];

		if ( $this->should_show_point_type_field() ) {
			$fields[ self::OPTION_POINT_TYPE ] = [
				'title'   => __( 'Typ punktu odbioru', 'dhl-polska' ),
				'type'    => 'select',
				'options' => [
					ShipmentData::POINT_TYPE_PARCELSHOP  => __( 'Punkt partnerski', 'dhl-polska' ),
					ShipmentData::POINT_TYPE_PACKSTATION => __( 'Automat paczkowy', 'dhl-polska' ),
				],
				'default' => ShipmentData::POINT_TYPE_PARCELSHOP,
				'class'   => 'js--dhl-polska-point-type',
			];
		}

		$fields[ self::OPTION_TEMPLATE ] = [
			'title'    => __( 'Szablon przesyłki', 'dhl-polska' ),
			'type'     => 'select',
			'options'  => $this->get_template_options(),
			'default'  => '',
			'desc_tip' => __( 'Wybierz szablon przesyłki dla tej metody.', 'dhl-polska' ),
		];

		$fields[ self::OPTION_COST ] = [
			'title'       => __( 'Koszt', 'dhl-polska' ),
			'type'        => 'text',
			'placeholder' => '',
			'default'     => 0,
			'desc_tip'    => __( 'Stały koszt przesyłki dla tej metody.', 'dhl-polska' ),
		];
		$fields['dhl_end']           = [
			'type' => 'title',
		];

		return $fields;
	}

	/**
	 * @return array<string, string>
	 */
	private function get_template_options(): array {
		$options = [
			'' => __( 'Brak', 'dhl-polska' ),
		];

		$templates = $this->templates_repository->get_templates();
		foreach ( $templates as $template ) {
			if ( ! isset( $template['id'], $template['name'] ) ) {
				continue;
			}

			$options[ (string) $template['id'] ] = $this->format_template_option_label( $template );
		}

		return $options;
	}

	/**
	 * @param array<string, mixed> $template .
	 */
	private function format_template_option_label( array $template ): string {
		$weight_unit    = get_option( 'woocommerce_weight_unit', 'kg' );
		$dimension_unit = get_option( 'woocommerce_dimension_unit', 'cm' );
		$weight         = wc_format_decimal( (string) ( $template['weight'] ?? '' ) );
		$type_labels    = $this->shipment_types->get_type_labels();
		$type_label     = $type_labels[ (string) ( $template['type'] ?? '' ) ] ?? (string) ( $template['type'] ?? '' );
		$dimensions     = sprintf(
			'%sx%sx%s',
			(string) ( $template['dimensions']['length'] ?? '' ),
			(string) ( $template['dimensions']['width'] ?? '' ),
			(string) ( $template['dimensions']['height'] ?? '' )
		);
		$cod            = (bool) ( $template['services']['cod'] ?? false );
		$insurance      = (bool) ( $template['services']['insurance'] ?? false );

		$details = [
			$type_label,
			trim( $weight . ' ' . $weight_unit ),
			trim( $dimensions . ' ' . $dimension_unit ),
		];

		if ( $cod ) {
			$details[] = __( 'Pobranie', 'dhl-polska' );
		}

		if ( $insurance ) {
			$details[] = __( 'Ubezpieczenie', 'dhl-polska' );
		}

		return sprintf(
			'%s (%s)',
			(string) ( $template['name'] ?? '' ),
			implode( ', ', $details )
		);
	}

	private function should_show_point_type_field(): bool {
		if ( null === $this->instance_id || 0 === $this->instance_id ) {
			return true;
		}

		if ( ! class_exists( 'WC_Shipping_Zones' ) ) {
			return true;
		}

		$zone = \WC_Shipping_Zones::get_zone_by( 'instance_id', $this->instance_id );
		if ( ! $zone instanceof \WC_Shipping_Zone ) {
			return true;
		}

		if ( 0 === (int) $zone->get_id() ) {
			return true;
		}

		$locations = $zone->get_zone_locations();
		if ( empty( $locations ) ) {
			return true;
		}

		$countries = [];
		foreach ( $locations as $location ) {
			if ( ! isset( $location->type, $location->code ) ) {
				continue;
			}

			if ( 'continent' === $location->type ) {
				return true;
			}

			if ( 'country' === $location->type ) {
				$countries[] = (string) $location->code;
				continue;
			}

			if ( 'state' === $location->type ) {
				$parts       = explode( ':', (string) $location->code, 2 );
				$countries[] = (string) $parts[0];
			}
		}

		$countries = array_filter( $countries, static fn ( $country ) => '' !== $country );
		if ( empty( $countries ) ) {
			return true;
		}

		foreach ( $countries as $country ) {
			if ( 'PL' !== strtoupper( $country ) ) {
				return true;
			}
		}

		return false;
	}
}
