package com.realnet.dlf.Services;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Service;

import com.realnet.dlf.Builders.HtmlBuilder;

@Service
public class HtmlService {

	public static String buildHtml(Object node) {
		if (node instanceof Map) {
			Map<String, Object> map = (Map<String, Object>) node;

			// Handle raw section container

			// Check if a universal TYPE_RENDERER exists for this block
			String type = getString(map, "type", "");
			if (HtmlBuilder.TYPE_RENDERERS.containsKey(type.toLowerCase())) {
				return HtmlBuilder.TYPE_RENDERERS.get(type.toLowerCase()).apply(map);
			}
			// Normal map block
			return renderFromMap(map);
		} else if (node instanceof List) {
			return renderFromList((List<Object>) node);
		} else if (node != null) {
			return node.toString();
		} else {
			return "";
		}
	}

	private static final Map<String, String> TYPE_TAG_MAP = new HashMap<>();
	static {
		TYPE_TAG_MAP.put("navbar", "nav");
		TYPE_TAG_MAP.put("footer", "footer");
		TYPE_TAG_MAP.put("article", "article");
		TYPE_TAG_MAP.put("header", "header");
		TYPE_TAG_MAP.put("logo", "div");
		TYPE_TAG_MAP.put("nav", "nav");
		TYPE_TAG_MAP.put("link", "a");
		TYPE_TAG_MAP.put("button", "button");
		TYPE_TAG_MAP.put("span", "span");
		TYPE_TAG_MAP.put("img", "img"); // already supported as self-closing
		TYPE_TAG_MAP.put("social-icons", "div");
		TYPE_TAG_MAP.put("icon", "div");
		TYPE_TAG_MAP.put("text", "span"); // or "p" depending on your choice

		// add more if needed
	}

	private static String getString(Map<String, Object> map, String key, String defaultValue) {
		Object val = map.get(key);
		return val instanceof String ? (String) val : defaultValue;
	}

	private static String renderFromMap(Map<String, Object> node) {
		StringBuilder html = new StringBuilder();

		// Get tag from 'tag' or fallback to 'type'
		String type = getString(node, "type", "div");
		String rawTag = getString(node, "tag", "");
		String tag = !rawTag.isEmpty() ? rawTag : TYPE_TAG_MAP.getOrDefault(type.toLowerCase(), type);

		html.append("<").append(tag);

		// Add class and id if present
		String className = getString(node, "class", getString(node, "ref", ""));
		String id = getString(node, "id", "");

		if (!className.isEmpty())
			html.append(" class=\"").append(className).append("\"");
		if (!id.isEmpty())
			html.append(" id=\"").append(id).append("\"");

		// Add other attributes (like src, alt for img)
		for (Map.Entry<String, Object> entry : node.entrySet()) {
			String key = entry.getKey();
			Object value = entry.getValue();
			if (!Arrays.asList("type", "tag", "class", "id", "content", "children", "menu", "actions", "buttons")
					.contains(key) && !(value instanceof Map || value instanceof List)) {
				html.append(" ").append(key).append("=\"").append(value).append("\"");
			}
		}

		// Self-closing tag support (like img)
		// Self-closing tag like <img />
		if ("img".equalsIgnoreCase(tag)) {
			html.append(" src=\"").append(getString(node, "src", "")).append("\"");
			html.append(" alt=\"").append(getString(node, "alt", "")).append("\"");
			html.append(" />");
			return html.toString();
		}

		// Content rendering
		if (node.containsKey("content")) {
			html.append(node.get("content"));
		}

		html.append(">");

		// Render inline content if present

		// Special short-circuit rendering for link and button
		if ("link".equalsIgnoreCase(type)) {
			html.append("<a href=\"#\">").append(node.get("content")).append("</a>");
			return html.toString();
		}

		if ("text".equalsIgnoreCase(type)) {
			html.append(getString(node, "content", ""));
			return html.toString();
		}

		if ("logo".equalsIgnoreCase(type)) {
			html.append("<div class=\"").append(className).append("\">").append(getString(node, "content", "Logo"))
					.append("</div>");
			return html.toString();
		}

		if ("icon".equalsIgnoreCase(type)) {
			String label = getString(node, "content", "");
			String emoji = getIconEmoji(label);
			html.append("<div>").append(emoji).append(" ").append(label).append("</div>");
			return html.toString();
		}

		if ("a".equalsIgnoreCase(type)) {
			String href = getString(node, "href", "#");
			html.append("<a href=\"").append(href).append("\">").append(getString(node, "content", "")).append("</a>");
			return html.toString();
		}

		if ("button".equalsIgnoreCase(type)) {
			html.append("<button class=\"").append(className).append("\">").append(node.get("content"))
					.append("</button>");
			return html.toString();
		}

		if (node.containsKey("content")) {
			html.append(node.get("content"));
		}

		// Handle structured known patterns
		if (node.containsKey("logo")) {
			html.append("<div class=\"logo-1\">").append(node.get("logo")).append("</div>");
		}

		if (node.containsKey("heading")) {
			html.append("<h1>").append(node.get("heading")).append("</h1>");
		}

		if (node.containsKey("subheading")) {
			html.append("<p>").append(node.get("subheading")).append("</p>");
		}

		if (node.containsKey("text")) {
			html.append("<p>").append(node.get("text")).append("</p>");
		}

		if (node.containsKey("menu")) {
			html.append(renderMenu(node.get("menu")));
		}

		if (node.containsKey("actions")) {
			html.append(renderActions(node.get("actions")));
		}

		if (node.containsKey("buttons")) {
			html.append(renderButtons(node.get("buttons")));
		}

		if (node.containsKey("columns")) {
			html.append(renderColumns(node.get("columns")));
		}

		if (node.containsKey("children")) {
			html.append(buildHtml(node.get("children")));
		}

		html.append("</").append(tag).append(">");
		return html.toString();
	}

