<?php
/**
 * Omnibus provider for PerfectWP - WC Omnibus plugin.
 *
 * @package Ilabs\Firevert\Core\Integration\Omnibus
 *
 * @since 1.0.3
 */

declare(strict_types=1);

namespace Ilabs\Firevert\Core\Integration\Omnibus;

/**
 * Omnibus by PerfectWP integration provider.
 */
final class OmnibusByPerfectWpProvider extends AbstractOmnibusProvider {

	/**
	 * Returns the plugin name.
	 *
	 * @return string
	 */
	public function get_plugin_name(): string {
		return 'PerfectWP - WC Omnibus';
	}

	/**
	 * Returns the plugin creator.
	 *
	 * @return string
	 */
	public function get_plugin_creator(): string {
		return 'PerfectWP';
	}

	/**
	 * Checks whether the PerfectWP WC Omnibus plugin is active.
	 *
	 * @return bool
	 */
	public function is_active(): bool {
		return class_exists( \PerfectWPWCO\Plugin::class );
	}

	/**
	 * Returns the lowest price for the product, using plugin settings.
	 *
	 * @param int $product_id WooCommerce product ID.
	 *
	 * @return float|null
	 */
	public function get_lowest_price( int $product_id ): ?float {
		if ( ! $this->is_active() ) {
			return null;
		}

		if ( ! class_exists( \PerfectWPWCO\Repositories\HistoryPriceRepository::class ) ) {
			return null;
		}

		try {
			$repository = new \PerfectWPWCO\Repositories\HistoryPriceRepository();

			/**
			 * Get the lowest price from the history table.
			 *
			 * @var \PerfectWPWCO\Models\HistoryPrice|null $history_price
			 */
			$history_price = $repository->findLowestHistoryPriceInDaysFromOptions( $product_id );

			if ( null === $history_price ) {
				return null;
			}

			$price = $history_price->getPrice();

			if ( $price <= 0 ) {
				return null;
			}

			return (float) $price;
		} catch ( \Throwable $e ) {
			return null;
		}
	}

	/**
	 * Returns the date of the lowest price (start_date of that history record).
	 *
	 * @param int $product_id WooCommerce product ID.
	 *
	 * @return string|null Date in 'Y-m-d' format or null if unavailable.
	 */
	public function get_lowest_price_date( int $product_id ): ?string {
		if ( ! $this->is_active() ) {
			return null;
		}

		if ( ! class_exists( \PerfectWPWCO\Repositories\HistoryPriceRepository::class ) ) {
			return null;
		}

		try {
			$repository = new \PerfectWPWCO\Repositories\HistoryPriceRepository();

			/**
			 * Get HistoryPrice|null $history_price.
			 *
			 * @var \PerfectWPWCO\Models\HistoryPrice|null $history_price
			 */
			$history_price = $repository->findLowestHistoryPriceInDaysFromOptions( $product_id );

			if ( null === $history_price ) {
				return null;
			}

			return $history_price->getStartDate()->format( 'Y-m-d' );
		} catch ( \Throwable $e ) {
			return null;
		}
	}

	/**
	 * Returns the number of days since the lowest price date.
	 *
	 * @param int $product_id WooCommerce product ID.
	 *
	 * @return int|null
	 */
	public function get_lowest_price_days_ago( int $product_id ): ?int {
		if ( ! $this->is_active() ) {
			return null;
		}

		if ( ! class_exists( \PerfectWPWCO\Repositories\HistoryPriceRepository::class ) ) {
			return null;
		}

		try {
			$repository = new \PerfectWPWCO\Repositories\HistoryPriceRepository();

			$history_price = $repository->findLowestHistoryPriceInDaysFromOptions( $product_id );

			if ( null === $history_price ) {
				return null;
			}

			$start_date = $history_price->getStartDate();

			$now  = new \DateTimeImmutable( 'now' );
			$diff = $now->diff( $start_date );

			if ( ! $diff instanceof \DateInterval ) {
				return $this->get_fallback_days();
			}

			$days = (int) $diff->days;

			if ( $days < 0 ) {
				return $this->get_fallback_days();
			}

			if ( 0 === $days ) {
				return $this->get_fallback_days();
			}

			return $days;

		} catch ( \Throwable $e ) {
			if ( null !== $this->get_lowest_price( $product_id ) ) {

				return $this->get_fallback_days();
			}

			return null;
		}
	}

	/**
	 * Returns the fallback number of days from PerfectWP options.
	 *
	 * @return int
	 */
	private function get_fallback_days(): int {
		if ( class_exists( '\PerfectWPWCO\Models\Options' ) ) {
			return (int) \PerfectWPWCO\Models\Options::getLowestPriceNumberOfDays();
		}

		return 30;
	}
}
