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: 300px;
		min-height: 400px;
	}

	.header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 8px 12px;
		background: #f97316;
		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);
	}

	.chat-container {
		display: flex;
		flex-direction: column;
		height: calc(100% - 36px);
	}

	.messages {
		flex: 1;
		overflow-y: auto;
		padding: 12px;
		display: flex;
		flex-direction: column;
		gap: 8px;
	}

	.message {
		background: var(--rs-bg-surface-sunken, #f1f5f9);
		color: var(--rs-text-primary, #1e293b);
		border-radius: 8px;
		padding: 8px 12px;
		max-width: 85%;
	}

	.message.own {
		background: #f97316;
		color: white;
		align-self: flex-end;
	}

	.message-header {
		display: flex;
		justify-content: space-between;
		font-size: 11px;
		opacity: 0.7;
		margin-bottom: 4px;
	}

	.message-content {
		font-size: 14px;
		line-height: 1.4;
	}

	.input-container {
		display: flex;
		gap: 8px;
		padding: 12px;
		border-top: 1px solid var(--rs-border, #e2e8f0);
	}

	.message-input {
		flex: 1;
		border: 1px solid var(--rs-input-border, #e2e8f0);
		border-radius: 6px;
		padding: 8px 12px;
		font-size: 14px;
		outline: none;
		background: var(--rs-input-bg, #fff);
		color: var(--rs-input-text, inherit);
	}

	.message-input:focus {
		border-color: #f97316;
	}

	.send-btn {
		background: #f97316;
		color: white;
		border: none;
		border-radius: 6px;
		padding: 8px 16px;
		cursor: pointer;
		font-weight: 500;
	}

	.send-btn:hover {
		background: #ea580c;
	}

	.mic-btn {
		background: transparent;
		border: 1px solid var(--rs-border, #e2e8f0);
		border-radius: 6px;
		padding: 8px 10px;
		cursor: pointer;
		font-size: 14px;
		transition: all 0.2s;
	}

	.mic-btn:hover {
		border-color: #f97316;
	}

	.mic-btn.recording {
		border-color: #ef4444;
		animation: micPulse 1.5s infinite;
	}

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

	.username-prompt {
		padding: 12px;
		text-align: center;
	}

	.username-input {
		border: 1px solid #e2e8f0;
		border-radius: 6px;
		padding: 8px 12px;
		font-size: 14px;
		outline: none;
		margin-bottom: 8px;
		width: 100%;
		box-sizing: border-box;
	}

	.username-btn {
		background: #f97316;
		color: white;
		border: none;
		border-radius: 6px;
		padding: 8px 16px;
		cursor: pointer;
		font-weight: 500;
	}
`;

interface ChatMessage {
	id: string;
	userName: string;
	content: string;
	timestamp: number;
}

declare global {
	interface HTMLElementTagNameMap {
		"folk-chat": FolkChat;
	}
}

export class FolkChat extends FolkShape {
	static override tagName = "folk-chat";

	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;
	}

	#roomId = "default-room";
	#userName = "";
	#messages: ChatMessage[] = [];
	#messagesEl: HTMLElement | null = null;

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

	set roomId(value: string) {
		this.#roomId = value;
		this.requestUpdate("roomId");
	}

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

	set userName(value: string) {
		this.#userName = value;
		localStorage.setItem("folk-chat-username", value);
		this.requestUpdate("userName");
	}

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

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

		// Try to restore username from localStorage
		this.#userName = localStorage.getItem("folk-chat-username") || "";
		this.#roomId = this.getAttribute("room-id") || "default-room";

		const wrapper = document.createElement("div");
		wrapper.innerHTML = html`
			<div class="header">
				<span class="header-title">
					<span>💬</span>
					<span>Chat</span>
				</span>
				<div class="header-actions">
					<button class="close-btn" title="Close">×</button>
				</div>
			</div>
			<div class="chat-container">
				<div class="messages"></div>
				<div class="input-container">
					<input type="text" class="message-input" placeholder="Type a message..." />
					${SpeechDictation.isSupported() ? '<button class="mic-btn" title="Voice dictation">🎤</button>' : ''}
					<button class="send-btn">Send</button>
				</div>
			</div>
			<div class="username-prompt" style="display: none;">
				<p>Enter your name to join the chat:</p>
				<input type="text" class="username-input" placeholder="Your name..." />
				<button class="username-btn">Join Chat</button>
			</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 element references
		this.#messagesEl = wrapper.querySelector(".messages");
		const chatContainer = wrapper.querySelector(".chat-container") as HTMLElement;
		const usernamePrompt = wrapper.querySelector(".username-prompt") as HTMLElement;
		const messageInput = wrapper.querySelector(".message-input") as HTMLInputElement;
		const sendBtn = wrapper.querySelector(".send-btn") as HTMLButtonElement;
		const usernameInput = wrapper.querySelector(".username-input") as HTMLInputElement;
		const usernameBtn = wrapper.querySelector(".username-btn") as HTMLButtonElement;
		const closeBtn = wrapper.querySelector(".close-btn") as HTMLButtonElement;

		// Show username prompt if not set
		if (!this.#userName) {
			chatContainer.style.display = "none";
			usernamePrompt.style.display = "block";
		}

		// Username submit
		const submitUsername = () => {
			const name = usernameInput.value.trim();
			if (name) {
				this.userName = name;
				chatContainer.style.display = "flex";
				usernamePrompt.style.display = "none";
			}
		};

		usernameBtn.addEventListener("click", submitUsername);
		usernameInput.addEventListener("keydown", (e) => {
			if (e.key === "Enter") submitUsername();
		});

		// Send message
		const sendMessage = () => {
			const content = messageInput.value.trim();
			if (content && this.#userName) {
				this.addMessage({
					id: crypto.randomUUID(),
					userName: this.#userName,
					content,
					timestamp: Date.now(),
				});
				messageInput.value = "";
			}
		};

		sendBtn.addEventListener("click", sendMessage);
		messageInput.addEventListener("keydown", (e) => {
			if (e.key === "Enter") sendMessage();
		});

		// Voice dictation
		const micBtn = wrapper.querySelector(".mic-btn") as HTMLButtonElement | null;
		if (micBtn) {
			let baseText = "";
			let interimText = "";
			const dictation = new SpeechDictation({
				onInterim: (text) => {
					interimText = text;
					messageInput.value = baseText + (baseText ? " " : "") + text;
				},
				onFinal: (text) => {
					interimText = "";
					baseText += (baseText ? " " : "") + text;
					messageInput.value = baseText;
				},
				onStateChange: (recording) => {
					micBtn.classList.toggle("recording", recording);
					if (!recording) {
						baseText = messageInput.value;
						interimText = "";
					}
				},
				onError: (err) => console.warn("Chat dictation:", err),
			});

			micBtn.addEventListener("click", (e) => {
				e.stopPropagation();
				if (!dictation.isRecording) {
					baseText = messageInput.value;
				}
				dictation.toggle();
				messageInput.focus();
			});
		}

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

		return root;
	}

	addMessage(message: ChatMessage) {
		this.#messages.push(message);
		this.#renderMessages();
		this.dispatchEvent(
			new CustomEvent("message", {
				detail: { message },
				bubbles: true,
			})
		);
	}

	#renderMessages() {
		if (!this.#messagesEl) return;

		this.#messagesEl.innerHTML = this.#messages
			.map((msg) => {
				const isOwn = msg.userName === this.#userName;
				const time = new Date(msg.timestamp).toLocaleTimeString([], {
					hour: "2-digit",
					minute: "2-digit",
				});
				return `
					<div class="message ${isOwn ? "own" : ""}">
						<div class="message-header">
							<span class="username">${msg.userName}</span>
							<span class="time">${time}</span>
						</div>
						<div class="message-content">${this.#escapeHtml(msg.content)}</div>
					</div>
				`;
			})
			.join("");

		// Scroll to bottom
		this.#messagesEl.scrollTop = this.#messagesEl.scrollHeight;
	}

	#escapeHtml(text: string): string {
		const div = document.createElement("div");
		div.textContent = text;
		return div.innerHTML;
	}

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

	override toJSON() {
		return {
			...super.toJSON(),
			type: "folk-chat",
			roomId: this.roomId,
			messages: this.messages,
		};
	}

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