	private static String renderFromList(List<Object> list) {
		StringBuilder html = new StringBuilder();
		for (Object item : list) {
			html.append(buildHtml(item));
		}
		return html.toString();
	}

	private static String renderButtons(Object obj) {
		StringBuilder html = new StringBuilder();

		// Case 1: Simple list of string labels
		if (obj instanceof List) {
			List<Object> btns = (List<Object>) obj;
			html.append("<div class=\"cta-buttons\">");
			for (Object item : btns) {
				if (item instanceof String) {
					html.append("<button>").append(item).append("</button>");
				} else if (item instanceof Map) {
					html.append(renderSingleButton((Map<String, Object>) item));
				}
			}
			html.append("</div>");
		}

		// Case 2: Object with "items" list and optional class
		else if (obj instanceof Map) {
			Map<String, Object> btnMap = (Map<String, Object>) obj;
			List<Object> items = (List<Object>) btnMap.get("items");
			String btnClass = getString(btnMap, "class", "cta-buttons");

			html.append("<div class=\"").append(btnClass).append("\">");
			if (items != null) {
				for (Object btn : items) {
					if (btn instanceof String) {
						html.append("<button>").append(btn).append("</button>");
					} else if (btn instanceof Map) {
						html.append(renderSingleButton((Map<String, Object>) btn));
					}
				}
			}
			html.append("</div>");
		}

		return html.toString();
	}

	private static String renderSingleButton(Map<String, Object> btn) {
		String label = getString(btn, "label", "Button");
		String href = getString(btn, "action", "#");
		String style = getString(btn, "style", "filled");
		String bg = getString(btn, "backgroundColor", style.equals("outlined") ? "white" : "black");
		String color = getString(btn, "textColor", style.equals("outlined") ? "black" : "white");
		String border = style.equals("outlined") ? "1px solid " + getString(btn, "borderColor", "#000") : "none";

		return new StringBuilder().append("<a href=\"").append(href).append("\" style=\"").append("background:")
				.append(bg).append("; ").append("color:").append(color).append("; ")
				.append("padding:10px 20px; border-radius:4px; text-decoration:none; ").append("border:").append(border)
				.append("; margin-right:10px; display:inline-block;\">").append(label).append("</a>").toString();
	}

