import { getProgress, saveProgress, getSettings, saveSettings } from "../storage/db";
import { companions } from "../companion/characters";
import type { CompanionType, KeyboardLayout, Settings } from "../types";
import { showScreen, getDB } from "../app";

const ACCESS_CODE = "1234";

/**
 * Show the parent code prompt gate, then reveal content on correct code.
 */
export function showParentCodePrompt(): void {
	showScreen("parent");

	const gate = document.getElementById("parent-gate")!;
	const content = document.getElementById("parent-content")!;
	const codeInput = document.getElementById("parent-code-input") as HTMLInputElement;
	const gateError = document.getElementById("parent-gate-error")!;

	// Reset state
	gate.style.display = "block";
	content.style.display = "none";
	codeInput.value = "";
	gateError.style.display = "none";

	codeInput.focus();

	// Remove previous listener to avoid duplicates
	const handler = () => {
		const value = codeInput.value;
		if (value === ACCESS_CODE) {
			gate.style.display = "none";
			content.style.display = "block";
			loadParentData();
			codeInput.removeEventListener("input", handler);
		} else if (value.length === 4) {
			gateError.style.display = "block";
			setTimeout(() => {
				gateError.style.display = "none";
				codeInput.value = "";
			}, 1500);
			codeInput.removeEventListener("input", handler);
			// Re-attach after clearing
			setTimeout(() => {
				codeInput.addEventListener("input", handler);
			}, 1500);
		}
	};

	codeInput.addEventListener("input", handler);
}

/**
 * Initialize the parent screen: wire back button.
 */
export function initParentScreen(_db: IDBDatabase, onBack: () => void): void {
	const backBtn = document.getElementById("parent-back-btn");
	if (backBtn) {
		backBtn.onclick = () => onBack();
	}
}

/**
 * Load and display all parent data (stats + settings).
 */
async function loadParentData(): Promise<void> {
	const db = getDB();
	const progress = await getProgress(db);
	const settings = await getSettings(db);

	// Stats
	if (progress) {
		document.getElementById("stat-level")!.textContent = String(progress.currentLevel);
		document.getElementById("stat-sessions")!.textContent = String(progress.totalSessions);

		const total = progress.totalCorrect + progress.totalErrors;
		const accuracy = total > 0 ? Math.round((progress.totalCorrect / total) * 100) : 0;
		document.getElementById("stat-accuracy")!.textContent = `${accuracy}%`;

		// Calendar dots (last 30 days)
		renderCalendarDots(progress.sessionDates);

		// Error keys
		renderErrorKeys(progress.errorKeyCounts);
	}

	// Settings
	await loadSettings(db, progress, settings);
}

/**
 * Render calendar dots for the last 30 days.
 */
function renderCalendarDots(sessionDates: string[]): void {
	const container = document.getElementById("calendar-dots")!;
	container.innerHTML = "";

	const today = new Date();
	const sessionSet = new Set(sessionDates);

	for (let i = 29; i >= 0; i--) {
		const date = new Date(today);
		date.setDate(today.getDate() - i);
		const dateStr = date.toISOString().split("T")[0]!;

		const dot = document.createElement("div");
		dot.className = sessionSet.has(dateStr)
			? "parent__calendar-dot"
			: "parent__calendar-dot parent__calendar-dot--empty";
		dot.title = dateStr;
		container.appendChild(dot);
	}
}

/**
 * Render error key badges, sorted by frequency, top 5.
 */
function renderErrorKeys(errorKeyCounts: Record<string, number>): void {
	const container = document.getElementById("error-keys-list")!;
	container.innerHTML = "";

	const entries = Object.entries(errorKeyCounts).sort((a, b) => b[1] - a[1]);

	if (entries.length === 0) {
		container.textContent = "Noch keine Fehler erfasst";
		return;
	}

	const top5 = entries.slice(0, 5);
	for (const [key, count] of top5) {
		const badge = document.createElement("span");
		badge.className = "parent__error-key";
		badge.textContent = `${key.toUpperCase()} (${count}x)`;
		container.appendChild(badge);
	}
}

/**
 * Load settings into form elements and wire change handlers.
 */
async function loadSettings(
	db: IDBDatabase,
	progress: Awaited<ReturnType<typeof getProgress>>,
	settings: Settings | null,
): Promise<void> {
	const layoutSelect = document.getElementById("setting-layout") as HTMLSelectElement;
	const audioCheckbox = document.getElementById("setting-audio") as HTMLInputElement;
	const companionSelect = document.getElementById("setting-companion") as HTMLSelectElement;
	const apiKeyInput = document.getElementById("setting-apikey") as HTMLInputElement;
	const saveApiKeyBtn = document.getElementById("save-apikey-btn")!;

	// Populate companion select
	companionSelect.innerHTML = "";
	for (const c of companions) {
		const option = document.createElement("option");
		option.value = c.type;
		option.textContent = `${c.emoji} ${c.name}`;
		companionSelect.appendChild(option);
	}

	// Set current values
	if (progress) {
		layoutSelect.value = progress.selectedLayout;
		companionSelect.value = progress.selectedCharacter;
	}
	if (settings) {
		audioCheckbox.checked = settings.audioEnabled;
		apiKeyInput.value = settings.apiKey || "";
	}

	// Wire change handlers
	layoutSelect.onchange = async () => {
		if (!progress) return;
		progress.selectedLayout = layoutSelect.value as KeyboardLayout;
		await saveProgress(db, progress);
		showSavedFeedback(layoutSelect);
	};

	companionSelect.onchange = async () => {
		if (!progress) return;
		progress.selectedCharacter = companionSelect.value as CompanionType;
		await saveProgress(db, progress);
		showSavedFeedback(companionSelect);
	};

	audioCheckbox.onchange = async () => {
		const currentSettings = settings ?? {
			id: 1 as const,
			audioEnabled: false,
			apiKey: "",
			apiCallsToday: { text: 0, image: 0 },
			lastApiCallDate: "",
		};
		currentSettings.audioEnabled = audioCheckbox.checked;
		await saveSettings(db, currentSettings);
		showSavedFeedback(audioCheckbox);
	};

	saveApiKeyBtn.onclick = async () => {
		const currentSettings = settings ?? {
			id: 1 as const,
			audioEnabled: false,
			apiKey: "",
			apiCallsToday: { text: 0, image: 0 },
			lastApiCallDate: "",
		};
		currentSettings.apiKey = apiKeyInput.value;
		await saveSettings(db, currentSettings);
		showSavedFeedback(saveApiKeyBtn);
	};
}

/**
 * Show brief "Gespeichert!" feedback next to an element.
 */
function showSavedFeedback(element: HTMLElement): void {
	// Remove any existing feedback
	const existing = element.parentElement?.querySelector(".parent__saved-feedback");
	if (existing) existing.remove();

	const feedback = document.createElement("span");
	feedback.className = "parent__saved-feedback";
	feedback.textContent = "Gespeichert!";
	element.parentElement?.appendChild(feedback);

	setTimeout(() => {
		feedback.style.opacity = "0";
		setTimeout(() => feedback.remove(), 300);
	}, 1500);
}
