/**
 * Reward module: Pre-generates forest element images during lessons
 * and displays the reward screen after lesson completion.
 *
 * Strategy: Start image generation at lesson begin (pre-generation),
 * show placeholder while awaiting, display result with companion comment.
 */

import { loadConfig } from "../api/config";
import {
	generateImage,
	checkRateLimit,
	incrementApiCall,
} from "../api/gemini";
import {
	getStyleReference,
	saveForestElement,
	getForestElements,
} from "../storage/db";
import { getForestComment } from "../companion/companion";
import { getRandomFallbackForestComment } from "../companion/fallbacks";
import type { CompanionType, ForestElement } from "../types";
import { playRewardSound } from "../audio/sounds";
import { speakText } from "../audio/speech";
import { renderInlineMarkdown } from "../utils/markdown";
import { SLOTS_PER_PAGE } from "./scene";

// --- Element types for random selection ---

const ELEMENT_TYPES = [
	"Blume",
	"Pilz",
	"Schmetterling",
	"Vogel",
	"Reh",
	"Eichhörnchen",
	"Hase",
	"Frosch",
	"Igel",
	"Marienkaefer",
	"Libelle",
	"Schnecke",
];

// --- Fallback images (static SVGs) ---

const FALLBACK_SVGS = [
	"/src/assets/fallback-images/blume.svg",
	"/src/assets/fallback-images/pilz.svg",
	"/src/assets/fallback-images/vogel.svg",
	"/src/assets/fallback-images/schmetterling.svg",
	"/src/assets/fallback-images/reh.svg",
	"/src/assets/fallback-images/baum.svg",
	"/src/assets/fallback-images/bach.svg",
];

async function getRandomFallbackImage(): Promise<{
	blob: Blob;
	description: string;
}> {
	const idx = Math.floor(Math.random() * FALLBACK_SVGS.length);
	const path = FALLBACK_SVGS[idx]!;
	const name = path.split("/").pop()!.replace(".svg", "");
	try {
		const res = await fetch(path);
		const blob = await res.blob();
		return { blob, description: name };
	} catch {
		// Ultimate fallback: empty SVG blob
		const svg =
			'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="50" cy="50" r="40" fill="#E8F5E4"/></svg>';
		return {
			blob: new Blob([svg], { type: "image/svg+xml" }),
			description: "element",
		};
	}
}

// --- Pre-generation ---

let pregenPromise: Promise<{
	blob: Blob;
	description: string;
	prompt: string;
}> | null = null;

export function startPreGeneration(db: IDBDatabase): void {
	pregenPromise = generateForestElement(db);
}

async function generateForestElement(db: IDBDatabase): Promise<{
	blob: Blob;
	description: string;
	prompt: string;
}> {
	// Check rate limit
	const canGenerate = await checkRateLimit(db, "image");
	if (!canGenerate) {
		const fallback = await getRandomFallbackImage();
		return { ...fallback, prompt: "fallback" };
	}

	// Load config
	const config = await loadConfig();
	if (!config) {
		const fallback = await getRandomFallbackImage();
		return { ...fallback, prompt: "fallback" };
	}

	// Get style reference for visual consistency
	const styleRef = await getStyleReference(db);
	const referenceImages: Blob[] = [];
	if (styleRef) {
		referenceImages.push(styleRef.imageBlob);
	}

	// Pick random element type
	const elementType =
		ELEMENT_TYPES[Math.floor(Math.random() * ELEMENT_TYPES.length)]!;

	// Build prompt
	const prompt = `Kinderbuch-Illustration, Aquarell-Stil, ${elementType}, magischer Wald, warm, einladend, für Kinder, Pastellfarben, kein Text, einfarbig heller grüner Hintergrund`;

	// Generate image
	const blob = await generateImage(prompt, referenceImages, config);
	if (!blob) {
		const fallback = await getRandomFallbackImage();
		return { ...fallback, prompt };
	}

	// Track API usage
	await incrementApiCall(db, "image");

	return { blob, description: elementType, prompt };
}

// --- Reward screen ---

export async function initRewardScreen(
	db: IDBDatabase,
	level: number,
	characterType: CompanionType,
	onContinue: () => void,
	onBackToForest: () => void,
): Promise<number> {
	const imageArea = document.getElementById("reward-image-area")!;
	const companionTextEl = document.getElementById("reward-companion-text")!;
	const continueBtn = document.getElementById(
		"reward-continue-btn",
	) as HTMLButtonElement;
	const backBtn = document.getElementById(
		"reward-back-btn",
	) as HTMLButtonElement;

	// 1. Show placeholder immediately
	imageArea.innerHTML = `
		<div class="reward__placeholder">
			<span class="reward__leaf reward__leaf--1">\uD83C\uDF43</span>
			<span class="reward__leaf reward__leaf--2">\uD83C\uDF42</span>
			<span class="reward__leaf reward__leaf--3">\uD83C\uDF43</span>
			<p>Der Wald denkt nach...</p>
		</div>
	`;
	companionTextEl.textContent = "";

	// 2. Await pre-generated image (or generate now if not started)
	const result = await (pregenPromise ?? generateForestElement(db));
	pregenPromise = null;

	// 3. Get companion comment
	let comment: string;
	try {
		comment = await getForestComment(characterType, result.description, db);
	} catch {
		comment = getRandomFallbackForestComment();
	}

	// 4. Determine grid position for new element
	const existing = await getForestElements(db);
	const slotIndex = existing.length % SLOTS_PER_PAGE;
	const col = slotIndex % 4;
	const row = Math.floor(slotIndex / 4);
	// Add small random offset for natural feel
	const offsetX = (Math.random() - 0.5) * 30; // +-15px
	const offsetY = (Math.random() - 0.5) * 30;

	// 5. Save to IndexedDB
	const element: ForestElement = {
		levelCompleted: level,
		imageBlob: result.blob,
		imagePrompt: result.prompt,
		description: result.description,
		companionText: comment,
		position: { x: col + offsetX / 100, y: row + offsetY / 100 },
		createdAt: new Date().toISOString(),
	};
	const elementId = await saveForestElement(db, element);

	// 6. Replace placeholder with actual image + play reward sound
	const objectUrl = URL.createObjectURL(result.blob);
	imageArea.innerHTML = "";
	const img = document.createElement("img");
	img.src = objectUrl;
	img.alt = result.description;
	imageArea.appendChild(img);
	playRewardSound();

	// 7. Show companion comment + speak it aloud
	companionTextEl.innerHTML = renderInlineMarkdown(comment);
	speakText(comment);

	// 8. Wire buttons
	continueBtn.onclick = () => {
		URL.revokeObjectURL(objectUrl);
		onContinue();
	};
	backBtn.onclick = () => {
		URL.revokeObjectURL(objectUrl);
		onBackToForest();
	};

	// 9. Return element ID for forest scene animation
	return elementId;
}
