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

namespace DhlPolska\ShippingMethod;

use DhlPolska\Integration\FlexibleShipping\FlexibleShippingIntegration;
use DhlPolska\SanitizeTrait;
use DhlPolska\Shipment\DhlServices;
use DhlPolska\Shipment\ShipmentData;
use DhlPolska\Shipment\ShipmentTypes;
use DhlPolska\WooCommerceSettings\Templates\TemplatesRepository;
use DhlPolska\WooCommerceSettings\WooCommerceDHLPolskaSettings;
use WC_Shipping_Method;

/**
 * Shipping Method Class.
 */
class DhlShippingMethod extends WC_Shipping_Method {
	use SanitizeTrait;

	public const SHIPPING_METHOD_ID = 'dhl_polska_flat_rate';

	/**
	 * Unique ID for the shipping method - must be set.
	 *
	 * @var string
	 */
	public $id = self::SHIPPING_METHOD_ID;

	/**
	 * Supports.
	 *
	 * @var array
	 */
	public $supports = [
		'shipping-zones',
		'instance-settings',
	];

	/**
	 * @var string
	 */
	private $cost;

	/**
	 * @var string
	 */
	private $service;

	/**
	 * @var string
	 */
	private $cod;

	/**
	 * @var string
	 */
	private $template_id;

	/**
	 * @var string
	 */
	private $point_type;

	/**
	 * @var string
	 */
	private $point_type_pl;

	/**
	 * @var string
	 */
	private $show_logo;

	/**
	 * @var string
	 */
	private $logo_variant;

	/**
	 * DhlShippingMethod constructor.
	 *
	 * @param int $instance_id .
	 */
	public function __construct( $instance_id = 0 ) {
		parent::__construct( $instance_id );

		$this->method_title       = __( 'DHL Polska', 'dhl-polska' );
		$this->method_description = __( 'Integracja DHL Polska dla WooCommerce.', 'dhl-polska' );

		$this->init();
	}

	/**
	 * Init settings.
	 *
	 * @return void
	 */
	private function init() {
		$this->init_form_fields();
		$this->init_settings();

		$this->title         = $this->get_option_value_title();
		$this->tax_status    = $this->get_option_value_tax_status();
		$this->cost          = $this->get_option_value_cost();
		$this->service       = $this->get_option_value_service();
		$this->cod           = $this->get_option_value_cod();
		$this->template_id   = $this->get_option_value_template();
		$this->point_type    = $this->get_option_value_point_type();
		$this->point_type_pl = $this->get_option_value_point_type_pl();
		$this->show_logo     = $this->get_option_value_show_logo();
		$this->logo_variant  = $this->get_option_value_logo_variant();

		add_action( 'woocommerce_update_options_shipping_' . $this->id, [ $this, 'process_settings_update' ] );
	}

	/**
	 * @return void
	 */
	public function process_settings_update() {
		$this->process_admin_options();
	}

	/**
	 * @return void
	 */
	public function init_form_fields() {
		$this->instance_form_fields = ( new DhlInstanceSettings( null, new ShipmentTypes(), $this->instance_id ) )->get_settings_fields();
	}

	/**
	 * Calculate shipping.
	 *
	 * @param array $package .
	 *
	 * @return void
	 */
	public function calculate_shipping( $package = [] ) {
		$rate = $this->get_rate_data( $package );

		$this->add_rate( $rate );

		do_action( 'woocommerce_' . $this->id . '_shipping_add_rate', $this, $rate );
	}

	/**
	 * @param array $package .
	 *
	 * @return array<string, mixed>
	 */
	private function get_rate_data( $package ): array {
		$shipping_country = $this->get_shipping_country_from_package( $package );
		$point_type       = ShipmentData::resolve_point_type_from_method(
			[
				ShipmentData::OPTION_POINT_TYPE    => $this->point_type,
				ShipmentData::OPTION_POINT_TYPE_PL => $this->point_type_pl,
			],
			$shipping_country
		);

		return [
			'id'        => $this->get_rate_id(),
			'label'     => $this->title,
			'cost'      => $this->get_float_value( $this->cost ),
			'package'   => $package,
			'meta_data' => [
				'_fs_method' => [
					'method_integration'                  => FlexibleShippingIntegration::INTEGRATION_ID,
					ShipmentData::OPTION_SERVICE          => $this->service,
					ShipmentData::OPTION_COD              => $this->cod,
					ShipmentData::OPTION_TEMPLATE         => $this->template_id,
					ShipmentData::OPTION_POINT_TYPE       => $point_type,
					ShipmentData::OPTION_POINT_TYPE_PL    => $this->point_type_pl,
					DhlInstanceSettings::OPTION_SHOW_LOGO => $this->show_logo,
					DhlInstanceSettings::OPTION_LOGO_VARIANT => $this->logo_variant,
				],
			],
		];
	}

