import { FolkShape } from "./folk-shape";
import { css, html } from "./tags";
import { SpeechDictation } from "./speech-dictation";

const styles = css`
	:host {
		background: var(--rs-bg-surface, #fff);
		color: var(--rs-text-primary, #1e293b);
		border-radius: 8px;
		box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
		min-width: 80px;
		min-height: 40px;
	}

	.header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 8px 12px;
		background: #14b8a6;
		color: white;
		border-radius: 8px 8px 0 0;
		font-size: 12px;
		font-weight: 600;
		cursor: move;
	}

	.header-title {
		display: flex;
		align-items: center;
		gap: 6px;
	}

	.header-actions {
		display: flex;
		gap: 4px;
	}

	.header-actions button {
		background: transparent;
		border: none;
		color: white;
		cursor: pointer;
		padding: 2px 6px;
		border-radius: 4px;
		font-size: 14px;
	}

	.header-actions button:hover {
		background: rgba(255, 255, 255, 0.2);
	}

	.header-actions button.mic-recording {
		animation: micPulse 1.5s infinite;
	}

	@keyframes micPulse {
		0%, 100% { transform: scale(1); }
		50% { transform: scale(1.2); }
	}

	.content {
		padding: 12px;
		height: calc(100% - 36px);
		overflow: auto;
	}

	.editor {
		width: 100%;
		height: 100%;
		border: none;
		outline: none;
		resize: none;
		font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
		font-size: 14px;
		line-height: 1.5;
	}

	.markdown-preview {
		font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
		font-size: 14px;
		line-height: 1.6;
	}

	.markdown-preview h1 {
		font-size: 1.5em;
		margin: 0 0 0.5em;
		color: #14b8a6;
	}

	.markdown-preview h2 {
		font-size: 1.25em;
		margin: 0.5em 0;
		color: #14b8a6;
	}

	.markdown-preview p {
		margin: 0.5em 0;
	}

	.markdown-preview code {
		background: #f1f5f9;
		padding: 2px 4px;
		border-radius: 3px;
		font-family: monospace;
	}

	.markdown-preview pre {
		background: #f1f5f9;
		padding: 12px;
		border-radius: 6px;
		overflow-x: auto;
	}

	.markdown-preview pre code {
		background: none;
		padding: 0;
	}

	.markdown-preview ul,
	.markdown-preview ol {
		margin: 0.5em 0;
		padding-left: 1.5em;
	}

	.markdown-preview blockquote {
		border-left: 3px solid #14b8a6;
		margin: 0.5em 0;
		padding-left: 1em;
		color: #64748b;
	}
`;

declare global {
	interface HTMLElementTagNameMap {
		"folk-markdown": FolkMarkdown;
	}
}

export class FolkMarkdown extends FolkShape {
	static override tagName = "folk-markdown";

	// Merge parent and child styles
	static {
		const sheet = new CSSStyleSheet();
		const parentRules = Array.from(FolkShape.styles.cssRules).map((r) => r.cssText).join("\n");
		const childRules = Array.from(styles.cssRules).map((r) => r.cssText).join("\n");
		sheet.replaceSync(`${parentRules}\n${childRules}`);
		this.styles = sheet;
	}

	#content = "";
	#isEditing = false;

	get content() {
		return this.#content;
	}

	set content(value: string) {
		this.#content = value;
		this.requestUpdate("content");
		this.dispatchEvent(new CustomEvent("content-change", { detail: { content: value } }));
	}

