<?php
/**
 * Public unsubscribe: pretty front-end URL + legacy REST endpoint.
 *
 * @package SuiteMkt3k
 */

namespace SuiteMkt3k\Modules\Subscribers;

use SuiteMkt3k\Modules\Settings\Settings_Manager;
use SuiteMkt3k\Security\Rate_Limiter;
use SuiteMkt3k\Utils\I18n;
use SuiteMkt3k\Utils\Logger;

defined( 'ABSPATH' ) || exit;

final class Unsubscribe_Handler {

	public static function register(): void {
		add_action( 'init', array( __CLASS__, 'register_rewrites' ) );
		add_filter( 'query_vars', array( __CLASS__, 'register_query_vars' ) );
		add_action( 'template_redirect', array( __CLASS__, 'maybe_render_page' ) );
		add_action( 'rest_api_init', array( __CLASS__, 'register_route' ) );
	}

	public static function register_query_vars( array $vars ): array {
		$vars[] = 'wmk_unsub';
		return $vars;
	}

	public static function register_rewrites(): void {
		add_rewrite_tag( '%wmk_unsub%', '([a-f0-9]{64})' );
		add_rewrite_rule( '^b/([a-f0-9]{64})/?$', 'index.php?wmk_unsub=$matches[1]', 'top' );
		add_rewrite_rule( '^baja/([a-f0-9]{64})/?$', 'index.php?wmk_unsub=$matches[1]', 'top' );

		$stored = get_option( 'suitemkt3k_rewrite_version', '' );
		if ( $stored !== SUITEMKT3K_VERSION ) {
			flush_rewrite_rules( false );
			update_option( 'suitemkt3k_rewrite_version', SUITEMKT3K_VERSION, false );
		}
	}

	public static function register_route(): void {
		register_rest_route(
			SUITEMKT3K_REST_NAMESPACE,
			'/public/unsubscribe',
			array(
				'methods'             => array( 'GET', 'POST' ),
				'permission_callback' => '__return_true',
				'callback'            => static function ( \WP_REST_Request $request ) {
					$token = (string) $request->get_param( 'token' );
					$html  = self::process_and_render( $token );
					$response = new \WP_REST_Response( $html, 200 );
					$response->header( 'Content-Type', 'text/html; charset=utf-8' );
					return $response;
				},
				'args'                => array(
					'token' => array(
						'required'          => true,
						'sanitize_callback' => array( __CLASS__, 'sanitize_token' ),
						'validate_callback' => array( __CLASS__, 'is_valid_token' ),
					),
				),
			)
		);
	}

	public static function maybe_render_page(): void {
		$token = (string) get_query_var( 'wmk_unsub' );
		if ( '' === $token ) {
			$request_uri = \SuiteMkt3k\Utils\Sanitizer::server( 'REQUEST_URI', 'text' );
			$path        = wp_parse_url( $request_uri, PHP_URL_PATH );
			$path        = is_string( $path ) ? trim( $path, '/' ) : '';
			if ( preg_match( '#(?:^|/)(?:b|baja)/([a-f0-9]{64})/?$#', $path, $matches ) ) {
				$token = self::sanitize_token( $matches[1] );
			}
		}
		if ( '' === $token ) {
			$legacy_token = \SuiteMkt3k\Utils\Sanitizer::get( 'wmk_baja', 'text' );
			if ( '' !== $legacy_token ) {
				$token = self::sanitize_token( $legacy_token );
			}
		}
		if ( ! self::is_valid_token( $token ) ) {
			return;
		}
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		echo self::process_and_render( $token );
		exit;
	}

	public static function sanitize_token( $value ): string {
		return preg_replace( '/[^a-f0-9]/', '', strtolower( (string) $value ) );
	}

	public static function is_valid_token( $value ): bool {
		return is_string( $value ) && strlen( $value ) === 64;
	}

	private static function process_and_render( string $token ): string {
		I18n::ensure_textdomain();

		$identifier = hash( 'sha256', Rate_Limiter::visitor_id() . '|unsubscribe' );
		if ( ! Rate_Limiter::check( 'unsubscribe', $identifier, 20, 60 ) ) {
			return self::render_html(
				__( 'Too many attempts. Please try again later.', 'suitemkt3k' ),
				false
			);
		}

		$ok = Subscriber_Manager::unsubscribe_by_token( $token );
		Logger::info( 'unsubscribe', $ok ? 'ok' : 'invalid_or_already' );

		if ( $ok ) {
			$message = self::success_message();
		} else {
			$message = self::already_processed_message();
		}

		return self::render_html( $message, $ok );
	}

	public static function default_success_message(): string {
		$company = (array) Settings_Manager::get( 'company', '', array() );
		$name    = (string) ( $company['name'] ?: get_bloginfo( 'name' ) );

		return sprintf(
			/* translators: %s: company or site name */
			__( 'Thank you for your trust. We are sorry to see you go. We hope to welcome you again soon at %s.', 'suitemkt3k' ),
			$name
		);
	}

	public static function default_already_message(): string {
		return __( 'Your unsubscribe request has already been processed.', 'suitemkt3k' );
	}

	private static function success_message(): string {
		$custom = trim( (string) Settings_Manager::get( 'subscribers', 'unsubscribe_success', '' ) );
		if ( '' === $custom ) {
			return self::default_success_message();
		}
		$company = (array) Settings_Manager::get( 'company', '', array() );
		$name    = (string) ( $company['name'] ?: get_bloginfo( 'name' ) );

		return str_replace( '%s', $name, $custom );
	}

	private static function already_processed_message(): string {
		$custom = trim( (string) Settings_Manager::get( 'subscribers', 'unsubscribe_already', '' ) );
		return '' !== $custom ? $custom : self::default_already_message();
	}

	private static function enqueue_page_styles(): void {
		if ( ! wp_style_is( 'suitemkt3k-unsubscribe', 'registered' ) ) {
			wp_register_style(
				'suitemkt3k-unsubscribe',
				SUITEMKT3K_URL . 'assets/frontend/css/unsubscribe-page.css',
				array(),
				SUITEMKT3K_VERSION
			);
		}
		wp_enqueue_style( 'suitemkt3k-unsubscribe' );
	}

	/**
	 * @return string Markup for enqueued styles (link tags).
	 */
	private static function styles_markup(): string {
		self::enqueue_page_styles();
		ob_start();
		wp_print_styles( array( 'suitemkt3k-unsubscribe' ) );
		return (string) ob_get_clean();
	}

	private static function render_html( string $message, bool $success ): string {
		$company = (array) Settings_Manager::get( 'company', '', array() );
		$brand   = (string) ( $company['name'] ?: get_bloginfo( 'name' ) );
		$accent  = '#2ab2e5';
		$icon    = $success ? '&#10003;' : '&#8505;';
		$styles  = self::styles_markup();

		return '<!doctype html><html lang="' . esc_attr( get_bloginfo( 'language' ) ) . '"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex,nofollow"><title>' . esc_html__( 'Unsubscribe', 'suitemkt3k' ) . '</title>' . $styles . '</head><body style="--wmk-accent:' . esc_attr( $accent ) . '"><div class="box"><div class="icon">' . $icon . '</div><h1>' . esc_html( $brand ) . '</h1><p>' . esc_html( $message ) . '</p></div></body></html>';
	}
}
