<?php
/**
 * Sandbox / test mode.
 *
 * @package TextTango
 */

declare( strict_types=1 );

namespace TextTango\Support;

defined( 'ABSPATH' ) || exit;

/**
 * Decides whether sends are real (spec §19).
 *
 * The default is `auto`, which turns sandbox **on** whenever
 * `wp_get_environment_type()` is anything other than `production`. That is the
 * point of the feature: a staging clone of a live shop inherits the real API
 * token along with the database, and without this it would text real customers
 * the moment an order status changed.
 */
final class Sandbox {

	/**
	 * Follow the environment type.
	 */
	public const MODE_AUTO = 'auto';

	/**
	 * Always sandboxed, whatever the environment.
	 */
	public const MODE_ON = 'on';

	/**
	 * Never sandboxed. Every send is real.
	 */
	public const MODE_OFF = 'off';

	/**
	 * Record the message and send nothing.
	 */
	public const BEHAVIOR_LOG_ONLY = 'log_only';

	/**
	 * Really send, but redirect every message to one test number.
	 */
	public const BEHAVIOR_REDIRECT = 'redirect';

	/**
	 * Whether sends are currently sandboxed.
	 */
	public static function is_active(): bool {
		$mode = (string) Settings::get( 'sandbox_mode', self::MODE_AUTO );

		if ( self::MODE_ON === $mode ) {
			$active = true;
		} elseif ( self::MODE_OFF === $mode ) {
			$active = false;
		} else {
			$active = 'production' !== wp_get_environment_type();
		}

		/**
		 * Filters whether sandbox mode is active.
		 *
		 * @param bool   $active Whether sends are sandboxed.
		 * @param string $mode   Configured mode: auto, on, or off.
		 */
		return (bool) apply_filters( 'texttango_sandbox_active', $active, $mode );
	}

	/**
	 * What sandbox does to a send.
	 */
	public static function behavior(): string {
		$behavior = (string) Settings::get( 'sandbox_behavior', self::BEHAVIOR_LOG_ONLY );

		return self::BEHAVIOR_REDIRECT === $behavior ? self::BEHAVIOR_REDIRECT : self::BEHAVIOR_LOG_ONLY;
	}

	/**
	 * The number every message is redirected to, in redirect behavior.
	 */
	public static function test_number(): string {
		return trim( (string) Settings::get( 'sandbox_test_number', '' ) );
	}

	/**
	 * Whether sandbox is on only because of the environment type.
	 *
	 * Used to explain *why* the banner is showing.
	 */
	public static function is_automatic(): bool {
		return self::MODE_AUTO === (string) Settings::get( 'sandbox_mode', self::MODE_AUTO )
			&& 'production' !== wp_get_environment_type();
	}

	/**
	 * Whether redirect behavior is configured but unusable for want of a number.
	 */
	public static function redirect_is_misconfigured(): bool {
		return self::is_active()
			&& self::BEHAVIOR_REDIRECT === self::behavior()
			&& '' === self::test_number();
	}

	/**
	 * A short, human explanation of the current state, for the admin banner.
	 */
	public static function describe(): string {
		if ( ! self::is_active() ) {
			return __( 'Sandbox is off. Messages are really sent and use credits.', 'texttango' );
		}

		if ( self::BEHAVIOR_REDIRECT === self::behavior() ) {
			$number = self::test_number();

			if ( '' === $number ) {
				return __( 'Sandbox is on and set to redirect, but no test number is configured, so messages are only logged.', 'texttango' );
			}

			return sprintf(
				/* translators: %s: the configured test phone number. */
				__( 'Sandbox is on. Every message is really sent, but redirected to %s.', 'texttango' ),
				$number
			);
		}

		return __( 'Sandbox is on. Messages are written to the log and never sent to TextTango.', 'texttango' );
	}
}
