import type { Progress, LevelStatus } from "../types";
import { levels } from "../game/levels";
import { getProgress, getForestElements, saveProgress } from "../storage/db";
import { playForestElementSound } from "../audio/sounds";

let activeObjectUrls: string[] = [];

export const SLOTS_PER_PAGE = 12;

export async function renderForestScene(
	db: IDBDatabase,
	page: number,
	newElementId?: number,
): Promise<void> {
	const grid = document.getElementById("forest-grid");
	if (!grid) return;

	// Revoke old object URLs to prevent memory leaks
	for (const url of activeObjectUrls) {
		URL.revokeObjectURL(url);
	}
	activeObjectUrls = [];

	// Fade out before clearing
	grid.style.opacity = "0";
	grid.style.transition = "opacity 0.3s ease";

	const elements = await getForestElements(db);
	grid.innerHTML = "";

	// Render elements for the given page (4x3 grid per page)
	const start = page * SLOTS_PER_PAGE;
	const end = start + SLOTS_PER_PAGE;
	const toRender = elements.slice(start, end);

	for (const element of toRender) {
		const slot = document.createElement("div");
		slot.className = "forest__element";

		const img = document.createElement("img");
		const objectUrl = URL.createObjectURL(element.imageBlob);
		activeObjectUrls.push(objectUrl);
		img.src = objectUrl;
		img.alt = element.description;

		// Random offset +-10-20px for natural placement
		const offsetX =
			(Math.random() > 0.5 ? 1 : -1) * (10 + Math.random() * 10);
		const offsetY =
			(Math.random() > 0.5 ? 1 : -1) * (10 + Math.random() * 10);
		img.style.transform = `translate(${Math.round(offsetX)}px, ${Math.round(offsetY)}px)`;

		// Animate newly added element
		if (element.id === newElementId) {
			slot.classList.add("forest__element--new");
			playForestElementSound();
		}

		slot.appendChild(img);
		grid.appendChild(slot);
	}

	// Trigger fade-in after a frame
	requestAnimationFrame(() => {
		grid.style.opacity = "1";
	});

	// Update navigation UI
	const totalPages = Math.max(1, Math.ceil(elements.length / SLOTS_PER_PAGE));
	const navContainer = document.getElementById("forest-nav");
	if (navContainer) {
		const prevBtn = document.getElementById(
			"forest-nav-prev",
		) as HTMLButtonElement;
		const nextBtn = document.getElementById(
			"forest-nav-next",
		) as HTMLButtonElement;
		const pageText = document.getElementById("forest-nav-text");

		if (totalPages <= 1) {
			navContainer.style.display = "none";
		} else {
			navContainer.style.display = "flex";
			prevBtn.disabled = page <= 0;
			nextBtn.disabled = page >= totalPages - 1;
			if (pageText) pageText.textContent = `Wald ${page + 1} von ${totalPages}`;
		}
	}
}

export function getLevelStatus(
	levelNum: number,
	progress: Progress,
): LevelStatus {
	if (progress.completedLevels.includes(levelNum)) return "completed";
	if (levelNum === progress.currentLevel) return "current";
	return "locked";
}

export function renderLevelMap(
	container: HTMLElement,
	progress: Progress,
	onLevelClick: (level: number) => void,
): void {
	container.innerHTML = "";

	levels.forEach((level) => {
		const status = getLevelStatus(level.level, progress);
		const card = document.createElement("button");
		card.className = `level-card level-card--${status}`;
		card.dataset.level = String(level.level);

		const statusIcon =
			status === "completed" ? "\u2713" : status === "current" ? "\u2192" : "\uD83D\uDD12";
		const keysDisplay = level.newKeys
			.filter((k) => k !== " ")
			.map((k) => k.toUpperCase())
			.join(" ");

		card.innerHTML = `
			<span class="level-card__number">Stufe ${level.level}</span>
			<span class="level-card__keys">${keysDisplay}${level.newKeys.includes(" ") ? " + Leertaste" : ""}</span>
			<span class="level-card__status">${statusIcon}</span>
		`;

		// Only current and completed levels are clickable
		if (status !== "locked") {
			card.addEventListener("click", () => onLevelClick(level.level));
		} else {
			card.disabled = true;
		}

		container.appendChild(card);
	});
}

const MAX_LEVEL = 6;

export async function initForestScreen(
	db: IDBDatabase,
	onStartLesson: (level: number) => void,
): Promise<void> {
	const mapContainer = document.getElementById("level-map")!;
	const continueBtn = document.getElementById(
		"continue-btn",
	) as HTMLButtonElement;
	const progress = await getProgress(db);
	if (!progress) return;

	renderLevelMap(mapContainer, progress, onStartLesson);
	let currentPage = progress.currentForestPage ?? 0;
	await renderForestScene(db, currentPage);

	// Wire navigation buttons
	const prevBtn = document.getElementById("forest-nav-prev") as HTMLButtonElement;
	const nextBtn = document.getElementById("forest-nav-next") as HTMLButtonElement;

	const navigateToPage = async (newPage: number) => {
		currentPage = newPage;
		await renderForestScene(db, currentPage);
		// Persist page in progress
		const freshProgress = await getProgress(db);
		if (freshProgress) {
			freshProgress.currentForestPage = currentPage;
			await saveProgress(db, freshProgress);
		}
	};

	if (prevBtn) {
		prevBtn.onclick = () => {
			if (currentPage > 0) navigateToPage(currentPage - 1);
		};
	}

	if (nextBtn) {
		nextBtn.onclick = async () => {
			const elements = await getForestElements(db);
			const totalPages = Math.max(1, Math.ceil(elements.length / SLOTS_PER_PAGE));
			if (currentPage < totalPages - 1) navigateToPage(currentPage + 1);
		};
	}

	const allComplete = levels.every((l) =>
		progress.completedLevels.includes(l.level),
	);

	if (allComplete) {
		continueBtn.textContent = "Alle Stufen geschafft!";
		continueBtn.disabled = true;
		continueBtn.classList.add("forest__continue-btn--done");
	} else {
		continueBtn.textContent = "Weiter üben";
		continueBtn.disabled = false;
		continueBtn.classList.remove("forest__continue-btn--done");
		continueBtn.onclick = () =>
			onStartLesson(Math.min(progress.currentLevel, MAX_LEVEL));
	}
}
