<?php

/**
 * Markdown to Email HTML Parser
 * 
 * PHP port of the TypeScript markdown parser from admin-spa
 * 
 * Supports:
 * - Standard Markdown (headings, bold, italic, lists, links, horizontal rules)
 * - Card blocks with ::: syntax
 * - Button blocks with [button url="..."]Text[/button] syntax
 * - Variables with {variable_name}
 * - Checkmarks (✓) and bullet points (•)
 * - Proper newline handling
 * 
 * @package WooNooW\Core\Notifications
 */

namespace WooNooW\Core\Notifications;

class MarkdownParser
{

	/**
	 * Parse markdown to email HTML
	 * 
	 * @param string $markdown
	 * @return string
	 */
	public static function parse($markdown)
	{
		$html = $markdown;

		// Parse card blocks first (:::card or :::card[type])
		$html = preg_replace_callback(
			'/:::card(?:\[(\w+)\])?\n([\s\S]*?):::/s',
			function ($matches) {
				$type = $matches[1] ?? '';
				$content = trim($matches[2]);
				$parsed_content = self::parse_basics($content);
				return '[card' . ($type ? ' type="' . $type . '"' : '') . "]\n" . $parsed_content . "\n[/card]";
			},
			$html
		);

		// Parse button blocks [button url="..."]Text[/button] - already in correct format
		// Also support legacy [button](url){text} syntax
		$html = preg_replace_callback(
			'/\[button(?:\s+style="(solid|outline)")?\]\((.*?)\)\s*\{([^}]+)\}/',
			function ($matches) {
				$style = $matches[1] ?? '';
				$url = $matches[2];
				$text = $matches[3];
				return '[button url="' . $url . '"' . ($style ? ' style="' . $style . '"' : '') . ']' . $text . '[/button]';
			},
			$html
		);

		// Horizontal rules
		$html = preg_replace('/^---$/m', '<hr>', $html);

		// Parse remaining markdown (outside cards)
		$html = self::parse_basics($html);

		return $html;
	}

	/**
	 * Parse basic markdown syntax
	 * 
	 * @param string $text
	 * @return string
	 */
	private static function parse_basics($text)
	{
		$html = $text;

		// Protect variables from markdown parsing by temporarily replacing them
		$variables = [];
		$var_index = 0;
		$html = preg_replace_callback('/\{([^}]+)\}/', function ($matches) use (&$variables, &$var_index) {
			$placeholder = '<!--VAR' . $var_index . '-->';
			$variables[$placeholder] = $matches[0];
			$var_index++;
			return $placeholder;
		}, $html);

		// Protect existing HTML tags (h1-h6, p) with style attributes from being overwritten
		$html_tags = [];
		$tag_index = 0;
		$html = preg_replace_callback('/<(h[1-6]|p)([^>]*style=[^>]*)>/', function ($matches) use (&$html_tags, &$tag_index) {
			$placeholder = '<!--HTMLTAG' . $tag_index . '-->';
			$html_tags[$placeholder] = $matches[0];
			$tag_index++;
			return $placeholder;
		}, $html);

		// Headings (must be done in order from h4 to h1 to avoid conflicts)
		// Only match markdown syntax (lines starting with #), not existing HTML
		$html = preg_replace('/^#### (.*)$/m', '<h4>$1</h4>', $html);
		$html = preg_replace('/^### (.*)$/m', '<h3>$1</h3>', $html);
		$html = preg_replace('/^## (.*)$/m', '<h2>$1</h2>', $html);
		$html = preg_replace('/^# (.*)$/m', '<h1>$1</h1>', $html);

		// Restore protected HTML tags
		foreach ($html_tags as $placeholder => $original) {
			$html = str_replace($placeholder, $original, $html);
		}

		// Bold (don't match across newlines)
		$html = preg_replace('/\*\*([^\n*]+?)\*\*/', '<strong>$1</strong>', $html);
		$html = preg_replace('/__([^\n_]+?)__/', '<strong>$1</strong>', $html);

		// Italic (don't match across newlines)
		$html = preg_replace('/\*([^\n*]+?)\*/', '<em>$1</em>', $html);
		$html = preg_replace('/_([^\n_]+?)_/', '<em>$1</em>', $html);

		// Horizontal rules
		$html = preg_replace('/^---$/m', '<hr>', $html);

		// Links (but not button syntax)
		$html = preg_replace('/\[(?!button)([^\]]+)\]\(([^)]+)\)/', '<a href="$2">$1</a>', $html);

		// Process lines for paragraphs and lists
		$lines = explode("\n", $html);
		$in_list = false;
		$paragraph_content = '';
		$processed_lines = [];

		$close_paragraph = function () use (&$paragraph_content, &$processed_lines) {
			if ($paragraph_content) {
				$processed_lines[] = '<p>' . $paragraph_content . '</p>';
				$paragraph_content = '';
			}
		};

		foreach ($lines as $line) {
			$trimmed = trim($line);

			// Empty line - close paragraph or list
			if (empty($trimmed)) {
				if ($in_list) {
					$processed_lines[] = '</ul>';
					$in_list = false;
				}
				$close_paragraph();
				$processed_lines[] = '';
				continue;
			}

			// Check if line is a list item
			if (preg_match('/^[\*\-•✓✔]\s/', $trimmed)) {
				$close_paragraph();
				$content = preg_replace('/^[\*\-•✓✔]\s/', '', $trimmed);
				if (!$in_list) {
					$processed_lines[] = '<ul>';
					$in_list = true;
				}
				$processed_lines[] = '<li>' . $content . '</li>';
				continue;
			}

			// Close list if we're in one
			if ($in_list) {
				$processed_lines[] = '</ul>';
				$in_list = false;
			}

			// Block-level HTML tags - don't wrap in paragraph
			if (preg_match('/^<(div|h1|h2|h3|h4|h5|h6|p|ul|ol|li|hr|table|blockquote)/i', $trimmed)) {
				$close_paragraph();
				$processed_lines[] = $line;
				continue;
			}

			// Regular text line - accumulate in paragraph
			if ($paragraph_content) {
				// Add line break before continuation (THIS IS THE KEY FIX!)
				$paragraph_content .= '<br>' . $trimmed;
			} else {
				// Start new paragraph
				$paragraph_content = $trimmed;
			}
		}

		// Close any open tags
		if ($in_list) {
			$processed_lines[] = '</ul>';
		}
		$close_paragraph();

		$html = implode("\n", $processed_lines);

		// Restore variables
		foreach ($variables as $placeholder => $original) {
			$html = str_replace($placeholder, $original, $html);
		}

		return $html;
	}

	/**
	 * Convert newlines to <br> tags for email rendering
	 * 
	 * @param string $html
	 * @return string
	 */
	public static function nl2br_email($html)
	{
		// Don't convert newlines inside HTML tags
		$html = preg_replace('/(?<!>)\n(?!<)/', '<br>', $html);
		return $html;
	}
}
