<?php
/**
 * Handles view/template changes related to stock.
 *
 * @package flo-sync
 */

namespace NMFS\Sync\Items\Articles\Stock;

use NMFS\Shared;
use NMFS\Sync\Items\Articles\Stock\Models\Stock_Data_Collection_Model;
use Northmill_Online_Shared_Sync\Northmill_Online_Shared\Abstracts\Hub_API\Hub_Accounts\Hub_Account_Setup;
use WC_Product;
use WP_Post;

defined( 'ABSPATH' ) || exit;

/**
 * Stock view class.
 */
class View {

	/**
	 * Constructor.
	 */
	public static function setup(): void {
		add_action(
			'woocommerce_product_options_inventory_product_data',
			array( self::class, 'admin_add_stock_field' )
		);

		add_action(
			'woocommerce_variation_options_inventory',
			array(
				self::class,
				'admin_add_variation_custom_product_meta_inventory',
			),
			10,
			3
		);

		add_action(
			'woocommerce_variation_options_pricing',
			array(
				self::class,
				'admin_add_variation_custom_product_meta_no_inventory',
			),
			10,
			3
		);

		add_filter(
			'woocommerce_get_stock_html',
			array( self::class, 'stock_html' ),
			10,
			2
		);

		add_filter(
			'woocommerce_get_availability',
			array( self::class, 'product_availability' ),
			10,
			2
		);
	}

	/**
	 * Show stock data on product edit page.
	 */
	public static function admin_add_stock_field(): void {
		/**
		 * Product object for this page.
		 *
		 * @var WC_Product $product_object
		 */
		global $product_object;

		if ( ! Hub_Account_Setup::is_multiple_stocks_enabled() ) {
			return;
		}

		$product_stock_collection = Stock::get_wc_product_stock_data( $product_object, 'display_name' );

		if ( empty( $product_stock_collection?->get_stock_data() ) ) {
			return;
		}

		Shared::instance()->template_loader->get_admin_template_part(
			'wc-article-stock-fields',
			array(
				'product_stock_collection' => $product_stock_collection,
				'manages_stock'            => $product_object->get_manage_stock(),
				'is_variation'             => false,
			),
			false
		);
	}

	/**
	 * Display MAS data on variation edit page.
	 *
	 * @param int     $loop Position in the loop.
	 * @param array   $variation_data Variation data.
	 * @param WP_Post $variation Post data.
	 *
	 * @return void
	 * @noinspection PhpUnusedParameterInspection WP action/filter function.
	 */
	public static function admin_add_variation_custom_product_meta_inventory( int $loop, array $variation_data, WP_Post $variation ): void {
		self::variation_stock_fields( $variation->ID, true );
	}

	/**
	 * Display MAS data on variation edit page.
	 *
	 * @param int     $loop Position in the loop.
	 * @param array   $variation_data Variation data.
	 * @param WP_Post $variation Post data.
	 *
	 * @return void
	 * @noinspection PhpUnusedParameterInspection WP action/filter function.
	 */
	public static function admin_add_variation_custom_product_meta_no_inventory( int $loop, array $variation_data, WP_Post $variation ): void {
		$wc_variation = wc_get_product( $variation->ID );
		if ( $wc_variation->get_manage_stock() ) {
			return;
		}
		self::variation_stock_fields( $variation->ID, false );
	}

	/**
	 * Action for variation stock HTML.
	 *
	 * @param int  $variation_id  Variation ID.
	 * @param bool $manages_stock Whether the product manages stock.
	 *
	 * @return void
	 */
	private static function variation_stock_fields( int $variation_id, bool $manages_stock ): void {
		if ( ! Hub_Account_Setup::is_multiple_stocks_enabled() ) {
			return;
		}

		$product_stock_collection = Stock::get_wc_product_stock_data( $variation_id, 'display_name' );

		if ( empty( $product_stock_collection?->get_stock_data() ) ) {
			return;
		}

		echo $manages_stock ? '' : '</div>'; // Close pricing div.
		Shared::instance()->template_loader->get_admin_template_part(
			'wc-article-stock-fields',
			array(
				'product_stock_collection' => $product_stock_collection,
				'manages_stock'            => $manages_stock,
				'is_variation'             => true,
			),
			false
		);
		echo $manages_stock ? '' : '<div>'; // Open div closed as pricing div.
	}