	/**
	 * @return string
	 */
	private function get_option_value_title(): string {
		return (string) $this->get_instance_option( DhlInstanceSettings::OPTION_TITLE, $this->method_title );
	}

	/**
	 * @return string
	 */
	private function get_option_value_tax_status(): string {
		return (string) $this->get_instance_option( DhlInstanceSettings::OPTION_TAX_STATUS, 'taxable' );
	}

	/**
	 * @return string
	 */
	private function get_option_value_cost(): string {
		return (string) $this->get_instance_option( DhlInstanceSettings::OPTION_COST, '0' );
	}

	/**
	 * @return string
	 */
	private function get_option_value_service(): string {
		return (string) $this->get_instance_option( DhlInstanceSettings::OPTION_SERVICE, DhlServices::SERVICE_AH );
	}

	/**
	 * @return string
	 */
	private function get_option_value_template(): string {
		return (string) $this->get_instance_option( DhlInstanceSettings::OPTION_TEMPLATE, '' );
	}

	/**
	 * @return string
	 */
	private function get_option_value_point_type(): string {
		if ( ! $this->has_instance_field( DhlInstanceSettings::OPTION_POINT_TYPE ) ) {
			return ShipmentData::POINT_TYPE_PARCELSHOP;
		}

		$point_type = (string) $this->get_instance_option( DhlInstanceSettings::OPTION_POINT_TYPE, ShipmentData::POINT_TYPE_PARCELSHOP );

		return ShipmentData::normalize_point_type( $point_type );
	}

	/**
	 * @return string
	 */
	private function get_option_value_point_type_pl(): string {
		if ( ! $this->has_instance_field( DhlInstanceSettings::OPTION_POINT_TYPE_PL ) ) {
			return ShipmentData::POINT_TYPE_PL_ALL;
		}

		$point_type_pl = (string) $this->get_instance_option( DhlInstanceSettings::OPTION_POINT_TYPE_PL, ShipmentData::POINT_TYPE_PL_ALL );

		return ShipmentData::normalize_point_type_pl( $point_type_pl );
	}

	/**
	 * @param string $key .
	 *
	 * @return bool
	 */
	private function has_instance_field( string $key ): bool {
		$instance_fields = $this->get_instance_form_fields();

		return isset( $instance_fields[ $key ] );
	}

	/**
	 * @param array<string, mixed> $package .
	 *
	 * @return string
	 */
	private function get_shipping_country_from_package( array $package ): string {
		$destination = $package['destination'] ?? [];
		if ( ! is_array( $destination ) ) {
			return '';
		}

		return strtoupper( (string) ( $destination['country'] ?? '' ) );
	}

	/**
	 * @return string
	 */
	private function get_option_value_show_logo(): string {
		$show_logo = (string) $this->get_instance_option( DhlInstanceSettings::OPTION_SHOW_LOGO, 'no' );

		return 'yes' === $show_logo ? 'yes' : 'no';
	}

	/**
	 * @return string
	 */
	private function get_option_value_logo_variant(): string {
		if ( ! $this->has_instance_field( DhlInstanceSettings::OPTION_LOGO_VARIANT ) ) {
			return LogoVariants::get_default_variant();
		}

		$logo_variant = (string) $this->get_instance_option( DhlInstanceSettings::OPTION_LOGO_VARIANT, LogoVariants::get_default_variant() );

		return LogoVariants::normalize_variant( $logo_variant );
	}

	/**
	 * @return string
	 */
	private function get_option_value_cod(): string {
		$template_id = (string) $this->get_instance_option( DhlInstanceSettings::OPTION_TEMPLATE, '' );
		if ( '' === $template_id ) {
			return 'no';
		}

		$template = ( new TemplatesRepository( new WooCommerceDHLPolskaSettings(), new ShipmentTypes() ) )->get_template( $template_id );
		if ( null === $template ) {
			return 'no';
		}

		$cod_enabled = (bool) ( $template['services'][ ShipmentData::TEMPLATE_SERVICE_COD ] ?? false );

		return $cod_enabled ? 'yes' : 'no';
	}
}