	private static String renderColumns(Object obj) {
		StringBuilder html = new StringBuilder();
		html.append("<div class=\"blog-layout\">");

		List<Map<String, Object>> columns = (List<Map<String, Object>>) obj;
		for (Map<String, Object> col : columns) {
			String type = getString(col, "type", "");
			if ("main".equalsIgnoreCase(type)) {
				html.append("<main class=\"main-column\">");
				if (col.containsKey("contentBlocks")) {
					List<Map<String, Object>> blocks = (List<Map<String, Object>>) col.get("contentBlocks");
					for (Map<String, Object> block : blocks) {
						html.append("<div class=\"content-block\">").append("<h2>")
								.append(getString(block, "heading", "")).append("</h2>").append("<p>")
								.append(getString(block, "text", "")).append("</p>").append("</div>");
					}
				}
				html.append("</main>");
			} else if ("sidebar".equalsIgnoreCase(type)) {
				html.append("<aside class=\"sidebar-column\">");
				List<String> widgets = (List<String>) col.get("widgets");
				for (String widget : widgets) {
					html.append("<div class=\"widget\">").append(getWidgetIcon(widget)).append(" ").append(widget)
							.append("</div>");
				}
				html.append("</aside>");
			}
		}

		html.append("</div>");
		return html.toString();
	}

	private static String renderMenu(Object obj) {
		StringBuilder html = new StringBuilder("<ul class=\"nav-1\">");

		List<Object> menu = (List<Object>) obj;
		for (Object item : menu) {
			if (item instanceof String) {
				html.append("<li><a href=\"#\">").append(item).append("</a></li>");
			} else if (item instanceof Map) {
				Map<String, Object> dropdownItem = (Map<String, Object>) item;
				html.append("<li class=\"dropdown\">");
				html.append("<a href=\"#\">").append(dropdownItem.get("title")).append("</a>");

				if (dropdownItem.containsKey("dropdown")) {
					html.append(renderDropdown(dropdownItem.get("dropdown")));
				}
				html.append("</li>");
			}
		}

		html.append("</ul>");
		return html.toString();
	}

	private static String renderDropdown(Object obj) {
		StringBuilder html = new StringBuilder("<div class=\"dropdown-content\"><div class=\"dropdown-columns\">");

		Map<String, Object> dropdown = (Map<String, Object>) obj;
		List<Map<String, Object>> columns = (List<Map<String, Object>>) dropdown.get("columns");

		for (Map<String, Object> column : columns) {
			html.append("<div class=\"column\">");
			html.append("<h4>").append(column.get("title")).append("</h4>");
			html.append("<ul>");

			if (column.containsKey("items")) {
				List<Map<String, Object>> items = (List<Map<String, Object>>) column.get("items");
				for (Map<String, Object> item : items) {
					html.append("<li><span>").append(item.get("icon")).append("</span>").append("<strong>")
							.append(item.get("title")).append("</strong>").append("<p>").append(item.get("description"))
							.append("</p>").append("</li>");
				}
			} else if (column.containsKey("blogs")) {
				List<Map<String, Object>> blogs = (List<Map<String, Object>>) column.get("blogs");
				for (Map<String, Object> blog : blogs) {
					html.append("<li><strong>").append(blog.get("title")).append("</strong>").append("<p>")
							.append(blog.get("description")).append("</p>").append("<a href=\"#\">")
							.append(blog.get("cta")).append("</a></li>");
				}
				if (column.containsKey("footerLink")) {
					html.append("<div class=\"footer-link\"><a href=\"#\">").append(column.get("footerLink"))
							.append("</a></div>");
				}
			}

			html.append("</ul></div>");
		}

		html.append("</div></div>");
		return html.toString();
	}

