import { useCallback, useEffect, useRef, useState } from "react";
import { Navigate, Route, Routes, useLocation, useNavigate } from "react-router-dom";
import {
	AboutModal,
	Lightbox,
	MedDetailModal,
	ProfileModal,
	ShareDialog,
	SharedSchedule,
	UserFilterModal,
} from "./components";
import { AppHeader } from "./components/AppHeader";
import { AuthPage, AuthProvider, useAuth } from "./components/Auth";
import { AppProvider, UnsavedChangesProvider, useAppContext } from "./context";
import { useScrollLock } from "./hooks/useScrollLock";
import { DashboardPage, MedicationsPage, PlannerPage, SchedulePage, SettingsPage, SharedOverviewPage } from "./pages";

// Vite injects this at build time from package.json
declare const __APP_VERSION__: string;
export const FRONTEND_VERSION = typeof __APP_VERSION__ !== "undefined" ? __APP_VERSION__ : "unknown";
const GITHUB_REPO = "DanielVolz/medassist-ng";
export const GITHUB_URL = `https://github.com/${GITHUB_REPO}`;

// =============================================================================
// Main App Wrapper with Auth
// =============================================================================
export default function App() {
	return (
		<AuthProvider>
			<Routes>
				{/* Public share route - accessible without auth */}
				<Route path="/share/:token/overview" element={<SharedOverviewPage />} />
				<Route path="/share/:token" element={<SharedSchedule />} />
				{/* All other routes go through AppRouter */}
				<Route path="*" element={<AppRouter />} />
			</Routes>
		</AuthProvider>
	);
}

function getInitialAuthTheme(): "light" | "dark" {
	if (typeof window === "undefined") return "dark";

	const stored = localStorage.getItem("theme");
	if (stored === "light" || stored === "dark") {
		return stored;
	}

	if (stored === "system") {
		return window.matchMedia?.("(prefers-color-scheme: light)").matches ? "light" : "dark";
	}

	return window.matchMedia?.("(prefers-color-scheme: light)").matches ? "light" : "dark";
}

function AppRouter() {
	const { user, authState, loading, authError } = useAuth();
	const authTheme = getInitialAuthTheme();

	// Show loading while checking auth state
	if (loading) {
		return (
			<div className="auth-container" data-theme={authTheme}>
				<div className="auth-card" style={{ textAlign: "center" }}>
					<h1 className="auth-title">💊 MedAssist-ng</h1>
					<p>Loading...</p>
				</div>
			</div>
		);
	}

	// Show error if we couldn't connect to the server
	if (authError) {
		return (
			<div className="auth-container" data-theme={authTheme}>
				<div className="auth-card" style={{ textAlign: "center" }}>
					<h1 className="auth-title">💊 MedAssist-ng</h1>
					<div className="auth-error" style={{ marginBottom: "1rem" }}>
						<strong>Connection Error</strong>
						<br />
						{authError}
					</div>
					<p style={{ fontSize: "0.9rem", color: "var(--text-muted)" }}>
						Please check if the server is running and try again.
					</p>
					<button className="btn btn-primary" onClick={() => window.location.reload()} style={{ marginTop: "1rem" }}>
						Retry
					</button>
				</div>
			</div>
		);
	}

	// If auth state is null (shouldn't happen after loading, but be safe)
	if (!authState) {
		return (
			<div className="auth-container" data-theme={authTheme}>
				<div className="auth-card" style={{ textAlign: "center" }}>
					<h1 className="auth-title">💊 MedAssist-ng</h1>
					<p>Initializing...</p>
				</div>
			</div>
		);
	}

	// If auth is enabled
	if (authState.authEnabled) {
		// Need to register first user
		if (authState.needsSetup) {
			return <AuthPage />;
		}
		// Not logged in
		if (!user) {
			return <AuthPage />;
		}
	}

	// Auth disabled or user is logged in - show main app
	return (
		<UnsavedChangesProvider>
			<AppProvider>
				<AppContent />
			</AppProvider>
		</UnsavedChangesProvider>
	);
}

