<?php // phpcs:ignore WordPress.Files.FileName.NotHyphenatedLowercase, WordPress.Files.FileName.InvalidClassFileName
/**
 * Snooze action implementation.
 *
 * Pauses a scheduled order with an auto-resume duration by calling
 * the QPilot Snooze endpoint. If the order is already snoozed, it
 * first activates it via SafeActivate before applying the new snooze.
 *
 * @package Autoship\Services\QuickLinks\Actions
 * @since   2.11.0
 */

namespace Autoship\Services\QuickLinks\Actions;

use Autoship\Services\QuickLinks\Interfaces\QuickLinkActionInterface;
use Autoship\Services\QuickLinks\Interfaces\QuickLinkRepositoryInterface;
use Autoship\Services\Logging\LoggerInterface;
use Autoship\Domain\QuickLinks\ActionResult;
use Autoship\Domain\QuickLinks\ActionType;

/**
 * Snooze action strategy.
 *
 * Pauses a scheduled order with a defined auto-resume duration.
 */
class SnoozeAction implements QuickLinkActionInterface {

	/**
	 * QuickLink repository.
	 *
	 * @var QuickLinkRepositoryInterface
	 */
	private QuickLinkRepositoryInterface $repository;

	/**
	 * Logger instance.
	 *
	 * @var LoggerInterface
	 */
	private LoggerInterface $logger;

	/**
	 * Constructor.
	 *
	 * @param QuickLinkRepositoryInterface $repository The repository instance.
	 * @param LoggerInterface              $logger     The logger instance.
	 */
	public function __construct( QuickLinkRepositoryInterface $repository, LoggerInterface $logger ) {
		$this->repository = $repository;
		$this->logger     = $logger;
	}

	/**
	 * Execute snooze action.
	 *
	 * Note: This method is part of the QuickLinkActionInterface but snooze
	 * requires additional parameters (duration data). For Native UI usage,
	 * call execute_snooze() directly instead.
	 *
	 * @param int $site_id            The QPilot site ID.
	 * @param int $scheduled_order_id The scheduled order ID.
	 *
	 * @return ActionResult
	 */
	public function execute( int $site_id, int $scheduled_order_id ): ActionResult {
		return ActionResult::failure(
			'SNOOZE_MISSING_PARAMS',
			__( 'Snooze requires duration parameters. Use execute_snooze() instead.', 'autoship' )
		);
	}

	/**
	 * Execute snooze with duration parameters.
	 *
	 * @param int    $site_id              The QPilot site ID.
	 * @param int    $scheduled_order_id   The scheduled order ID.
	 * @param string $snooze_until_utc     The UTC date/time to resume (ISO 8601).
	 * @param int    $snooze_duration      The duration value.
	 * @param string $snooze_duration_type The duration type: Days, Weeks, or Months.
	 * @param bool   $is_already_snoozed   Whether the order is currently snoozed.
	 *
	 * @return ActionResult
	 */
	public function execute_snooze(
		int $site_id,
		int $scheduled_order_id,
		string $snooze_until_utc,
		int $snooze_duration,
		string $snooze_duration_type,
		bool $is_already_snoozed = false
	): ActionResult {
		$this->log(
			sprintf(
				'Snooze: Starting execution for order %d on site %d (duration: %d %s, already_snoozed: %s)',
				$scheduled_order_id,
				$site_id,
				$snooze_duration,
				$snooze_duration_type,
				$is_already_snoozed ? 'yes' : 'no'
			)
		);

		try {
			// If already snoozed, activate first to clear existing snooze.
			if ( $is_already_snoozed ) {
				$this->log(
					sprintf(
						'Snooze: Order %d is already snoozed, activating first via SafeActivate',
						$scheduled_order_id
					)
				);

				$activated = $this->repository->safe_activate( $site_id, $scheduled_order_id );

				if ( ! $activated ) {
					$this->log_error(
						sprintf(
							'Snooze: Failed to activate order %d before re-snooze',
							$scheduled_order_id
						)
					);

					return ActionResult::failure(
						'SNOOZE_ACTIVATE_FAILED',
						__( 'Failed to clear existing snooze before applying new duration.', 'autoship' ),
						array( 'scheduled_order_id' => $scheduled_order_id )
					);
				}
			}

			$success = $this->repository->snooze(
				$site_id,
				$scheduled_order_id,
				$snooze_until_utc,
				$snooze_duration,
				$snooze_duration_type
			);

			if ( $success ) {
				$this->log(
					sprintf(
						'Snooze: Successfully snoozed order %d until %s',
						$scheduled_order_id,
						$snooze_until_utc
					)
				);

				return ActionResult::success(
					array(
						'action'              => 'Snooze',
						'scheduled_order_id'  => $scheduled_order_id,
						'snooze_until_utc'    => $snooze_until_utc,
						'snooze_duration'     => $snooze_duration,
						'snooze_duration_type' => $snooze_duration_type,
					)
				);
			}

			$this->log_error(
				sprintf(
					'Snooze: Failed to snooze order %d - repository returned false',
					$scheduled_order_id
				)
			);

			return ActionResult::failure(
				'SNOOZE_FAILED',
				__( 'Failed to snooze subscription.', 'autoship' ),
				array( 'scheduled_order_id' => $scheduled_order_id )
			);
		} catch ( \Exception $e ) {
			$this->log_error(
				sprintf(
					'Snooze: Exception snoozing order %d - %s: %s',
					$scheduled_order_id,
					get_class( $e ),
					$e->getMessage()
				)
			);

			return ActionResult::failure(
				'SNOOZE_EXCEPTION',
				$e->getMessage(),
				array(
					'scheduled_order_id' => $scheduled_order_id,
					'exception'          => get_class( $e ),
				)
			);
		}
	}

	/**
	 * Log an info message.
	 *
	 * @param string $message The message to log.
	 *
	 * @return void
	 */
	private function log( string $message ): void {
		$this->logger->info( 'Autoship QuickLinks', $message );
	}

	/**
	 * Log an error message.
	 *
	 * @param string $message The message to log.
	 *
	 * @return void
	 */
	private function log_error( string $message ): void {
		$this->logger->error( 'Autoship QuickLinks', $message );
	}

	/**
	 * Get action type.
	 *
	 * @return int
	 */
	public function get_action_type(): int {
		return ActionType::SNOOZE;
	}

	/**
	 * Get action name.
	 *
	 * @return string
	 */
	public function get_action_name(): string {
		return 'Snooze';
	}
}
