<?php // phpcs:ignore WordPress.Files.FileName.NotHyphenatedLowercase, WordPress.Files.FileName.InvalidClassFileName
/**
 * Core wholesale pricing service.
 *
 * @package Autoship\Modules\WholesalePricing\Services
 * @since   2.13.0
 */

namespace Autoship\Modules\WholesalePricing\Services;

use Autoship\Domain\WholesalePricing\WholesaleRequirements;
use Autoship\Domain\WholesalePricing\WholesaleValidationResult;
use Autoship\Repositories\WholesaleDiscountRepositoryInterface;

/**
 * Core orchestrator for wholesale pricing operations.
 *
 * Provides validation, price adjustment, and user role retrieval.
 * No WC notice calls — notice lifecycle is owned by WholesaleNoticeManager.
 *
 * @package Autoship\Modules\WholesalePricing\Services
 * @since   2.13.0
 */
class WholesalePricingService implements WholesalePricingServiceInterface {

	/**
	 * The requirements resolver.
	 *
	 * @var WholesaleRequirementsResolver
	 */
	private WholesaleRequirementsResolver $resolver;

	/**
	 * The discount repository.
	 *
	 * @var WholesaleDiscountRepositoryInterface
	 */
	private WholesaleDiscountRepositoryInterface $discount_repository;

	/**
	 * Constructor.
	 *
	 * @param WholesaleRequirementsResolver        $resolver            The resolver.
	 * @param WholesaleDiscountRepositoryInterface $discount_repository The discount repository.
	 */
	public function __construct(
		WholesaleRequirementsResolver $resolver,
		WholesaleDiscountRepositoryInterface $discount_repository
	) {
		$this->resolver            = $resolver;
		$this->discount_repository = $discount_repository;
	}

	/**
	 * Validate wholesale requirements for a given user/role/product.
	 *
	 * @param array    $user_wholesale_role The user's wholesale role.
	 * @param int      $qty                Actual item quantity.
	 * @param float    $total              Actual item total price.
	 * @param int|bool $product_id         The product ID.
	 *
	 * @return WholesaleValidationResult
	 */
	public function validate( array $user_wholesale_role, int $qty, float $total, $product_id = false ): WholesaleValidationResult {
		$requirements = $this->resolver->resolve( $user_wholesale_role, $product_id );

		return $this->check_requirements( $requirements, $qty, $total );
	}

	/**
	 * Check requirements against actual values.
	 *
	 * Pure validation with no side effects.
	 *
	 * @param WholesaleRequirements $requirements The resolved requirements.
	 * @param int                   $qty          Actual item quantity.
	 * @param float                 $total        Actual item total price.
	 *
	 * @return WholesaleValidationResult
	 */
	public function check_requirements( WholesaleRequirements $requirements, int $qty, float $total ): WholesaleValidationResult {
		$has_qty   = $requirements->has_quantity_requirement();
		$has_price = $requirements->has_price_requirement();

		if ( ! $has_qty && ! $has_price ) {
			return WholesaleValidationResult::pass( $qty, $total, $requirements );
		}

		$min_items = $requirements->get_minimum_order_items();
		$min_price = $requirements->get_minimum_order_price();

		// MOQ only.
		if ( $has_qty && ! $has_price ) {
			if ( $qty < $min_items ) {
				return WholesaleValidationResult::fail( 'min_qty', $qty, $total, $requirements );
			}
			return WholesaleValidationResult::pass( $qty, $total, $requirements );
		}

		// MOP only.
		if ( $has_price && ! $has_qty ) {
			if ( $total < $min_price ) {
				return WholesaleValidationResult::fail( 'min_price', $qty, $total, $requirements );
			}
			return WholesaleValidationResult::pass( $qty, $total, $requirements );
		}

		// Both MOQ and MOP.
		$logic = $requirements->get_conditional_logic();

		if ( strcasecmp( $logic, 'and' ) === 0 ) {
			// AND: fail if either is not met.
			if ( $qty < $min_items || $total < $min_price ) {
				return WholesaleValidationResult::fail( 'min_qty_and_price', $qty, $total, $requirements );
			}
		} elseif ( $qty < $min_items && $total < $min_price ) {
			// OR: fail only if both are not met.
			return WholesaleValidationResult::fail( 'min_qty_and_price', $qty, $total, $requirements );
		}

		return WholesaleValidationResult::pass( $qty, $total, $requirements );
	}

