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

const styles = css`
	:host {
		background: var(--rs-bg-surface);
		border-radius: 8px;
		box-shadow: var(--rs-shadow-sm);
		min-width: 400px;
		min-height: 350px;
	}

	.header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 8px 12px;
		background: linear-gradient(135deg, #059669, #10b981);
		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);
	}

	.content {
		display: flex;
		flex-direction: column;
		height: calc(100% - 36px);
		background: var(--rs-bg-surface);
		border-radius: 0 0 8px 8px;
	}

	.video-container {
		flex: 1;
		display: grid;
		grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
		gap: 8px;
		padding: 12px;
		background: var(--rs-bg-page);
	}

	.video-slot {
		background: var(--rs-bg-surface-raised);
		border-radius: 8px;
		aspect-ratio: 16/9;
		display: flex;
		align-items: center;
		justify-content: center;
		position: relative;
		overflow: hidden;
	}

	.video-slot video {
		width: 100%;
		height: 100%;
		object-fit: cover;
		border-radius: 8px;
	}

	.video-placeholder {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		color: var(--rs-text-muted);
		gap: 8px;
	}

	.video-placeholder-icon {
		font-size: 32px;
		opacity: 0.5;
	}

	.participant-name {
		position: absolute;
		bottom: 8px;
		left: 8px;
		background: rgba(0, 0, 0, 0.6);
		color: white;
		padding: 4px 8px;
		border-radius: 4px;
		font-size: 11px;
	}

	.controls {
		display: flex;
		align-items: center;
		justify-content: center;
		gap: 12px;
		padding: 12px;
		background: var(--rs-bg-surface);
		border-top: 1px solid var(--rs-border);
	}

	.control-btn {
		width: 48px;
		height: 48px;
		border-radius: 50%;
		border: none;
		cursor: pointer;
		display: flex;
		align-items: center;
		justify-content: center;
		font-size: 20px;
		transition: all 0.2s;
	}

	.control-btn.primary {
		background: #10b981;
		color: white;
	}

	.control-btn.primary:hover {
		background: #059669;
	}

	.control-btn.secondary {
		background: var(--rs-bg-surface-raised);
		color: white;
	}

	.control-btn.secondary:hover {
		background: var(--rs-toolbar-btn-hover);
	}

	.control-btn.danger {
		background: #ef4444;
		color: white;
	}

	.control-btn.danger:hover {
		background: #dc2626;
	}

	.control-btn.muted {
		background: #ef4444 !important;
	}

	.join-screen {
		flex: 1;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		gap: 16px;
		padding: 24px;
	}

	.join-icon {
		font-size: 48px;
	}

	.join-title {
		color: var(--rs-text-primary);
		font-size: 18px;
		font-weight: 600;
	}

	.join-subtitle {
		color: var(--rs-text-secondary);
		font-size: 13px;
		text-align: center;
	}

	.room-input {
		padding: 10px 16px;
		border: 2px solid var(--rs-input-border);
		border-radius: 8px;
		background: var(--rs-input-bg);
		color: var(--rs-input-text);
		font-size: 14px;
		width: 200px;
		text-align: center;
		outline: none;
	}

	.room-input:focus {
		border-color: var(--rs-accent);
	}

	.join-btn {
		padding: 12px 32px;
		background: #10b981;
		color: white;
		border: none;
		border-radius: 8px;
		font-size: 14px;
		font-weight: 600;
		cursor: pointer;
		transition: background 0.2s;
	}

	.join-btn:hover {
		background: #059669;
	}

	.join-btn:disabled {
		opacity: 0.5;
		cursor: not-allowed;
	}

	.status-bar {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 8px 12px;
		background: var(--rs-bg-page);
		font-size: 11px;
		color: var(--rs-text-secondary);
	}

	.recording-indicator {
		display: flex;
		align-items: center;
		gap: 4px;
		color: #ef4444;
	}

	.recording-dot {
		width: 8px;
		height: 8px;
		background: #ef4444;
		border-radius: 50%;
		animation: pulse 1.5s infinite;
	}

	@keyframes pulse {
		0%, 100% { opacity: 1; }
		50% { opacity: 0.5; }
	}
`;

interface Participant {
	id: string;
	name: string;
	videoEnabled: boolean;
	audioEnabled: boolean;
}

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

export class FolkVideoChat extends FolkShape {
	static override tagName = "folk-video-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: string | null = null;
	#isJoined = false;
	#isMuted = false;
	#isVideoOff = false;
	#isRecording = false;
	#participants: Participant[] = [];
	#localStream: MediaStream | null = null;

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

	set roomId(value: string | null) {
		this.#roomId = value;
	}

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