// =============================================================================
// Main App Content
// =============================================================================

function AppContent() {
	const navigate = useNavigate();
	const location = useLocation();
	// Get shared state from AppContext
	const ctx = useAppContext();
	const {
		// Medications
		meds,
		loadMeds,
		// Refill
		showRefillModal,
		setShowRefillModal,
		refillPacks,
		setRefillPacks,
		refillLoose,
		setRefillLoose,
		usePrescriptionRefill,
		setUsePrescriptionRefill,
		refillSaving,
		refillHistory,
		refillHistoryExpanded,
		setRefillHistoryExpanded,
		showEditStockModal,
		setShowEditStockModal,
		editStockFullBlisters,
		setEditStockFullBlisters,
		editStockPartialBlisterPills,
		setEditStockPartialBlisterPills,
		editStockLoosePills,
		setEditStockLoosePills,
		editStockSaving,
		editStockMedication,
		openRefillModal,
		closeRefillModal,
		openEditStockModal,
		closeEditStockModal,
		// Share
		showShareDialog,
		sharePeople,
		shareSelectedPerson,
		setShareSelectedPerson,
		shareSelectedDays,
		setShareSelectedDays,
		shareGenerating,
		shareLink,
		setShareLink,
		shareCopied,
		setShareCopied,
		generateShareLink,
		copyShareLink,
		closeShareDialog,
		resetShareDialogState,
		// Computed
		coverage,
		// Modal state
		selectedMed,
		setSelectedMed,
		showImageLightbox,
		setShowImageLightbox,
		scheduleLightboxImage,
		setScheduleLightboxImage,
		selectedUser,
		setSelectedUser,
		// Modal helpers
		openMedDetail,
		closeMedDetail,
		openImageLightbox,
		closeImageLightbox,
		closeScheduleLightbox,
		closeUserFilter,
	} = ctx;

	// Wrapper to pass meds to openShareDialog
	const _openShareDialog = () => ctx.openShareDialog();

	// Local-only state (not shared across components)
	const [showProfile, setShowProfile] = useState(false);
	const [showAbout, setShowAbout] = useState(false);
	const [routeTransitionMaskActive, setRouteTransitionMaskActive] = useState(false);
	const routeTransitionMinEndRef = useRef(0);
	const routeTransitionFallbackTimerRef = useRef<number | null>(null);
	const closeProfile = useCallback(() => {
		if (showProfile) {
			window.history.back();
		}
	}, [showProfile]);

	const closeAbout = useCallback(() => {
		if (showAbout) {
			window.history.back();
		}
	}, [showAbout]);

	// Get centralized stockThresholds from context
	const { stockThresholds } = ctx;

	// Handle browser back button to close modals (in priority order)
	useEffect(() => {
		const handlePopState = () => {
			// Close modals in order of priority (topmost first)
			// NOTE: This handler MUST NOT call history.back() or it will cause infinite loops
			// Only use direct state setters here
			if (showImageLightbox) {
				setShowImageLightbox(false);
			} else if (scheduleLightboxImage) {
				setScheduleLightboxImage(null);
			} else if (showEditStockModal) {
				setShowEditStockModal(false);
			} else if (showRefillModal) {
				setShowRefillModal(false);
			} else if (showShareDialog) {
				resetShareDialogState();
			} else if (showAbout) {
				setShowAbout(false);
			} else if (showProfile) {
				setShowProfile(false);
			} else if (selectedUser) {
				setSelectedUser(null);
			} else if (selectedMed) {
				setSelectedMed(null);
			}
		};
		window.addEventListener("popstate", handlePopState);
		return () => window.removeEventListener("popstate", handlePopState);
	}, [
		selectedMed,
		showImageLightbox,
		scheduleLightboxImage,
		selectedUser,
		showProfile,
		showAbout,
		showShareDialog,
		showRefillModal,
		showEditStockModal,
		resetShareDialogState,
		setScheduleLightboxImage,
		setSelectedMed,
		setSelectedUser,
		setShowEditStockModal,
		setShowImageLightbox,
		setShowRefillModal,
	]);

	// Close tooltips on scroll/touch (for mobile)
	useEffect(() => {
		const closeAllTooltips = () => {
			document.querySelectorAll(".info-tooltip.tooltip-active, .tooltip-trigger.tooltip-active").forEach((el) => {
				el.classList.remove("tooltip-active");
			});
		};

		const handleTooltipClick = (e: Event) => {
			const target = e.target as HTMLElement;
			const tooltipTrigger = target.closest(".info-tooltip, .tooltip-trigger") as HTMLElement | null;
			if (tooltipTrigger) {
				// Close other tooltips first
				closeAllTooltips();
				// Toggle this one
				tooltipTrigger.classList.add("tooltip-active");
				// Position tooltip above the icon on mobile
				if (window.innerWidth <= 640) {
					const rect = tooltipTrigger.getBoundingClientRect();
					// Place tooltip bottom edge just above the icon
					tooltipTrigger.style.setProperty("--tooltip-bottom", `${window.innerHeight - rect.top + 8}px`);
				}
			} else {
				closeAllTooltips();
			}
		};

		const handleTouchMove = () => {
			closeAllTooltips();
		};

		document.addEventListener("click", handleTooltipClick, { capture: true });
		document.addEventListener("touchmove", handleTouchMove, { passive: true });
		document.addEventListener("scroll", handleTouchMove, { passive: true });
		return () => {
			document.removeEventListener("click", handleTooltipClick, { capture: true });
			document.removeEventListener("touchmove", handleTouchMove);
			document.removeEventListener("scroll", handleTouchMove);
		};
	}, []);

	// Global Escape handling in priority order.
	// This keeps behavior consistent even when child modals are mocked in tests.
	useEffect(() => {
		const handleEscape = (e: KeyboardEvent) => {
			if (e.key !== "Escape") return;
			if (e.defaultPrevented) return;

			if (scheduleLightboxImage) {
				closeScheduleLightbox();
				return;
			}
			if (showImageLightbox) {
				closeImageLightbox();
				return;
			}
			if (showEditStockModal) {
				closeEditStockModal();
				return;
			}
			if (showRefillModal) {
				closeRefillModal();
				return;
			}
			if (showShareDialog) {
				closeShareDialog();
				return;
			}
			if (showAbout) {
				closeAbout();
				return;
			}
			if (showProfile) {
				closeProfile();
				return;
			}
			if (selectedUser) {
				closeUserFilter();
				return;
			}
			if (selectedMed) {
				closeMedDetail();
			}
		};

		document.addEventListener("keydown", handleEscape);
		return () => document.removeEventListener("keydown", handleEscape);
	}, [
		showImageLightbox,
		scheduleLightboxImage,
		showEditStockModal,
		showRefillModal,
		showShareDialog,
		showAbout,
		showProfile,
		selectedUser,
		selectedMed,
		closeImageLightbox,
		closeScheduleLightbox,
		closeEditStockModal,
		closeRefillModal,
		closeShareDialog,
		closeAbout,
		closeProfile,
		closeUserFilter,
		closeMedDetail,
	]);

	// Prevent background scroll when any modal is open
	useScrollLock(
		!!(
			selectedMed ||
			selectedUser ||
			showProfile ||
			showAbout ||
			showShareDialog ||
			showRefillModal ||
			showEditStockModal ||
			showImageLightbox ||
			scheduleLightboxImage
		)
	);

	// Update selectedMed when meds change (e.g., after refill)
	useEffect(() => {
		if (selectedMed) {
			const updated = meds.find((m) => m.id === selectedMed.id);
			if (
				updated &&
				(updated.packCount !== selectedMed.packCount ||
					updated.looseTablets !== selectedMed.looseTablets ||
					updated.updatedAt !== selectedMed.updatedAt)
			) {
				setSelectedMed(updated);
			}
		}
	}, [meds, selectedMed, setSelectedMed]);

	const stockCorrectionMed = selectedMed ?? (showEditStockModal ? editStockMedication : null);

	const handleSubmitStockCorrection = async (medId: number) => {
		if (!stockCorrectionMed) return;
		await ctx.submitStockCorrection(medId, stockCorrectionMed, loadMeds);
	};

	// For MedDetailModal: refill without form update (not editing)
	const handleSubmitRefill = async (medId: number, usePrescription: boolean = false) => {
		await ctx.submitRefill(medId, null, () => {}, loadMeds, usePrescription);
	};

	useEffect(() => {
		if (!routeTransitionMaskActive) return;
		if (location.pathname !== "/medications") return;

		const hasEditMedIdParam = new URLSearchParams(location.search).has("editMedId");
		if (hasEditMedIdParam) return;

		const remaining = Math.max(0, routeTransitionMinEndRef.current - performance.now());
		const timer = window.setTimeout(() => setRouteTransitionMaskActive(false), remaining);
		return () => window.clearTimeout(timer);
	}, [location.pathname, location.search, routeTransitionMaskActive]);

	useEffect(() => {
		const handleEditTransitionReady = () => {
			if (!routeTransitionMaskActive) return;
			const remaining = Math.max(0, routeTransitionMinEndRef.current - performance.now());
			window.setTimeout(() => {
				setRouteTransitionMaskActive(false);
				if (routeTransitionFallbackTimerRef.current !== null) {
					window.clearTimeout(routeTransitionFallbackTimerRef.current);
					routeTransitionFallbackTimerRef.current = null;
				}
			}, remaining);
		};

		window.addEventListener("medassist:edit-transition-ready", handleEditTransitionReady);
		return () => {
			window.removeEventListener("medassist:edit-transition-ready", handleEditTransitionReady);
		};
	}, [routeTransitionMaskActive]);

	useEffect(() => {
		return () => {
			if (routeTransitionFallbackTimerRef.current !== null) {
				window.clearTimeout(routeTransitionFallbackTimerRef.current);
			}
		};
	}, []);

	const handleOpenMedicationEdit = () => {
		if (!selectedMed) return;
		const medId = selectedMed.id;
		routeTransitionMinEndRef.current = performance.now() + 80;
		setRouteTransitionMaskActive(true);
		if (routeTransitionFallbackTimerRef.current !== null) {
			window.clearTimeout(routeTransitionFallbackTimerRef.current);
		}
		routeTransitionFallbackTimerRef.current = window.setTimeout(() => {
			setRouteTransitionMaskActive(false);
			routeTransitionFallbackTimerRef.current = null;
		}, 700);
		setShowImageLightbox(false);
		setShowRefillModal(false);
		setShowEditStockModal(false);
		setSelectedMed(null);
		navigate(`/medications?editMedId=${medId}`);
	};

	const handleOpenEditStockFromDetail = () => {
		if (!selectedMed) return;
		openEditStockModal(selectedMed, coverage);
	};

	const openProfile = useCallback(() => {
		setShowProfile(true);
		window.history.pushState({ modal: "profile" }, "");
	}, []);

	const openAbout = useCallback(() => {
		setShowAbout(true);
		window.history.pushState({ modal: "about" }, "");
	}, []);

	return (
		<main className="page">
			<AppHeader onOpenProfile={openProfile} onOpenAbout={openAbout} />

			{/* Profile Modal */}
			<ProfileModal isOpen={showProfile} onClose={closeProfile} />

			{/* About Modal */}
			<AboutModal isOpen={showAbout} onClose={closeAbout} />

			<Routes>
				<Route path="/" element={<Navigate to="/dashboard" replace />} />
				<Route path="/dashboard" element={<DashboardPage />} />

				<Route path="/medications" element={<MedicationsPage />} />

				<Route path="/planner" element={<PlannerPage />} />

				<Route path="/settings" element={<SettingsPage />} />

				<Route path="/schedule" element={<SchedulePage />} />
				{/* Catch-all: redirect unknown routes to dashboard */}
				<Route path="*" element={<Navigate to="/dashboard" replace />} />
			</Routes>

			{/* Medication Detail Modal */}
			<MedDetailModal
				selectedMed={stockCorrectionMed}
				coverage={coverage}
				settings={stockThresholds}
				showImageLightbox={showImageLightbox}
				showRefillModal={showRefillModal}
				showEditStockModal={showEditStockModal}
				editStockOnly={showEditStockModal && !selectedMed}
				onClose={closeMedDetail}
				onOpenImageLightbox={openImageLightbox}
				onCloseImageLightbox={closeImageLightbox}
				onOpenRefillModal={openRefillModal}
				onCloseRefillModal={closeRefillModal}
				onOpenMedicationEdit={handleOpenMedicationEdit}
				onOpenEditStockModal={handleOpenEditStockFromDetail}
				onCloseEditStockModal={closeEditStockModal}
				refillPacks={refillPacks}
				onRefillPacksChange={setRefillPacks}
				refillLoose={refillLoose}
				onRefillLooseChange={setRefillLoose}
				usePrescriptionRefill={usePrescriptionRefill}
				onUsePrescriptionRefillChange={setUsePrescriptionRefill}
				refillSaving={refillSaving}
				refillHistory={refillHistory}
				refillHistoryExpanded={refillHistoryExpanded}
				onRefillHistoryExpandedChange={setRefillHistoryExpanded}
				onSubmitRefill={handleSubmitRefill}
				editStockFullBlisters={editStockFullBlisters}
				onEditStockFullBlistersChange={setEditStockFullBlisters}
				editStockPartialBlisterPills={editStockPartialBlisterPills}
				onEditStockPartialBlisterPillsChange={setEditStockPartialBlisterPills}
				editStockLoosePills={editStockLoosePills}
				onEditStockLoosePillsChange={setEditStockLoosePills}
				editStockSaving={editStockSaving}
				onSubmitStockCorrection={handleSubmitStockCorrection}
			/>

			{/* User Medications Modal */}
			<UserFilterModal
				selectedUser={selectedUser}
				meds={meds}
				coverage={coverage}
				settings={stockThresholds}
				onClose={closeUserFilter}
				onClearUser={() => {
					setSelectedUser(null);
					// Replace the userFilter history entry so it doesn't remain on the stack
					window.history.replaceState(null, "");
				}}
				onOpenMedDetail={openMedDetail}
			/>

			{/* Share Dialog Modal */}
			<ShareDialog
				show={showShareDialog}
				sharePeople={sharePeople}
				shareSelectedPerson={shareSelectedPerson}
				onShareSelectedPersonChange={setShareSelectedPerson}
				shareSelectedDays={shareSelectedDays}
				onShareSelectedDaysChange={setShareSelectedDays}
				shareGenerating={shareGenerating}
				shareLink={shareLink}
				onShareLinkChange={setShareLink}
				shareCopied={shareCopied}
				onShareCopiedChange={setShareCopied}
				onClose={closeShareDialog}
				onGenerateShareLink={generateShareLink}
				onCopyShareLink={copyShareLink}
			/>

			{/* Schedule Lightbox - for clicking medication images in schedule */}
			{scheduleLightboxImage && (
				<Lightbox src={scheduleLightboxImage} alt="Medication" onClose={closeScheduleLightbox} />
			)}

			<div className={`route-transition-mask${routeTransitionMaskActive ? " active" : ""}`} aria-hidden="true" />
		</main>
	);
}
