<?php
/**
 * Lead Magnet Validator
 *
 * Validates and sanitizes custom HTML/CSS for lead magnet templates
 * Provides security through wp_kses and pattern-based filtering
 *
 * @package Dobare
 * @subpackage Lead_Magnet
 */

namespace Dobare\Lead_Magnet;

class Dobare_Lead_Magnet_Validator
{

	/**
	 * Get allowed HTML tags and attributes for lead magnet customization
	 * Blocks dangerous tags: script, iframe, object, embed
	 *
	 * @return array
	 */
	private static function get_allowed_html(): array
	{
		return array(
			'div'      => array('id' => true, 'class' => true, 'style' => true),
			'span'     => array('id' => true, 'class' => true, 'style' => true),
			'p'        => array('id' => true, 'class' => true, 'style' => true),
			'button'   => array('id' => true, 'class' => true, 'style' => true, 'type' => true),
			'a'        => array('href' => true, 'id' => true, 'class' => true, 'style' => true, 'target' => true),
			'b'        => array('class' => true, 'style' => true),
			'strong'   => array('class' => true, 'style' => true),
			'i'        => array('class' => true, 'style' => true),
			'em'       => array('class' => true, 'style' => true),
			'ul'       => array('class' => true, 'style' => true),
			'li'       => array('class' => true, 'style' => true),
			'svg'      => array(
				'width'   => true,
				'height'  => true,
				'viewBox' => true,
				'fill'    => true,
				'xmlns'   => true,
				'class'   => true,
			),
			'g'        => array('id' => true, 'class' => true),
			'path'     => array(
				'id'               => true,
				'd'                => true,
				'stroke'           => true,
				'stroke-width'     => true,
				'stroke-linecap'   => true,
				'stroke-linejoin'  => true,
				'fill'             => true,
				'class'            => true,
			),
			'template' => array('id' => true),
		);
	}

	/**
	 * Get list of blocked tags (explicitly removed)
	 *
	 * @return array
	 */
	private static function get_blocked_tags(): array
	{
		return array('script', 'iframe', 'object', 'embed', 'link', 'meta', 'base', 'form', 'input');
	}

	/**
	 * Sanitize HTML using wp_kses
	 * Removes dangerous tags and attributes
	 *
	 * @param string $html
	 * @return string
	 */
	public static function sanitize_html(string $html): string
	{
		// First, remove ALL inline event handlers (on* attributes)
		$html = preg_replace('/\s+on\w+\s*=\s*["\'][^"\']*["\']/i', '', $html);
		$html = preg_replace('/\s+on\w+\s*=\s*[^>\s]+/i', '', $html);

		// Explicitly remove blocked tags
		foreach (self::get_blocked_tags() as $tag) {
			$html = preg_replace('/<' . $tag . '[^>]*?>.*?<\/' . $tag . '>/is', '', $html);
			$html = preg_replace('/<' . $tag . '[^>]*?\/?>/is', '', $html);
		}

		// Apply wp_kses with allowed tags
		$sanitized = wp_kses($html, self::get_allowed_html());

		return $sanitized;
	}

	/**
	 * Sanitize CSS - basic validation and dangerous pattern removal
	 * Removes scripts hidden in CSS, expressions, and behaviors
	 *
	 * @param string $css
	 * @return string
	 */
	public static function sanitize_css(string $css): string
	{
		// Remove script blocks hidden in CSS
		$css = preg_replace('/<script[^>]*>.*?<\/script>/is', '', $css);

		// Strip dangerous CSS expressions (IE specific)
		$css = preg_replace('/expression\s*\(/i', '', $css);


		// Remove javascript: pseudo-protocol
		$css = str_replace('javascript:', '', $css);

		// Remove import statements (prevent external resource loading)
		$css = preg_replace('/@import[^;]*;/i', '', $css);

		// Block data URIs that could contain HTML/JavaScript
		$css = preg_replace('/url\s*\(\s*["\']?data:text\/html[^)]*\)/i', '', $css);
		$css = preg_replace('/url\s*\(\s*["\']?data:application\/[^)]*\)/i', '', $css);

		// Strip any HTML tags that might have slipped through
		$css = strip_tags($css);

		return $css;
	}