		const wrapper = document.createElement("div");
		wrapper.innerHTML = html`
			<div class="header">
				<span class="header-title">
					<span>📹</span>
					<span>Video Chat</span>
				</span>
				<div class="header-actions">
					<button class="close-btn" title="Close">×</button>
				</div>
			</div>
			<div class="content">
				<div class="join-screen">
					<span class="join-icon">📹</span>
					<span class="join-title">Join Video Call</span>
					<span class="join-subtitle">Enter a room name to start or join a call</span>
					<input type="text" class="room-input" placeholder="Room name..." />
					<button class="join-btn">Join Call</button>
				</div>
			</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);
		}

		const content = wrapper.querySelector(".content") as HTMLElement;
		const joinScreen = wrapper.querySelector(".join-screen") as HTMLElement;
		const roomInput = wrapper.querySelector(".room-input") as HTMLInputElement;
		const joinBtn = wrapper.querySelector(".join-btn") as HTMLButtonElement;
		const closeBtn = wrapper.querySelector(".close-btn") as HTMLButtonElement;

		// Join button handler
		joinBtn.addEventListener("click", (e) => {
			e.stopPropagation();
			const roomName = roomInput.value.trim();
			if (roomName) {
				this.#roomId = roomName;
				this.#joinCall(content, joinScreen);
			}
		});

		roomInput.addEventListener("keydown", (e) => {
			if (e.key === "Enter") {
				e.preventDefault();
				joinBtn.click();
			}
		});

		// Prevent drag on input
		roomInput.addEventListener("pointerdown", (e) => e.stopPropagation());

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

		return root;
	}

	async #joinCall(content: HTMLElement, joinScreen: HTMLElement) {
		try {
			// Request camera/microphone access
			this.#localStream = await navigator.mediaDevices.getUserMedia({
				video: true,
				audio: true,
			});

			this.#isJoined = true;

			// Add self as participant
			this.#participants = [
				{
					id: "local",
					name: "You",
					videoEnabled: true,
					audioEnabled: true,
				},
			];

			// Replace join screen with video UI
			content.innerHTML = `
				<div class="status-bar">
					<span>Room: ${this.#escapeHtml(this.#roomId || "")}</span>
					<span>${this.#participants.length} participant(s)</span>
					${this.#isRecording ? '<span class="recording-indicator"><span class="recording-dot"></span>Recording</span>' : ""}
				</div>
				<div class="video-container">
					<div class="video-slot" id="local-video">
						<video autoplay muted playsinline></video>
						<span class="participant-name">You</span>
					</div>
				</div>
				<div class="controls">
					<button class="control-btn secondary" id="mute-btn" title="Mute">🔊</button>
					<button class="control-btn secondary" id="video-btn" title="Toggle Video">📷</button>
					<button class="control-btn secondary" id="record-btn" title="Record">⏺</button>
					<button class="control-btn danger" id="leave-btn" title="Leave Call">📞</button>
				</div>
			`;

			// Attach local video stream
			const localVideo = content.querySelector("#local-video video") as HTMLVideoElement;
			if (localVideo && this.#localStream) {
				localVideo.srcObject = this.#localStream;
			}

			// Control handlers
			const muteBtn = content.querySelector("#mute-btn") as HTMLButtonElement;
			const videoBtn = content.querySelector("#video-btn") as HTMLButtonElement;
			const recordBtn = content.querySelector("#record-btn") as HTMLButtonElement;
			const leaveBtn = content.querySelector("#leave-btn") as HTMLButtonElement;

			muteBtn.addEventListener("click", (e) => {
				e.stopPropagation();
				this.#toggleMute(muteBtn);
			});

			videoBtn.addEventListener("click", (e) => {
				e.stopPropagation();
				this.#toggleVideo(videoBtn, localVideo);
			});

			recordBtn.addEventListener("click", (e) => {
				e.stopPropagation();
				this.#toggleRecording(recordBtn, content);
			});

			leaveBtn.addEventListener("click", (e) => {
				e.stopPropagation();
				this.#leaveCall();
				// Reset to join screen
				content.innerHTML = "";
				content.appendChild(joinScreen);
			});

			this.dispatchEvent(
				new CustomEvent("call-joined", { detail: { roomId: this.#roomId } })
			);
		} catch (error) {
			console.error("Failed to join call:", error);
			// Show error in join screen
			const errorEl = document.createElement("div");
			errorEl.style.cssText = "color: #ef4444; font-size: 12px; margin-top: 8px;";
			errorEl.textContent = "Failed to access camera/microphone";
			joinScreen.appendChild(errorEl);
		}
	}

	#toggleMute(btn: HTMLButtonElement) {
		this.#isMuted = !this.#isMuted;
		if (this.#localStream) {
			this.#localStream.getAudioTracks().forEach((track) => {
				track.enabled = !this.#isMuted;
			});
		}
		btn.textContent = this.#isMuted ? "🔇" : "🔊";
		btn.classList.toggle("muted", this.#isMuted);
	}

	#toggleVideo(btn: HTMLButtonElement, video: HTMLVideoElement) {
		this.#isVideoOff = !this.#isVideoOff;
		if (this.#localStream) {
			this.#localStream.getVideoTracks().forEach((track) => {
				track.enabled = !this.#isVideoOff;
			});
		}
		btn.textContent = this.#isVideoOff ? "📷️⃠" : "📷";
		btn.classList.toggle("muted", this.#isVideoOff);
		video.style.opacity = this.#isVideoOff ? "0.3" : "1";
	}

	#toggleRecording(btn: HTMLButtonElement, content: HTMLElement) {
		this.#isRecording = !this.#isRecording;
		btn.classList.toggle("muted", this.#isRecording);

		const statusBar = content.querySelector(".status-bar");
		if (statusBar) {
			const existing = statusBar.querySelector(".recording-indicator");
			if (this.#isRecording && !existing) {
				const indicator = document.createElement("span");
				indicator.className = "recording-indicator";
				indicator.innerHTML =
					'<span class="recording-dot"></span>Recording';
				statusBar.appendChild(indicator);
			} else if (!this.#isRecording && existing) {
				existing.remove();
			}
		}

		this.dispatchEvent(
			new CustomEvent("recording-change", { detail: { isRecording: this.#isRecording } })
		);
	}

	#leaveCall() {
		if (this.#localStream) {
			this.#localStream.getTracks().forEach((track) => track.stop());
			this.#localStream = null;
		}
		this.#isJoined = false;
		this.#isMuted = false;
		this.#isVideoOff = false;
		this.#isRecording = false;
		this.#participants = [];

		this.dispatchEvent(
			new CustomEvent("call-left", { detail: { roomId: this.#roomId } })
		);
	}

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

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

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

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