	private static String renderActions(Object obj) {
		StringBuilder html = new StringBuilder("<div class=\"navbar-actions\">");

		List<Map<String, Object>> actions = (List<Map<String, Object>>) obj;
		for (Map<String, Object> action : actions) {
			String label = getString(action, "label", "Button");
			String variant = getString(action, "variant", "");
			String btnClass = "join-btn";
			if (!variant.isEmpty()) {
				btnClass += " " + variant;
			}
			html.append("<button class=\"").append(btnClass).append("\">").append(label).append("</button>");
		}

		html.append("</div>");
		return html.toString();
	}

	private static String renderNavbarBlock(Map<String, Object> nav) {
		StringBuilder html = new StringBuilder();

		// Inline styles
		StringBuilder style = new StringBuilder();
		if (nav.containsKey("style")) {
			Map<String, Object> styleMap = (Map<String, Object>) nav.get("style");
			for (Map.Entry<String, Object> s : styleMap.entrySet()) {
				appendStyle(style, s.getKey(), s.getValue());
			}
		}

		html.append("<nav style=\"").append(style).append("\">");

		// Logo
		if (nav.containsKey("Logo")) {
			Map<String, Object> logo = (Map<String, Object>) nav.get("Logo");
			String type = getString(logo, "type", "text");
			if ("image".equalsIgnoreCase(type)) {
				html.append("<img src=\"").append(logo.get("src")).append("\" alt=\"").append(logo.get("alt"))
						.append("\" width=\"").append(logo.get("width")).append("\" height=\"")
						.append(logo.get("height")).append("\" />");
			} else if ("text".equalsIgnoreCase(type)) {
				html.append("<div style=\"font-weight:").append(getString(logo, "fontWeight", "normal"))
						.append("; font-size:").append(getString(logo, "fontSize", "16px")).append(";\">")
						.append(getString(logo, "text", "Logo")).append("</div>");
			}
		}

		// Links
		if (nav.containsKey("Links")) {
			List<Map<String, Object>> links = (List<Map<String, Object>>) nav.get("Links");
			html.append("<ul style=\"display:flex; gap:20px; list-style:none\">");
			for (Map<String, Object> link : links) {
				html.append("<li><a href=\"").append(link.get("href")).append("\">")
						.append(getString(link, "label", "")).append("</a></li>");
			}
			html.append("</ul>");
		}

		// Buttons
		if (nav.containsKey("Buttons")) {
			List<Map<String, Object>> buttons = (List<Map<String, Object>>) nav.get("Buttons");
			for (Map<String, Object> btn : buttons) {
				String bg = getString(btn, "background", "white");
				String color = getString(btn, "textColor", "black");
				String border = getString(btn, "border", "none");

				html.append("<a href=\"").append(getString(btn, "action", "#")).append("\" style=\"")
						.append("background:").append(bg).append(";").append("color:").append(color).append(";")
						.append("padding:8px 16px;").append("border:").append(border).append(";")
						.append("text-decoration:none; margin-left:10px;").append("\">")
						.append(getString(btn, "label", "Button")).append("</a>");
			}
		}

		html.append("</nav>");
		return html.toString();
	}

	private static void appendStyle(StringBuilder style, String key, Object value) {
		if (value != null) {
			style.append(key).append(":").append(value).append("; ");
		}
	}

	private static String getIconEmoji(String label) {
		label = label.toLowerCase();
		if (label.contains("facebook"))
			return "📘";
		if (label.contains("instagram"))
			return "📷";
		if (label.equals("x"))
			return "𝕏";
		if (label.contains("search"))
			return "🔍";
		if (label.contains("profile"))
			return "👤";
		if (label.contains("twitter"))
			return "🐦";

		if (label.contains("linkedin"))
			return "🔗";
		if (label.contains("youtube"))
			return "▶️";
		return "📦";
	}

	private static String getWidgetIcon(String widget) {
		widget = widget.toLowerCase();
		if (widget.contains("search"))
			return "🔍";
		if (widget.contains("recent"))
			return "📝";
		if (widget.contains("newsletter"))
			return "📬";
		return "📦";
	}

}
