<?php
/**
 * License Service
 *
 * @package MBMaxCf7Relay
 */

namespace MBMaxCf7Relay\Includes\Services;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Проверка лицензии интеграции на стороне CACR.
 */
class LicenseService {

	/**
	 * Ключ transient для кэша лицензии.
	 */
	const CACHE_KEY = 'mb_max_cf7_license_cache';

	/**
	 * Ключ option со статусом лицензии.
	 */
	const STATUS_OPTION = 'mb_max_cf7_license_status';

	/**
	 * Проверить лицензию.
	 *
	 * @param bool $force Принудительная проверка без кэша.
	 * @return array
	 */
	public function check_license( $force = false ) {
		$options = \MBMaxCf7Relay\Includes\Plugin::get_options();

		if ( '' === $options['integration_key'] ) {
			$result = $this->prepare_status(
				false,
				'no_integration_key',
				'Не указан ключ интеграции из кабинета CACR.',
				array(
					'plan'         => '',
					'valid_from'   => null,
					'valid_until'  => null,
					'integration_id' => 0,
					'integration_site_url' => '',
				)
			);
			$this->persist_status( $result );
			return $result;
		}

		if ( ! $force ) {
			$cached = get_transient( self::CACHE_KEY );
			if ( is_array( $cached ) ) {
				return $cached;
			}
		}

		$url = untrailingslashit( \MBMaxCf7Relay\Includes\Plugin::get_portal_base_url() ) . '/wp-json/mb/v1/max-cf7/license';

		$payload = array(
			'integration_key' => (string) $options['integration_key'],
			'site_url'        => home_url( '/' ),
			'site_domain'     => (string) wp_parse_url( home_url( '/' ), PHP_URL_HOST ),
			'plugin_version'  => MB_MAX_CF7_RELAY_VERSION,
		);

		$response = \MBMaxCf7Relay\Includes\Plugin::post_portal_json( $url, $payload, 12 );

		if ( is_wp_error( $response ) ) {
			$result = $this->prepare_status(
				false,
				'remote_unreachable',
				'Не удалось связаться с CACR: ' . $response->get_error_message(),
				array(
					'http_code' => 0,
				)
			);
			$this->persist_status( $result );
			return $result;
		}

		$code = (int) wp_remote_retrieve_response_code( $response );
		$raw  = wp_remote_retrieve_body( $response );
		$data = json_decode( (string) $raw, true );

		if ( ! is_array( $data ) ) {
			$result = $this->prepare_status(
				false,
				'bad_license_response',
				'Некорректный ответ CACR при проверке лицензии.',
				array(
					'http_code' => $code,
					'raw'       => $raw,
				)
			);
			$this->persist_status( $result );
			return $result;
		}

		if ( $code < 200 || $code >= 300 || empty( $data['success'] ) ) {
			$remote_code    = ! empty( $data['code'] ) ? sanitize_key( (string) $data['code'] ) : 'license_check_failed';
			$remote_message = ! empty( $data['message'] ) ? sanitize_text_field( (string) $data['message'] ) : 'Проверка лицензии на CACR завершилась ошибкой.';

			$result = $this->prepare_status(
				false,
				$remote_code,
				$remote_message,
				array(
					'http_code' => $code,
					'raw'       => $raw,
				)
			);
			$this->persist_status( $result );
			return $result;
		}

		$license_data = isset( $data['data'] ) && is_array( $data['data'] ) ? $data['data'] : array();
		$active       = ! empty( $license_data['active'] );
		$reason       = isset( $license_data['reason'] ) ? sanitize_key( (string) $license_data['reason'] ) : 'unknown';
		$plan         = isset( $license_data['plan'] ) ? sanitize_key( (string) $license_data['plan'] ) : '';
		$valid_from   = isset( $license_data['valid_from'] ) ? sanitize_text_field( (string) $license_data['valid_from'] ) : null;
		$valid_until  = isset( $license_data['valid_until'] ) ? sanitize_text_field( (string) $license_data['valid_until'] ) : null;
		$integration_id = isset( $license_data['integration_id'] ) ? (int) $license_data['integration_id'] : 0;
		$integration_site_url = isset( $license_data['site_url'] ) ? esc_url_raw( (string) $license_data['site_url'] ) : '';

		$message = $active
			? 'Лицензия активна. Отправка заявок разрешена.'
			: 'Лицензия неактивна (' . $reason . '). Отправка заявок заблокирована.';

		$result = $this->prepare_status(
			$active,
			$reason,
			$message,
			array(
				'plan'                 => $plan,
				'valid_from'           => $valid_from,
				'valid_until'          => $valid_until,
				'integration_id'       => $integration_id,
				'integration_site_url' => $integration_site_url,
				'http_code'            => $code,
			)
		);

		$this->persist_status( $result );
		return $result;
	}

	/**
	 * Получить последний статус лицензии из option.
	 *
	 * @return array
	 */
	public function get_last_status() {
		$status = get_option( self::STATUS_OPTION, array() );
		return is_array( $status ) ? $status : array();
	}

	/**
	 * Подготовить структуру статуса.
	 *
	 * @param bool   $active Активна ли лицензия.
	 * @param string $reason Код причины.
	 * @param string $message Текст.
	 * @param array  $extra Доп. данные.
	 * @return array
	 */
	private function prepare_status( $active, $reason, $message, $extra = array() ) {
		return array_merge(
			array(
				'active'     => (bool) $active,
				'reason'     => sanitize_key( (string) $reason ),
				'message'    => sanitize_text_field( (string) $message ),
				'checked_at' => current_time( 'mysql' ),
			),
			$extra
		);
	}

	/**
	 * Сохранить статус в кэш и option.
	 *
	 * @param array $status Статус.
	 * @return void
	 */
	private function persist_status( $status ) {
		$options = \MBMaxCf7Relay\Includes\Plugin::get_options();
		$ttl     = max( 60, (int) $options['license_ttl'] );
		set_transient( self::CACHE_KEY, $status, $ttl );
		update_option( self::STATUS_OPTION, $status );
	}
}