	/**
	 * Adjust the wholesale price for a product.
	 *
	 * @param int           $product_id          The product ID.
	 * @param float|null    $base_wholesale_price The base wholesale price.
	 * @param float|null    $regular_price        The regular price.
	 * @param \WP_User|null $wp_user              The user.
	 *
	 * @return float|null The adjusted wholesale price, or null.
	 */
	public function adjust_price( int $product_id, ?float $base_wholesale_price = null, ?float $regular_price = null, $wp_user = null ): ?float {
		if ( null === $base_wholesale_price ) {
			$base_wholesale_price = $this->retrieve_base_price( $product_id, $wp_user );
		}

		if ( null !== $base_wholesale_price ) {
			$user_wholesale_role = $this->get_user_role( $wp_user );
			$discount            = $this->get_scheduled_discount_percentage( $product_id, $user_wholesale_role );
			$regular_price       = floatval( $base_wholesale_price ) - ( floatval( $base_wholesale_price ) * $discount );
		}

		return ( ! isset( $regular_price ) || ( empty( $regular_price ) && 0 !== $regular_price ) ) ? null : $regular_price;
	}

	/**
	 * Get the user's wholesale role.
	 *
	 * @param \WP_User|null $wp_user The user.
	 *
	 * @return array The user's wholesale role.
	 */
	public function get_user_role( $wp_user = null ): array {
		if ( ! class_exists( 'WWP_Wholesale_Roles' ) ) {
			return array();
		}

		$wp_user   = $wp_user && ( $wp_user instanceof \WP_User ) ? $wp_user : null;
		$wwp_roles = new \WWP_Wholesale_Roles();

		return apply_filters( 'autoship_get_user_wholesale_role', $wwp_roles->getUserWholesaleRole( $wp_user ), $wp_user );
	}

	/**
	 * Retrieve the wholesale base price for a product.
	 *
	 * @param int           $product_id The product ID.
	 * @param \WP_User|null $wp_user    The user.
	 *
	 * @return float|null The wholesale base price, or null.
	 */
	public function retrieve_base_price( int $product_id, $wp_user = null ): ?float {
		$wholesale = null;

		$user_wholesale_role = $this->get_user_role( $wp_user );

		if ( ! empty( $user_wholesale_role ) ) {
			$wholesale = $this->calculate_wholesale_price( $product_id, $user_wholesale_role );
		}

		return ( ! isset( $wholesale ) || ( empty( $wholesale ) && 0 !== $wholesale ) ) ? null : (float) $wholesale;
	}

	/**
	 * Get the scheduled discount percentage for a product.
	 *
	 * @param int    $product_id          The product ID.
	 * @param string $user_wholesale_role The user's wholesale role.
	 *
	 * @return float The discount as a decimal (e.g., 0.10 for 10%).
	 */
	public function get_scheduled_discount_percentage( int $product_id, $user_wholesale_role ): float {
		$discount   = $this->discount_repository->get_discount( $product_id );
		$percentage = empty( $discount ) ? 0 : $discount / 100;

		return apply_filters( 'autoship_wholesale_scheduled_discount_percentage', $percentage, $product_id, $user_wholesale_role );
	}

	/**
	 * Calculate the wholesale price for a product using WWP.
	 *
	 * @param int   $product_id          The product ID.
	 * @param array $user_wholesale_role The user's wholesale role.
	 *
	 * @return string|null The wholesale price, or null.
	 */
	private function calculate_wholesale_price( int $product_id, array $user_wholesale_role ) {
		if ( ! class_exists( 'WWP_Wholesale_Prices' ) ) {
			return null;
		}

		$prices = \WWP_Wholesale_Prices::get_product_wholesale_price_on_shop_v3( $product_id, $user_wholesale_role );

		return apply_filters( 'autoship_calculate_schedule_product_wholesale_price', trim( $prices['wholesale_price'] ), $product_id, $user_wholesale_role );
	}
}