	/**
	 * Validate custom HTML and CSS content before saving
	 * Checks for required variables, size limits, and dangerous patterns
	 *
	 * @param string $html
	 * @param string $css
	 * @return array ['valid' => bool, 'errors' => string[]]
	 */
	public static function validate_custom_content(string $html, string $css): array
	{
		$errors = array();

		// HTML validation
		if (!empty($html)) {
			// Check for blocked tags
			foreach (self::get_blocked_tags() as $tag) {
				if (stripos($html, '<' . $tag) !== false) {
					$errors[] = sprintf(
						'HTML شامل تگ غیرمجاز است: <%s>. تگ‌های غیرمجاز: %s',
						$tag,
						implode(', ', self::get_blocked_tags())
					);
				}
			}

			// Check for required variable placeholders
			$required_vars = array(
				'id="business-name"',
				'id="dobare-gift-credit-amount"',
				'id="dobare-currency-word"',
			);
			foreach ($required_vars as $var) {
				if (stripos($html, $var) === false) {
					$errors[] = sprintf('HTML باید شامل المان با %s باشد', str_replace('id="', '#', str_replace('"', '', $var)));
				}
			}

			// Size check (prevent abuse)
			if (strlen($html) > 100000) { // 100KB limit
				$errors[] = 'حجم HTML بیش از حد مجاز است (حداکثر 100KB)';
			}

			// Check for inline event handlers (security concern)
			$dangerous_patterns = array(
				'onerror=',
				'onload=',
				'onmouseover=',
				'onfocus=',
			);
			foreach ($dangerous_patterns as $pattern) {
				if (stripos($html, $pattern) !== false) {
					$errors[] = sprintf('HTML شامل کد خطرناک است: %s', $pattern);
				}
			}
		}

		// CSS validation
		if (!empty($css)) {
			$sanitized = self::sanitize_css($css);

			// Check if sanitization removed content (indicates dangerous patterns)
			if ($sanitized !== $css && strlen($sanitized) < strlen($css) * 0.9) {
				$errors[] = 'CSS شامل محتوای خطرناک است که حذف شده است';
			}

			// Size check
			if (strlen($css) > 50000) { // 50KB limit
				$errors[] = 'حجم CSS بیش از حد مجاز است (حداکثر 50KB)';
			}

			// Check for dangerous CSS patterns
			if (preg_match('/expression\s*\(/i', $css)) {
				$errors[] = 'CSS شامل expression() غیرمجاز است';
			}
			if (stripos($css, 'javascript:') !== false) {
				$errors[] = 'CSS شامل javascript: غیرمجاز است';
			}
		}

		return array(
			'valid'  => empty($errors),
			'errors' => $errors,
		);
	}

	/**
	 * Render preview with actual API data
	 * Generates a complete HTML document with JavaScript for full functionality
	 *
	 * @param string $html
	 * @param string $css
	 * @param string $device 'desktop' or 'mobile'
	 * @return array ['html' => string, 'position' => string]
	 */
	public static function render_preview(string $html, string $css, string $device = 'desktop'): array
	{
		// Get REAL data from Dobare API
		$lead_magnet_data = Dobare_Lead_Magnet_Service::get_lead_magnet_data();

		$preview_data = array(
			'business_name' => $lead_magnet_data['business_title'] ?: get_option('blogname', 'فروشگاه'),
			'credit_amount' => $lead_magnet_data['credit_amount']
				? number_format($lead_magnet_data['credit_amount'])
				: '50,000',
			'currency_word' => \Dobare\Utils\Dobare_Utils::get_currency_word(),
			'position'      => $lead_magnet_data['position'] ?: 'L',
		);

		// Replace variable placeholders with actual data
		$rendered_html = $html;

		// Replace business name
		$rendered_html = preg_replace(
			'/(<[^>]+id=["\']business-name["\'][^>]*>)([^<]*)(<\/[^>]+>)/i',
			'$1' . esc_html($preview_data['business_name']) . '$3',
			$rendered_html
		);

		// Replace credit amount
		$rendered_html = preg_replace(
			'/(<[^>]+id=["\']dobare-gift-credit-amount["\'][^>]*>)([^<]*)(<\/[^>]+>)/i',
			'$1' . esc_html($preview_data['credit_amount']) . '$3',
			$rendered_html
		);

		// Replace currency word
		$rendered_html = preg_replace(
			'/(<[^>]+id=["\']dobare-currency-word["\'][^>]*>)([^<]*)(<\/[^>]+>)/i',
			'$1' . esc_html($preview_data['currency_word']) . '$3',
			$rendered_html
		);

		// Build complete HTML document
		$viewport = $device === 'mobile'
			? 'width=device-width,height=device-height,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no'
			: 'width=device-width,initial-scale=1';

		// Get fonts and loading CSS URLs for preview
		$fonts_url = plugin_dir_url(DOBARE_MAIN_PLUGIN_FILE) . 'build/assets/lead-magnet/styles/fonts.css';
		$loading_url = plugin_dir_url(DOBARE_MAIN_PLUGIN_FILE) . 'build/assets/lead-magnet/styles/loading.css';

		// Get preview JavaScript
		$js = self::get_preview_javascript();

		$preview_html = sprintf(
			'<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="%s">
	<link rel="stylesheet" href="%s">
	<link rel="stylesheet" href="%s">
	<style>%s</style>
</head>
<body>
	<div id="dobare-lead-magnet-wrraper">%s</div>
	<script>%s</script>
</body>
</html>',
			esc_attr($viewport),
			esc_url($fonts_url),
			esc_url($loading_url),
			$css, // CSS already sanitized via sanitize_css()
			$rendered_html, // Already sanitized via wp_kses
			$js
		);

		return array(
			'html'     => $preview_html,
			'position' => $preview_data['position'],
		);
	}