	/**
	 * Filter stock html.
	 *
	 * @param string     $html Current stock html.
	 * @param WC_Product $product WC_Product object.
	 *
	 * @noinspection PhpUnusedParameterInspection WP action/filter function.
	 */
	public static function stock_html( string $html, WC_Product $product ): string {
		$availability = $product->get_availability();

		return $availability['availability'];
	}

	/**
	 * Filter product availability.
	 *
	 * @param array      $availability Current product availability.
	 * @param WC_Product $product WC_Product object.
	 */
	public static function product_availability( array $availability, WC_Product $product ): array {
		if ( ! Hub_Account_Setup::is_multiple_stocks_enabled() ) {
			return $availability;
		}

		$availability['class'] = 'in-stock';

		$availability['availability'] = self::render_mas_product_availability( $product );

		return $availability;
	}

	/**
	 * Render multi-account sync product availability.
	 * TODO: Also modify order emails to include backorder information.
	 *
	 * @param WC_Product $product WC_Product object.
	 *
	 * @return string HTML for rendered availability.
	 */
	public static function render_mas_product_availability( WC_Product $product ): string {

		if ( ! Hub_Account_Setup::is_multiple_stocks_enabled() ) {
			return '';
		}

		$product_stock_collection = Stock::get_wc_product_stock_data( $product, 'display_name' );
		$is_backorder_allowed     = $product->get_backorders() === 'yes' || $product->get_backorders() === 'notify';

		if (
			empty( $product_stock_collection?->get_stock_data() ) ||
			false === $product_stock_collection->is_stock_kept
		) {
			return '';
		}

		ob_start();
		echo '<h2>' . esc_html__( 'Stock', 'flo-sync' ) . '</h2>';
		echo '<ul class="nmf-single-product-stock">';
		foreach ( $product_stock_collection->get_stock_data() as $stock_data ) {
			if ( ! isset( $stock_data->hub_account ) ) {
				continue;
			}
			$out_of_stock = $stock_data->quantity < 1;

			if ( $out_of_stock && ! $is_backorder_allowed ) {
				$class         = 'nmf-out-of-stock';
				$quantity_text = __( 'Out of stock', 'woocommerce' );

			} elseif ( $product->managing_stock() && $out_of_stock ) {
				$quantity_text = $product->backorders_require_notification() ? __( 'Available on backorder', 'woocommerce' ) : __( 'In stock', 'flo-sync' );
				$class         = 'available-on-backorder';
			} elseif ( ! $product->managing_stock() && $out_of_stock ) {
				$quantity_text = __( 'Available on backorder', 'woocommerce' );
				$class         = 'available-on-backorder';
			} elseif ( $product->managing_stock() ) {
				$quantity_text = wc_format_stock_quantity_for_display( $stock_data->quantity, $product );
				$class         = 'in-stock';
			} else {
				$quantity_text = __( 'In stock', 'flo-sync' );
				$class         = 'in-stock';
			}

			echo '<li class="' . esc_attr( $class ) . '">';
			echo esc_html( $stock_data->hub_account->get_display_name() ) . ' <span class="availability-text">(' . esc_html( $quantity_text ) . ')</span>';
			echo '</li>';
		}
		echo '</ul>';

		$html = ob_get_clean();

		/**
		 * Filter the multi-account sync product availability HTML.
		 *
		 * @param string                      $html Current stock html.
		 * @param Stock_Data_Collection_Model $product_stock_data Product stock data collection.
		 * @param WC_Product                  $product WC_Product object.
		 */
		return apply_filters( 'nmf_mas_product_availability', $html, $product_stock_collection, $product );
	}
}