	override createRenderRoot() {
		const root = super.createRenderRoot();

		// Add markdown-specific UI
		const wrapper = document.createElement("div");
		wrapper.innerHTML = html`
			<div class="header">
				<span class="header-title">
					<span>📝</span>
					<span>Markdown</span>
				</span>
				<div class="header-actions">
					<button class="edit-btn" title="Toggle Edit">✏️</button>
					${SpeechDictation.isSupported() ? '<button class="mic-btn" title="Voice dictation">🎤</button>' : ''}
					<button class="close-btn" title="Close">×</button>
				</div>
			</div>
			<div class="content">
				<div class="markdown-preview"></div>
				<textarea class="editor" style="display: none;" placeholder="Write markdown here..."></textarea>
			</div>
		`;

		// Replace the container div (slot's parent) with our wrapper
		const slot = root.querySelector("slot");
		const containerDiv = slot?.parentElement as HTMLElement;
		if (containerDiv) {
			containerDiv.replaceWith(wrapper);
		}

		// Get references to elements
		const preview = wrapper.querySelector(".markdown-preview") as HTMLElement;
		const editor = wrapper.querySelector(".editor") as HTMLTextAreaElement;
		const editBtn = wrapper.querySelector(".edit-btn") as HTMLButtonElement;
		const closeBtn = wrapper.querySelector(".close-btn") as HTMLButtonElement;

		// Helper to enter/exit markdown edit mode
		const enterMarkdownEdit = () => {
			if (this.#isEditing) return;
			this.#isEditing = true;
			editor.style.display = "block";
			preview.style.display = "none";
			editor.value = this.#content;
			editor.focus();
		};

		const exitMarkdownEdit = () => {
			if (!this.#isEditing) return;
			this.#isEditing = false;
			editor.style.display = "none";
			preview.style.display = "block";
			this.content = editor.value;
			preview.innerHTML = this.#renderMarkdown(this.#content);
		};

		// Edit toggle button
		editBtn.addEventListener("click", (e) => {
			e.stopPropagation();
			if (this.#isEditing) {
				exitMarkdownEdit();
			} else {
				enterMarkdownEdit();
			}
		});

		// Click on preview enters edit mode (when shape is focused/editing)
		preview.addEventListener("click", (e) => {
			e.stopPropagation();
			enterMarkdownEdit();
		});

		// When parent shape enters edit mode, also enter markdown edit
		this.addEventListener("edit-enter", () => {
			enterMarkdownEdit();
		});

		// When parent shape exits edit mode, also exit markdown edit
		this.addEventListener("edit-exit", () => {
			exitMarkdownEdit();
		});

		// Close button
		closeBtn.addEventListener("click", (e) => {
			e.stopPropagation();
			this.dispatchEvent(new CustomEvent("close"));
		});

		// Voice dictation
		const micBtn = wrapper.querySelector(".mic-btn") as HTMLButtonElement | null;
		if (micBtn) {
			const dictation = new SpeechDictation({
				onInterim: (text) => {
					// Show interim in editor (will be replaced by final)
				},
				onFinal: (text) => {
					enterMarkdownEdit();
					const pos = editor.selectionStart;
					const before = editor.value.slice(0, pos);
					const after = editor.value.slice(pos);
					const sep = before && !before.endsWith(" ") && !before.endsWith("\n") ? " " : "";
					editor.value = before + sep + text + after;
					this.#content = editor.value;
					editor.selectionStart = editor.selectionEnd = pos + sep.length + text.length;
				},
				onStateChange: (recording) => {
					micBtn.classList.toggle("mic-recording", recording);
					if (recording) enterMarkdownEdit();
				},
				onError: (err) => console.warn("Markdown dictation:", err),
			});

			micBtn.addEventListener("click", (e) => {
				e.stopPropagation();
				dictation.toggle();
			});
		}

		// Editor input
		editor.addEventListener("input", () => {
			this.#content = editor.value;
		});

		editor.addEventListener("blur", () => {
			exitMarkdownEdit();
		});

		// Initial render
		this.#content = this.getAttribute("content") || "# Hello World\n\nStart typing...";
		preview.innerHTML = this.#renderMarkdown(this.#content);

		return root;
	}

	#renderMarkdown(text: string): string {
		// Simple markdown renderer
		return text
			.replace(/^### (.+)$/gm, "<h3>$1</h3>")
			.replace(/^## (.+)$/gm, "<h2>$1</h2>")
			.replace(/^# (.+)$/gm, "<h1>$1</h1>")
			.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>")
			.replace(/\*(.+?)\*/g, "<em>$1</em>")
			.replace(/`(.+?)`/g, "<code>$1</code>")
			.replace(/^- (.+)$/gm, "<li>$1</li>")
			.replace(/(<li>.*<\/li>)/s, "<ul>$1</ul>")
			.replace(/^> (.+)$/gm, "<blockquote>$1</blockquote>")
			.replace(/\n\n/g, "</p><p>")
			.replace(/^(.+)$/gm, (match) => {
				if (
					match.startsWith("<h") ||
					match.startsWith("<ul") ||
					match.startsWith("<li") ||
					match.startsWith("<blockquote")
				) {
					return match;
				}
				return `<p>${match}</p>`;
			});
	}

	static override fromData(data: Record<string, any>): FolkMarkdown {
		const shape = FolkShape.fromData(data) as FolkMarkdown;
		if (data.content) shape.content = data.content;
		return shape;
	}

	toJSON() {
		return {
			type: "folk-markdown",
			id: this.id,
			x: this.x,
			y: this.y,
			width: this.width,
			height: this.height,
			rotation: this.rotation,
			content: this.content,
		};
	}

	override applyData(data: Record<string, any>): void {
		super.applyData(data);
		if ("content" in data && this.content !== data.content) {
			this.content = data.content;
		}
	}
}