	/**
	 * Get JavaScript for preview functionality
	 * Includes timer countdown, close button, and height communication
	 *
	 * @return string JavaScript code
	 */
	private static function get_preview_javascript(): string
	{
		return <<<'JS'
// Timer variables
let timerElement = null;
let progressTimer = null;
let timeLeft = 60;
let totalTime = 60;
let countdownInterval = null;

// Helpers
const toPersianNumber = (number) => {
    return number.toString().replace(/\d/g, (digit) => '۰۱۲۳۴۵۶۷۸۹'[digit]);
};

// Close preview - sends message to parent
window.removeIframeFromDom = function() {
    window.parent.postMessage({ key: 'CLOSE_PREVIEW' }, '*');
};

// CTA button - does nothing in preview
window.goToLoginPage = function() {
    // Intentionally disabled for preview
};

// Height communication to parent
const sendHeightToParent = () => {
    const wrapper = document.getElementById('dobare-lead-magnet-wrraper');
    if (!wrapper) return;
    const height = Math.max(wrapper.scrollHeight, 180);
    window.parent.postMessage({ key: 'SET_PREVIEW_HEIGHT', height: height }, '*');
};

// Timer countdown
const startCountdown = () => {
    timerElement = document.getElementById('dobare-timer');
    progressTimer = document.getElementById('dobare-progress-timer');

    if (!timerElement || !progressTimer) return;

    countdownInterval = setInterval(() => {
        if (timeLeft < 0) {
            clearInterval(countdownInterval);
            window.removeIframeFromDom();
            return;
        }

        const minutes = Math.floor(timeLeft / 60);
        const seconds = timeLeft % 60;
        const formattedMinutes = String(minutes).padStart(2, '0');
        const formattedSeconds = String(seconds).padStart(2, '0');

        timerElement.textContent = `${toPersianNumber(formattedMinutes)}:${toPersianNumber(formattedSeconds)}`;

        // Note: We don't apply inline timer background styles here
        // because this is for custom lead magnets that have their own CSS styling

        timeLeft--;
    }, 1000);
};

// Attach event listeners to buttons
const attachButtonListeners = () => {
    const closeBtn = document.getElementById('dobare-close-btn') || document.querySelector('.dobare-close-button');
    if (closeBtn) {
        closeBtn.addEventListener('click', window.removeIframeFromDom);
    }

    const loginBtn = document.getElementById('dobare-login-btn') || document.querySelector('.dobare-submit-button');
    if (loginBtn) {
        loginBtn.addEventListener('click', window.goToLoginPage);
    }
};

// Initialize on load
window.addEventListener('load', () => {
    sendHeightToParent();
    startCountdown();
    attachButtonListeners();

    // Setup resize observer
    const wrapper = document.getElementById('dobare-lead-magnet-wrraper');
    if (wrapper && window.ResizeObserver) {
        const observer = new ResizeObserver(() => sendHeightToParent());
        observer.observe(wrapper);
    }
});
JS;
	}

	/**
	 * Get list of required element IDs for variable replacement
	 *
	 * @return array
	 */
	public static function get_required_ids(): array
	{
		return array(
			'business-name'              => 'نام کسب‌وکار',
			'dobare-gift-credit-amount'  => 'مبلغ اعتبار هدیه',
			'dobare-currency-word'       => 'واحد پولی (تومان/ریال)',
		);
	}
}
