import { useEffect, useMemo, useState } from "react";
import { Routes, Route, useNavigate, useLocation, Navigate, useParams } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { AuthProvider, useAuth, AuthPage, UserProfile } from "./components/Auth";

type Blister = {
	usage: number;
	every: number;
	start: string;
};

type Medication = {
	id: number;
	name: string;
	genericName?: string | null;
	takenBy?: string | null;
	count: number;
	strips: number;
	stripSize: number;
	packCount?: number;
	stripsPerPack?: number;
	tabsPerStrip?: number;
	looseTablets?: number;
	pillWeightMg?: number | null;
	blisters: Blister[];
	imageUrl?: string | null;
	expiryDate?: string | null;
	notes?: string | null;
	intakeRemindersEnabled?: boolean;
	updatedAt: string | number | null;
};

type PlannerRow = {
	medicationId: number;
	medicationName: string;
	totalPills: number;
	plannerUsage: number;
	stripSize: number;
	stripsNeeded: number;
	fullBlisters: number;
	loosePills: number;
	enough: boolean;
};

type FormBlister = { usage: string; every: string; startDate: string; startTime: string };

type FormState = {
	name: string;
	genericName: string;
	takenBy: string;
	packCount: string;
	stripsPerPack: string;
	tabsPerStrip: string;
	looseTablets: string;
	pillWeightMg: string;
	expiryDate: string;
	notes: string;
	intakeRemindersEnabled: boolean;
	blisters: FormBlister[];
};

const defaultBlister = (): FormBlister => {
	const now = new Date();
	return {
		usage: "1",
		every: "1",
		startDate: toDateValue(now),
		startTime: toTimeValue(now)
	};
};

const defaultForm = (): FormState => ({ name: "", genericName: "", takenBy: "", packCount: "1", stripsPerPack: "1", tabsPerStrip: "1", looseTablets: "0", pillWeightMg: "", expiryDate: "", notes: "", intakeRemindersEnabled: false, blisters: [defaultBlister()] });

const todayIso = () => new Date().toISOString();
const plusDaysIso = (days: number) => {
	const d = new Date();
	d.setDate(d.getDate() + days);
	return d.toISOString();
};

type Coverage = {
	name: string;
	medsLeft: number;
	daysLeft: number | null;
	depletionDate: string | null;
	depletionTime: number | null;
	nextDose: string | null;
};

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

function AppRouter() {
	const { user, authState, loading, authError } = useAuth();
	const location = useLocation();
	const navigate = useNavigate();

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

	// Show error if we couldn't connect to the server
	if (authError) {
		return (
			<div className="auth-container">
				<div className="auth-card" style={{ textAlign: "center" }}>
					<h1 className="auth-title">💊 MedAssist</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">
				<div className="auth-card" style={{ textAlign: "center" }}>
					<h1 className="auth-title">💊 MedAssist</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 <AppContent />;
}

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

// Helper for user-specific localStorage keys
function userStorageKey(userId: number | undefined, key: string): string {
	return userId ? `user_${userId}_${key}` : key;
}

function AppContent() {
	const { t, i18n } = useTranslation();
	const { user, authState, logout } = useAuth();
	const [showProfile, setShowProfile] = useState(false);
	const [meds, setMeds] = useState<Medication[]>([]);
	const [plannerRows, setPlannerRows] = useState<PlannerRow[]>([]);
	const [plannerLoading, setPlannerLoading] = useState(false);
	const [loading, setLoading] = useState(false);
	const [saving, setSaving] = useState(false);
	const [editingId, setEditingId] = useState<number | null>(null);
	const [showEditModal, setShowEditModal] = useState(false);
	const [form, setForm] = useState<FormState>(defaultForm());
	const [range, setRange] = useState<{ start: string; end: string }>({
		start: toInputValue(todayIso()),
		end: toInputValue(plusDaysIso(3))
	});

	// Load user-specific planner data when user changes
	useEffect(() => {
		if (typeof window !== "undefined" && user?.id) {
			const savedRows = localStorage.getItem(userStorageKey(user.id, "plannerRows"));
			const savedRange = localStorage.getItem(userStorageKey(user.id, "plannerRange"));
			
			if (savedRows) {
				try { setPlannerRows(JSON.parse(savedRows)); } catch { setPlannerRows([]); }
			} else {
				setPlannerRows([]);
			}
			
			if (savedRange) {
				try { setRange(JSON.parse(savedRange)); } catch { /* keep default */ }
			} else {
				setRange({ start: toInputValue(todayIso()), end: toInputValue(plusDaysIso(3)) });
			}
		}
	}, [user?.id]);

	const navigate = useNavigate();
	const location = useLocation();
	const currentPath = location.pathname;

	// Settings state
	const [settings, setSettings] = useState({
		emailEnabled: false,
		notificationEmail: "",
		reminderDaysBefore: 7,
		repeatDailyReminders: false,
		lowStockDays: 30,
		normalStockDays: 90,
		highStockDays: 180,
		smtpHost: "",
		smtpPort: 587,
		smtpUser: "",
		smtpPass: "",
		smtpFrom: "",
		smtpSecure: false,
		hasSmtpPassword: false,
		lastAutoEmailSent: null as string | null,
		nextScheduledCheck: null as string | null,
		lastNotificationType: null as "stock" | "intake" | null,
		lastNotificationChannel: null as "email" | "push" | "both" | null,
		// Shoutrrr/ntfy settings
		shoutrrrEnabled: false,
		shoutrrrUrl: "",
		// Granular notification settings
		emailStockReminders: true,
		emailIntakeReminders: true,
		shoutrrrStockReminders: true,
		shoutrrrIntakeReminders: true,
		// Admin settings (from .env, read-only)
		expiryWarningDays: 30,
	});
	const [savedSettings, setSavedSettings] = useState(settings);
	const [settingsLoading, setSettingsLoading] = useState(false);
	const [settingsSaving, setSettingsSaving] = useState(false);
	const [settingsSaved, setSettingsSaved] = useState(false);
	const [testingEmail, setTestingEmail] = useState(false);
	const [testEmailResult, setTestEmailResult] = useState<{ success: boolean; message: string } | null>(null);
	const [testingShoutrrr, setTestingShoutrrr] = useState(false);
	const [testShoutrrrResult, setTestShoutrrrResult] = useState<{ success: boolean; message: string } | null>(null);
	const [sendingPlannerEmail, setSendingPlannerEmail] = useState(false);
	const [plannerEmailResult, setPlannerEmailResult] = useState<{ success: boolean; message: string } | null>(null);
	const [sendingReminderEmail, setSendingReminderEmail] = useState(false);
	const [reminderEmailResult, setReminderEmailResult] = useState<{ success: boolean; message: string } | null>(null);
	const [uploadingImage, setUploadingImage] = useState(false);
	const [pendingImage, setPendingImage] = useState<File | null>(null);
	const [pendingImagePreview, setPendingImagePreview] = useState<string | null>(null);
	const [selectedMed, setSelectedMed] = useState<Medication | null>(null);
	const [showImageLightbox, setShowImageLightbox] = useState(false);
	const [selectedUser, setSelectedUser] = useState<string | null>(null);
	const [scheduleDays, setScheduleDays] = useState<number>(30);
	const [showPastDays, setShowPastDays] = useState(false);
	const [takenDoses, setTakenDoses] = useState<Set<string>>(new Set());
	// Share dialog state
	const [showShareDialog, setShowShareDialog] = useState(false);
	const [sharePeople, setSharePeople] = useState<string[]>([]);
	const [shareSelectedPerson, setShareSelectedPerson] = useState<string>("");
	const [shareSelectedDays, setShareSelectedDays] = useState<number>(30);
	const [shareGenerating, setShareGenerating] = useState(false);
	const [shareLink, setShareLink] = useState<string | null>(null);
	const [shareCopied, setShareCopied] = useState(false);
	// Collapsed days state (manually collapsed days are persisted)
	const [manuallyCollapsedDays, setManuallyCollapsedDays] = useState<Set<string>>(new Set());
	const [manuallyExpandedDays, setManuallyExpandedDays] = useState<Set<string>>(new Set());

	// Load user-specific scheduleDays and takenDoses when user changes
	useEffect(() => {
		if (typeof window !== "undefined" && user?.id) {
			const storedDays = localStorage.getItem(userStorageKey(user.id, "scheduleDays"));
			setScheduleDays(storedDays ? Number(storedDays) : 30);
			
			// Load manually collapsed/expanded days from localStorage
			const storedCollapsed = localStorage.getItem(userStorageKey(user.id, "collapsedDays"));
			const storedExpanded = localStorage.getItem(userStorageKey(user.id, "expandedDays"));
			try {
				setManuallyCollapsedDays(storedCollapsed ? new Set(JSON.parse(storedCollapsed)) : new Set());
				setManuallyExpandedDays(storedExpanded ? new Set(JSON.parse(storedExpanded)) : new Set());
			} catch {
				setManuallyCollapsedDays(new Set());
				setManuallyExpandedDays(new Set());
			}
			
			// Load taken doses from server
			async function loadTakenDoses() {
				try {
					const res = await fetch("/api/doses/taken", { credentials: "include" });
					if (res.ok) {
						const data = await res.json();
						setTakenDoses(new Set(data.doses.map((d: { doseId: string }) => d.doseId)));
					}
					// Don't reset on error - keep current state
				} catch {
					// Don't reset on error - keep current state
				}
			}
			loadTakenDoses();
			
			// Poll for updates every 5 seconds (real-time sync with share links)
			const interval = setInterval(loadTakenDoses, 5000);
			return () => clearInterval(interval);
		}
	}, [user?.id]);

	async function markDoseTaken(doseId: string) {
		// Optimistic update
		setTakenDoses((prev) => {
			const next = new Set(prev);
			next.add(doseId);
			return next;
		});
		
		// Send to server
		try {
			await fetch("/api/doses/taken", {
				method: "POST",
				headers: { "Content-Type": "application/json" },
				credentials: "include",
				body: JSON.stringify({ doseId }),
			});
		} catch {
			// Revert on error
			setTakenDoses((prev) => {
				const next = new Set(prev);
				next.delete(doseId);
				return next;
			});
		}
	}

	async function undoDoseTaken(doseId: string) {
		// Optimistic update
		setTakenDoses((prev) => {
			const next = new Set(prev);
			next.delete(doseId);
			return next;
		});
		
		// Send to server
		try {
			await fetch(`/api/doses/taken/${encodeURIComponent(doseId)}`, {
				method: "DELETE",
				credentials: "include",
			});
		} catch {
			// Revert on error
			setTakenDoses((prev) => {
				const next = new Set(prev);
				next.add(doseId);
				return next;
			});
		}
	}

	// Close modal on Escape key
	useEffect(() => {
		const handleEscape = (e: KeyboardEvent) => {
			if (e.key === "Escape") {
				// Close modals in order of priority (topmost first)
				if (showImageLightbox) {
					setShowImageLightbox(false);
				} else if (showEditModal) {
					setShowEditModal(false);
					resetForm();
				} else if (showShareDialog) {
					setShowShareDialog(false);
				} else if (showProfile) {
					setShowProfile(false);
				} else if (selectedUser) {
					setSelectedUser(null);
				} else if (selectedMed) {
					setSelectedMed(null);
				}
			}
		};
		document.addEventListener("keydown", handleEscape);
		return () => document.removeEventListener("keydown", handleEscape);
	}, [selectedMed, showImageLightbox, selectedUser, showProfile, showShareDialog, showEditModal]);

	// Check if settings have changed
	const settingsChanged = settings.emailEnabled !== savedSettings.emailEnabled ||
		settings.notificationEmail !== savedSettings.notificationEmail ||
		settings.reminderDaysBefore !== savedSettings.reminderDaysBefore ||
		settings.repeatDailyReminders !== savedSettings.repeatDailyReminders ||
		settings.lowStockDays !== savedSettings.lowStockDays ||
		settings.normalStockDays !== savedSettings.normalStockDays ||
		settings.highStockDays !== savedSettings.highStockDays ||
		settings.shoutrrrEnabled !== savedSettings.shoutrrrEnabled ||
		settings.shoutrrrUrl !== savedSettings.shoutrrrUrl;

	const schedule = useMemo(() => buildSchedulePreview(meds, i18n.language, true), [meds, i18n.language]);
	const totalTablets = useMemo(() => deriveTotal(form), [form]);
	const coverage = useMemo(() => calculateCoverage(meds, schedule.events, i18n.language, settings.reminderDaysBefore), [meds, schedule.events, i18n.language, settings.reminderDaysBefore]);
	const depletionByMed = useMemo(() => Object.fromEntries(coverage.all.map((c) => [c.name, c.depletionTime])), [coverage.all]);
	const coverageByMed = useMemo(() => Object.fromEntries(coverage.all.map((c) => [c.name, c])), [coverage.all]);

	// Get worst stock status for a day's medications (for coloring day blocks)
	const getDayStockStatus = (dayMeds: { medName: string; lastWhen: number }[]) => {
		const statuses = dayMeds.map((item) => {
			const cov = coverageByMed[item.medName];
			const depletionTime = depletionByMed[item.medName];
			
			// Will be out of stock by this day?
			if (typeof depletionTime === "number" && item.lastWhen > depletionTime) {
				return "danger";
			}
			
			if (!cov) return "success";
			const { daysLeft, medsLeft } = cov;
			
			// Currently out of stock
			if (medsLeft <= 0 || daysLeft === 0) return "danger";
			// No schedule (can't calculate)
			if (daysLeft === null) return "success";
			// Low stock: < lowStockDays (warning)
			if (daysLeft < settings.lowStockDays) return "warning";
			// Normal/High stock
			return "success";
		});
		return statuses.includes("danger") ? "danger" : statuses.includes("warning") ? "warning" : "success";
	};

	const groupedSchedule = useMemo(() => {
		type DoseInfo = { id: string; timeStr: string; when: number; usage: number };
		const days = new Map<string, { dateStr: string; date: Date; isPast: boolean; meds: Map<string, { medName: string; total: number; doses: DoseInfo[]; lastWhen: number }> }>();
		schedule.events.slice(0, 2000).forEach((event) => {
			const day = days.get(event.dateStr) ?? { dateStr: event.dateStr, date: new Date(event.when), isPast: event.isPast, meds: new Map() };
			const medEntry = day.meds.get(event.medName) ?? { medName: event.medName, total: 0, doses: [], lastWhen: event.when };
			medEntry.total += event.usage;
			medEntry.doses.push({ id: event.id, timeStr: event.timeStr, when: event.when, usage: event.usage });
			medEntry.lastWhen = Math.max(medEntry.lastWhen, event.when);
			day.meds.set(event.medName, medEntry);
			days.set(event.dateStr, day);
		});
		return Array.from(days.values()).map((d) => ({ dateStr: d.dateStr, date: d.date, isPast: d.isPast, meds: Array.from(d.meds.values()) }));
	}, [schedule.events]);

	const pastDays = useMemo(() => groupedSchedule.filter(d => d.isPast), [groupedSchedule]);
	const futureDays = useMemo(() => groupedSchedule.filter(d => !d.isPast).slice(0, scheduleDays), [groupedSchedule, scheduleDays]);

	useEffect(() => {
		loadMeds();
		loadSettings();
	}, []);

	function loadMeds() {
		setLoading(true);
		fetch("/api/medications")
			.then((res) => res.json())
			.then((data: Medication[]) => setMeds(data))
			.catch(() => setMeds([]))
			.finally(() => setLoading(false));
	}

	function loadSettings() {
		setSettingsLoading(true);
		fetch("/api/settings")
			.then((res) => res.json())
			.then((data) => {
				const newSettings = { ...settings, ...data, smtpPass: "" };
				setSettings(newSettings);
				setSavedSettings(newSettings);
				setSettingsSaved(false);
			})
			.catch(() => {})
			.finally(() => setSettingsLoading(false));
	}

	async function saveSettings(e: React.FormEvent) {
		e.preventDefault();
		
		// Auto-disable email if no recipient is set
		const effectiveEmailEnabled = settings.emailEnabled && !!settings.notificationEmail?.trim();
		// Auto-disable push if no URL is set
		const effectiveShoutrrrEnabled = settings.shoutrrrEnabled && !!settings.shoutrrrUrl?.trim();
		
		// Validate email if email notifications are enabled
		if (effectiveEmailEnabled && settings.notificationEmail) {
			const emailRegex = /^[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,}$/i;
			if (!emailRegex.test(settings.notificationEmail)) {
				setTestEmailResult({ success: false, message: "Invalid email address" });
				return;
			}
		}
		
		setSettingsSaving(true);
		setTestEmailResult(null);
		
		const payload = {
			emailEnabled: effectiveEmailEnabled,
			notificationEmail: settings.notificationEmail,
			reminderDaysBefore: settings.reminderDaysBefore,
			repeatDailyReminders: settings.repeatDailyReminders,
			lowStockDays: settings.lowStockDays,
			normalStockDays: settings.normalStockDays,
			highStockDays: settings.highStockDays,
			shoutrrrEnabled: effectiveShoutrrrEnabled,
			shoutrrrUrl: settings.shoutrrrUrl,
			// Granular notification settings
			emailStockReminders: settings.emailStockReminders,
			emailIntakeReminders: settings.emailIntakeReminders,
			shoutrrrStockReminders: settings.shoutrrrStockReminders,
			shoutrrrIntakeReminders: settings.shoutrrrIntakeReminders,
			// Language setting (for backend notifications)
			language: i18n.language,
			// SMTP (legacy - not saved, read from .env)
			smtpHost: settings.smtpHost,
			smtpPort: settings.smtpPort,
			smtpUser: settings.smtpUser,
			smtpPass: settings.smtpPass || undefined,
			smtpFrom: settings.smtpFrom,
			smtpSecure: settings.smtpSecure,
		};

		await fetch("/api/settings", {
			method: "PUT",
			headers: { "Content-Type": "application/json" },
			body: JSON.stringify(payload),
		}).catch(() => null);

		// Update local state with effective values
		const updatedSettings = { 
			...settings, 
			emailEnabled: effectiveEmailEnabled,
			shoutrrrEnabled: effectiveShoutrrrEnabled 
		};
		setSettings(updatedSettings);
		setSettingsSaving(false);
		setSavedSettings(updatedSettings);
		setSettingsSaved(true);
	}

	async function testEmail() {
		if (!settings.notificationEmail) return;
		setTestingEmail(true);
		setTestEmailResult(null);

		try {
			const res = await fetch("/api/settings/test-email", {
				method: "POST",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify({ email: settings.notificationEmail }),
			});
			const data = await res.json();
			if (res.ok) {
				setTestEmailResult({ success: true, message: data.message || "Email sent!" });
			} else {
				setTestEmailResult({ success: false, message: data.error || "Failed to send" });
			}
		} catch {
			setTestEmailResult({ success: false, message: "Network error" });
		}
		setTestingEmail(false);
	}

	async function testShoutrrr() {
		if (!settings.shoutrrrUrl) return;
		setTestingShoutrrr(true);
		setTestShoutrrrResult(null);

		try {
			const res = await fetch("/api/settings/test-shoutrrr", {
				method: "POST",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify({ url: settings.shoutrrrUrl }),
			});
			const data = await res.json();
			if (res.ok) {
				setTestShoutrrrResult({ success: true, message: data.message || "Notification sent!" });
			} else {
				setTestShoutrrrResult({ success: false, message: data.error || "Failed to send" });
			}
		} catch {
			setTestShoutrrrResult({ success: false, message: "Network error" });
		}
		setTestingShoutrrr(false);
	}

	async function sendPlannerEmail() {
		if (!settings.notificationEmail || plannerRows.length === 0) return;
		setSendingPlannerEmail(true);
		setPlannerEmailResult(null);

		try {
			const res = await fetch("/api/planner/send-email", {
				method: "POST",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify({
					email: settings.notificationEmail,
					from: range.start,
					until: range.end,
					rows: plannerRows,
				}),
			});
			const data = await res.json();
			if (res.ok) {
				setPlannerEmailResult({ success: true, message: data.message || "Email sent!" });
			} else {
				setPlannerEmailResult({ success: false, message: data.error || "Failed to send" });
			}
		} catch {
			setPlannerEmailResult({ success: false, message: "Network error" });
		}
		setSendingPlannerEmail(false);
	}

	async function sendReminderEmail() {
		if (!settings.notificationEmail || coverage.low.length === 0) return;
		setSendingReminderEmail(true);
		setReminderEmailResult(null);

		try {
			const res = await fetch("/api/reminder/send-email", {
				method: "POST",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify({
					email: settings.notificationEmail,
					lowStock: coverage.low,
				}),
			});
			const data = await res.json();
			if (res.ok) {
				setReminderEmailResult({ success: true, message: data.message || "Email sent!" });
				// Reload settings to get updated lastAutoEmailSent
				loadSettings();
			} else {
				setReminderEmailResult({ success: false, message: data.error || "Failed to send" });
			}
		} catch {
			setReminderEmailResult({ success: false, message: "Network error" });
		}
		setSendingReminderEmail(false);
	}

	async function deleteMed(id: number) {
		await fetch(`/api/medications/${id}`, { method: "DELETE" }).catch(() => null);
		if (editingId === id) resetForm();
		loadMeds();
	}

	async function uploadMedImage(medId: number, file: File) {
		setUploadingImage(true);
		const formData = new FormData();
		formData.append("file", file);
		
		try {
			const res = await fetch(`/api/medications/${medId}/image`, {
				method: "POST",
				body: formData,
			});
			if (res.ok) {
				loadMeds();
			}
		} catch {
			// ignore
		}
		setUploadingImage(false);
	}

	async function deleteMedImage(medId: number) {
		await fetch(`/api/medications/${medId}/image`, { method: "DELETE" }).catch(() => null);
		loadMeds();
	}

	function setBlisterValue(idx: number, field: keyof FormBlister, value: string) {
		setForm((prev) => {
			const next = [...prev.blisters];
			next[idx] = { ...next[idx], [field]: value };
			return { ...prev, blisters: next };
		});
	}

	function addBlister() {
		setForm((prev) => ({ ...prev, blisters: [...prev.blisters, defaultBlister()] }));
	}

	function removeBlister(idx: number) {
		setForm((prev) => ({ ...prev, blisters: prev.blisters.filter((_, i) => i !== idx) }));
	}

	function startEdit(med: Medication) {
		setEditingId(med.id);
		setForm({
			name: med.name,
			genericName: med.genericName ?? "",
			takenBy: med.takenBy ?? "",
			packCount: String(med.packCount ?? 1),
			stripsPerPack: String(med.stripsPerPack ?? med.strips ?? 1),
			tabsPerStrip: String(med.tabsPerStrip ?? med.stripSize ?? 1),
			looseTablets: String(med.looseTablets ?? 0),
			pillWeightMg: med.pillWeightMg ? String(med.pillWeightMg) : "",
			expiryDate: med.expiryDate ? med.expiryDate.slice(0, 10) : "",
			notes: med.notes ?? "",
			intakeRemindersEnabled: med.intakeRemindersEnabled ?? false,
			blisters: med.blisters.map((s) => ({ 
				usage: String(s.usage), 
				every: String(s.every), 
				startDate: toDateValue(s.start),
				startTime: toTimeValue(s.start)
			})),
		});
		// Show modal on mobile
		if (window.innerWidth <= 768) {
			setShowEditModal(true);
		}
	}

	function resetForm() {
		setEditingId(null);
		setShowEditModal(false);
		setPendingImage(null);
		setPendingImagePreview(null);
		setForm(defaultForm());
	}

	function handleValueChange<K extends keyof FormState>(key: K, value: string) {
		setForm((prev) => ({ ...prev, [key]: value }));
	}

	async function saveMedication(e: React.FormEvent) {
		e.preventDefault();
		if (!form.name.trim()) return;
		setSaving(true);

		const payload = {
			name: form.name.trim(),
			genericName: form.genericName.trim() || null,
			takenBy: form.takenBy.trim() || null,
			packCount: Number(form.packCount) || 0,
			stripsPerPack: Math.max(1, Number(form.stripsPerPack) || 1),
			tabsPerStrip: Math.max(1, Number(form.tabsPerStrip) || 1),
			looseTablets: Math.max(0, Number(form.looseTablets) || 0),
			pillWeightMg: form.pillWeightMg ? Number(form.pillWeightMg) : null,
			expiryDate: form.expiryDate || null,
			notes: form.notes.trim() || null,
			intakeRemindersEnabled: form.intakeRemindersEnabled,
			blisters: form.blisters.map((s) => ({ 
				usage: Number(s.usage) || 0, 
				every: Math.max(1, Number(s.every) || 1), 
				start: toIsoString(combineDateAndTime(s.startDate, s.startTime))
			})),
		};

		const method = editingId ? "PUT" : "POST";
		const url = editingId ? `/api/medications/${editingId}` : "/api/medications";

		try {
			const res = await fetch(url, { method, headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) });
			
			// If creating new medication and we have a pending image, upload it
			if (!editingId && pendingImage && res.ok) {
				const newMed = await res.json();
				if (newMed?.id) {
					await uploadMedImage(newMed.id, pendingImage);
				}
			}
		} catch {
			// ignore
		}

		setSaving(false);
		resetForm();
		loadMeds();
	}

	async function runPlanner(e: React.FormEvent) {
		e.preventDefault();
		setPlannerLoading(true);
		const body = { startDate: toIsoString(range.start), endDate: toIsoString(range.end) };
		const rows = await fetch("/api/medications/usage", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) })
			.then((res) => res.json())
			.catch(() => []) as PlannerRow[];
		setPlannerRows(rows);
		setPlannerLoading(false);
		// Save to user-specific localStorage
		if (user?.id) {
			localStorage.setItem(userStorageKey(user.id, "plannerRange"), JSON.stringify(range));
			localStorage.setItem(userStorageKey(user.id, "plannerRows"), JSON.stringify(rows));
		}
	}

	function resetRange() {
		setRange({ start: toInputValue(todayIso()), end: toInputValue(plusDaysIso(3)) });
		setPlannerRows([]);
		if (user?.id) {
			localStorage.removeItem(userStorageKey(user.id, "plannerRange"));
			localStorage.removeItem(userStorageKey(user.id, "plannerRows"));
		}
	}

	// Share dialog functions
	async function openShareDialog() {
		setShowShareDialog(true);
		setShareLink(null);
		setShareCopied(false);
		setShareSelectedPerson("");
		setShareSelectedDays(30);
		
		// Get unique takenBy people from medications
		const uniquePeople = [...new Set(meds.map(m => m.takenBy).filter(Boolean))] as string[];
		setSharePeople(uniquePeople);
		if (uniquePeople.length > 0) {
			setShareSelectedPerson(uniquePeople[0]);
		}
	}

	async function generateShareLink() {
		if (!shareSelectedPerson) return;
		setShareGenerating(true);
		setShareCopied(false);
		
		try {
			const res = await fetch("/api/share", {
				method: "POST",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify({
					takenBy: shareSelectedPerson,
					scheduleDays: shareSelectedDays,
				}),
			});
			
			if (res.ok) {
				const data = await res.json();
				const fullUrl = `${window.location.origin}/share/${data.token}`;
				setShareLink(fullUrl);
			} else {
				const err = await res.json();
				alert(err.error || "Failed to generate share link");
			}
		} catch {
			alert("Failed to generate share link");
		} finally {
			setShareGenerating(false);
		}
	}

	function copyShareLink() {
		if (shareLink) {
			navigator.clipboard.writeText(shareLink);
			setShareCopied(true);
			setTimeout(() => setShareCopied(false), 2000);
		}
	}

	function closeShareDialog() {
		setShowShareDialog(false);
		setShareLink(null);
		setShareCopied(false);
	}

	// Toggle day collapse/expand
	function toggleDayCollapse(dateStr: string, isAutoCollapsed: boolean) {
		if (isAutoCollapsed) {
			// Day is auto-collapsed (all taken) - toggle the expanded override
			setManuallyExpandedDays((prev) => {
				const next = new Set(prev);
				if (next.has(dateStr)) {
					next.delete(dateStr);
				} else {
					next.add(dateStr);
				}
				if (user?.id) localStorage.setItem(userStorageKey(user.id, "expandedDays"), JSON.stringify([...next]));
				return next;
			});
		} else {
			// Day is not auto-collapsed - toggle manual collapse
			setManuallyCollapsedDays((prev) => {
				const next = new Set(prev);
				if (next.has(dateStr)) {
					next.delete(dateStr);
				} else {
					next.add(dateStr);
				}
				if (user?.id) localStorage.setItem(userStorageKey(user.id, "collapsedDays"), JSON.stringify([...next]));
				return next;
			});
		}
	}

	const [theme, setTheme] = useState<"light" | "dark">(() => {
		if (typeof window !== "undefined") {
			return (localStorage.getItem("theme") as "light" | "dark") || "dark";
		}
		return "dark";
	});

	useEffect(() => {
		document.documentElement.setAttribute("data-theme", theme);
		localStorage.setItem("theme", theme);
	}, [theme]);

	function toggleTheme() {
		setTheme((prev) => (prev === "dark" ? "light" : "dark"));
	}

	// Page titles based on current route
	const pageInfo = {
		"/dashboard": { eyebrow: t('header.eyebrow.overview'), title: t('nav.dashboard') },
		"/medications": { eyebrow: t('header.eyebrow.inventory'), title: t('nav.medications') },
		"/planner": { eyebrow: t('header.eyebrow.planner'), title: t('nav.planner') },
		"/settings": { eyebrow: t('header.eyebrow.settings'), title: t('nav.settings') },
		"/schedule": { eyebrow: t('header.eyebrow.schedule'), title: t('dashboard.schedules.title') },
	}[currentPath] || { eyebrow: t('header.eyebrow.overview'), title: t('nav.dashboard') };

	return (
		<main className="page">
			<header className="hero">
				<div className="hero-title">
					<img src="/favicon.svg" alt="MedAssist-ng" className="hero-logo" />
					<div>
						<p className="eyebrow">{pageInfo.eyebrow}</p>
						<h1>{pageInfo.title}</h1>
					</div>
				</div>
				<div className="header-actions">
					<div className="tabs">
						<button className={currentPath === "/dashboard" || currentPath === "/" ? "pill primary" : "pill"} onClick={() => navigate("/dashboard")}>{t('nav.dashboard')}</button>
						<button className={currentPath === "/medications" ? "pill primary" : "pill"} onClick={() => navigate("/medications")}>{t('nav.medications')}</button>
						<button className={currentPath === "/planner" ? "pill primary" : "pill"} onClick={() => navigate("/planner")}>{t('nav.planner')}</button>
					</div>
					{/* Settings button only shown when auth is disabled (no user dropdown available) */}
					{!authState?.authEnabled && (
						<button className={`icon-btn ${currentPath === "/settings" ? "active" : ""}`} onClick={() => navigate("/settings")} title={t('nav.settings')}>⚙️</button>
					)}
					<button className="icon-btn" onClick={toggleTheme} title={theme === "dark" ? t('tooltips.lightMode') : t('tooltips.darkMode')}>
						{theme === "dark" ? "☀️" : "🌙"}
					</button>
					{authState?.authEnabled && user && (
						<div className="user-menu">
							<button className="user-menu-btn">
								{user.avatarUrl ? (
									<img src={`/api/images/${user.avatarUrl}`} alt={user.username} className="user-avatar-img" />
								) : (
									<span className="user-avatar">{user.username.charAt(0).toUpperCase()}</span>
								)}
							</button>
							<div className="user-dropdown">
								<div className="dropdown-header">
									{user.avatarUrl ? (
										<img src={`/api/images/${user.avatarUrl}`} alt={user.username} className="dropdown-avatar-img" />
									) : (
										<div className="dropdown-avatar">{user.username.charAt(0).toUpperCase()}</div>
									)}
									<span className="dropdown-username">{user.username}</span>
								</div>
								<div className="dropdown-menu">
									<button className="dropdown-item" onClick={() => setShowProfile(true)}>
										<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
										{t('auth.profile', 'Profile')}
									</button>
									<button className="dropdown-item" onClick={() => navigate('/settings')}>
										<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
										{t('nav.settings', 'Settings')}
									</button>
									<button className="dropdown-item danger" onClick={() => logout()}>
										<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>
										{t('auth.signOut', 'Sign Out')}
									</button>
								</div>
							</div>
						</div>
					)}
				</div>
			</header>

			{/* Profile Modal */}
			{showProfile && (
				<div className="modal-overlay" onClick={() => setShowProfile(false)}>
					<div className="modal-content profile-modal" onClick={(e) => e.stopPropagation()}>
						<button className="modal-close" onClick={() => setShowProfile(false)}>×</button>
						<UserProfile onClose={() => setShowProfile(false)} />
					</div>
				</div>
			)}

			<Routes>
				<Route path="/" element={<Navigate to="/dashboard" replace />} />
				<Route path="/dashboard" element={
					<>
						{(settings.emailEnabled || settings.shoutrrrEnabled) && (
							<section className="email-status-bar">
								<span className="email-status-icon">{settings.emailEnabled && settings.shoutrrrEnabled ? "🔔" : settings.emailEnabled ? "📧" : "🔔"}</span>
								<span className="email-status-text">
									{t('dashboard.reminders.active')} — {getReminderStatusText(settings.reminderDaysBefore, settings.lowStockDays, coverage.low, coverage.all, settings.lastAutoEmailSent, settings.lastNotificationType, settings.lastNotificationChannel, t, i18n.language)}
								</span>
								{settings.emailEnabled && settings.notificationEmail && <span className="email-status-recipient">→ {settings.notificationEmail}</span>}
							</section>
						)}
						<section className="grid">
							<article className="card">
								<div className="card-head">
									<h2>{t('dashboard.reorder.title')}</h2>
								</div>
								{(() => {
									if (meds.length === 0) {
										return <p className="muted">{t('dashboard.reorder.noMeds')}</p>;
									}
									
									// Count medications with "Low" stock status (based on lowStockDays setting)
									const lowStockCount = coverage.all.filter(c => {
										if (c.medsLeft <= 0) return true; // out of stock
										if (c.daysLeft === null) return false; // no schedule
										return c.daysLeft < settings.lowStockDays;
									}).length;
									
									if (coverage.low.length === 0) {
										// No critical meds (≤3 days)
										if (lowStockCount === 0) {
											// All good - everything is Normal or High
											return <p className="success-text">{t('dashboard.reorder.allGood')}</p>;
										} else {
											// Some meds are Low but not critical
											return <p className="warning-text">{t('dashboard.reorder.lowWarning', { count: lowStockCount })}</p>;
										}
									}
									
									return (
										<>
											<div className="table table-7">
											<div className="table-head">
												<span>{t('table.name')}</span>
												<span>{t('table.fullBlisters')}</span>
												<span>{t('table.openBlister')}</span>
												<span>{t('table.daysLeft')}</span>
												<span>{t('table.status')}</span>
												<span>{t('table.runsOut')}</span>
												<span>{t('table.autoRemind')}</span>
											</div>
											{coverage.low.map((row) => {
												const status = getStockStatus(row.daysLeft, row.medsLeft, settings);
												const med = meds.find(m => m.name === row.name);
												const textClass = status.className === "danger" ? "danger-text" : status.className === "warning" ? "warning-text" : "success-text";
												const stock = getBlisterStock(
													Math.round(row.medsLeft), 
													med?.tabsPerStrip ?? 1,
													med?.looseTablets ?? 0,
													med?.count ?? Math.round(row.medsLeft)
												);
												return (
													<div key={row.name} className="table-row clickable" onClick={() => med && setSelectedMed(med)}>
														<span data-label={t('table.name')} className="cell-with-avatar">
															<MedicationAvatar name={row.name} imageUrl={med?.imageUrl} />
															<span className="med-name-text">{row.name}</span>
															{med?.takenBy && <span className="taken-by-badge clickable" onClick={(e) => { e.stopPropagation(); setSelectedUser(med.takenBy!); }}>{med.takenBy}</span>}
															{(med?.intakeRemindersEnabled || med?.notes) && (
																<span className="med-icons">
																	{med?.intakeRemindersEnabled && <span className="reminder-icon info-tooltip" data-tooltip={t('tooltips.intakeReminders')}>🔔</span>}
																	{med?.notes && <span className="notes-icon info-tooltip" data-tooltip={t('tooltips.hasNotes')}>📝</span>}
																</span>
															)}
														</span>
														<span data-label={t('table.fullBlisters')} className={textClass}>{formatFullBlisters(stock.fullBlisters, t)}</span>
														<span data-label={t('table.openBlister')} className={textClass}>{formatOpenBlisterAndLoose(stock.openBlisterPills, stock.loosePills, med?.tabsPerStrip ?? 1, t)}</span>
														<span data-label={t('table.days')} className={textClass}>{formatNumber(row.daysLeft)}</span>
														<span data-label={t('table.status')} className={`status-chip ${status.className}`}>{t(status.label)}</span>
														<span data-label={t('table.runsOut')}>{row.depletionDate ?? "-"}</span>
														<span data-label={t('table.autoRemind')} className="next-reminder-date">{getNextReminderForMed(row, settings.reminderDaysBefore, i18n.language)}</span>
													</div>
												);
											})}
										</div>
										{(settings.emailEnabled || settings.shoutrrrEnabled) && (
											<div className="email-send-action">
												<button type="button" className="ghost" onClick={sendReminderEmail} disabled={sendingReminderEmail}>
													{sendingReminderEmail ? t('common.sending') : t('dashboard.reorder.sendReminder')}
												</button>
												{reminderEmailResult && (
													<span className={reminderEmailResult.success ? "success-text" : "danger-text"}>
														{reminderEmailResult.message}
													</span>
												)}
											</div>
										)}
									</>
									);
								})()}
							</article>
						</section>

						<section className="grid">
							<article className="card">
								<div className="card-head">
									<h2>{t('dashboard.overview.title')}</h2>
								</div>
								<div className="table table-7">
									<div className="table-head">
										<span>{t('table.name')}</span>
										<span>{t('table.fullBlisters')}</span>
										<span>{t('table.openBlister')}</span>
										<span>{t('table.daysLeft')}</span>
										<span>{t('table.runsOut')}</span>
										<span>{t('table.expiry')}</span>
										<span>{t('table.status')}</span>
									</div>
									{coverage.all.map((row) => {
										const status = getStockStatus(row.daysLeft, row.medsLeft, settings);
										const med = meds.find(m => m.name === row.name);
										const expiryClass = getExpiryClass(med?.expiryDate, settings.expiryWarningDays);
										const textClass = status.className === "danger" ? "danger-text" : status.className === "warning" ? "warning-text" : "success-text";
										const stock = getBlisterStock(
											Math.round(row.medsLeft), 
											med?.tabsPerStrip ?? 1,
											med?.looseTablets ?? 0,
											med?.count ?? Math.round(row.medsLeft)
										);
										return (
											<div key={row.name} className="table-row clickable" onClick={() => med && setSelectedMed(med)}>
												<span data-label={t('table.name')} className="cell-with-avatar">
													<span className="med-name-line">
														<MedicationAvatar name={row.name} imageUrl={med?.imageUrl} />
														<span className="med-name-text">{row.name}</span>
														{med?.takenBy && <span className="taken-by-badge clickable" onClick={(e) => { e.stopPropagation(); setSelectedUser(med.takenBy!); }}>{med.takenBy}</span>}
													</span>
													{(med?.intakeRemindersEnabled || med?.notes) && (
														<span className="med-icons">
															{med?.intakeRemindersEnabled && <span className="reminder-icon info-tooltip" data-tooltip={t('tooltips.intakeReminders')}>🔔</span>}
															{med?.notes && <span className="notes-icon info-tooltip" data-tooltip={t('tooltips.hasNotes')}>📝</span>}
														</span>
													)}
												</span>
												<span data-label={t('table.fullBlisters')} className={textClass}>{formatFullBlisters(stock.fullBlisters, t)}</span>
												<span data-label={t('table.openBlister')} className={textClass}>{formatOpenBlisterAndLoose(stock.openBlisterPills, stock.loosePills, med?.tabsPerStrip ?? 1, t)}</span>
												<span data-label={t('table.daysLeft')} className={textClass}>{formatNumber(row.daysLeft)}</span>
												<span data-label={t('table.runsOut')}>{row.depletionDate ?? "-"}</span>
												<span data-label={t('table.expiry')} className={expiryClass}>{med?.expiryDate ? new Date(med.expiryDate).toLocaleDateString(i18n.language, { day: "2-digit", month: "short", year: "2-digit" }) : "-"}</span>
												<span data-label={t('table.status')} className={`status-chip ${status.className}`}>{t(status.label)}</span>
											</div>
										);
									})}
								</div>
							</article>
						</section>

						<section className="grid">
							<article className="card">
								<div className="card-head">
									<h2>{t('dashboard.schedules.title')}</h2>
									<div className="card-head-actions">
										{meds.some(m => m.takenBy) && (
											<button className="ghost share-btn" onClick={openShareDialog} title={t('share.button')}>
												🔗 {t('share.button')}
											</button>
										)}
										<select 
											className="schedule-days-select"
											value={scheduleDays}
											onChange={(e) => {
												const val = Number(e.target.value);
												setScheduleDays(val);
												if (user?.id) localStorage.setItem(userStorageKey(user.id, "scheduleDays"), String(val));
											}}
										>
											<option value={30}>{t('dashboard.schedules.1month')}</option>
											<option value={90}>{t('dashboard.schedules.3months')}</option>
											<option value={180}>{t('dashboard.schedules.6months')}</option>
										</select>
									</div>
								</div>
								<div className="timeline">
									{/* Past days toggle */}
									{pastDays.length > 0 && (() => {
										const totalPastDoses = pastDays.flatMap(d => d.meds.flatMap(m => m.doses.map(dose => dose.id)));
										const missedPastDoses = totalPastDoses.filter(id => !takenDoses.has(id)).length;
										return (
											<div 
												className={`past-days-toggle ${showPastDays ? 'expanded' : ''} ${missedPastDoses > 0 ? 'has-missed' : ''}`}
												onClick={() => setShowPastDays(!showPastDays)}
											>
												<span className="past-days-icon">{showPastDays ? '▼' : '▶'}</span>
												<span className="past-days-label">
													{showPastDays ? t('dashboard.schedules.hidePastDays') : t('dashboard.schedules.showPastDays')}
												</span>
												<span className="past-days-count">({t('dashboard.schedules.pastDaysCount', { count: pastDays.length })})</span>
												{missedPastDoses > 0 ? (
													<span className="past-days-warning" title={t('dashboard.schedules.missedDoses', { count: missedPastDoses })}>⚠️ {missedPastDoses}</span>
												) : totalPastDoses.length > 0 ? (
													<span className="past-days-complete" title={t('dashboard.schedules.allTaken')}>✓</span>
												) : null}
											</div>
										);
									})()}
									{/* Past days (when expanded) */}
									{showPastDays && pastDays.map((day) => {
										const allDoseIds = day.meds.flatMap((item) => item.doses.map((d) => d.id));
										const allDayTaken = allDoseIds.length > 0 && allDoseIds.every((id) => takenDoses.has(id));
										const takenCount = allDoseIds.filter((id) => takenDoses.has(id)).length;
										const isAutoCollapsed = true; // Past days are always auto-collapsed
										const isManuallyExpanded = manuallyExpandedDays.has(day.dateStr);
										const isCollapsed = !isManuallyExpanded;
										const worstStatus = getDayStockStatus(day.meds);
										
										return (
											<div key={day.dateStr} className={`day-block past ${isCollapsed ? "collapsed" : ""} ${allDayTaken ? "all-taken" : ""} stock-${worstStatus}`}>
												<div 
													className="day-divider clickable" 
													onClick={() => toggleDayCollapse(day.dateStr, isAutoCollapsed)}
													title={isCollapsed ? t('common.expand') : t('common.collapse')}
												>
													<span className="day-collapse-icon">{isCollapsed ? "▶" : "▼"}</span>
													<span className="day-date">{day.dateStr}</span>
													<span className="day-summary">
														{allDayTaken ? (
															<span className="day-complete">✓ {t('dashboard.schedules.allTaken')}</span>
														) : (
															<><span className="day-warning" title={t('dashboard.schedules.missedDoses', { count: allDoseIds.length - takenCount })}>⚠️</span><span className="day-progress">{takenCount}/{allDoseIds.length}</span></>
														)}
													</span>
												</div>
												{!isCollapsed && day.meds.map((item) => {
													const med = meds.find(m => m.name === item.medName);
													const allTaken = item.doses.every((d) => takenDoses.has(d.id));
													return (
														<div key={`${day.dateStr}-${item.medName}`} className={`time-row ${allTaken ? "taken" : ""}`}>
															<div className="time-main">
																<div className="med-name"><MedicationAvatar name={item.medName} imageUrl={med?.imageUrl} size="sm" /><span className="med-name-text">{item.medName}</span>{med?.intakeRemindersEnabled && <span className="reminder-icon info-tooltip" data-tooltip={t('tooltips.intakeReminders')}>🔔</span>}</div>
																<div className="tag-row">
																	<span className="tag subtle">{item.total} {t('common.pills')} {t('common.total')}</span>
																</div>
															</div>
															<div className="doses-col">
																{item.doses.map((dose) => {
																	const isTaken = takenDoses.has(dose.id);
																	return (
																		<div key={dose.id} className={`dose-item past ${isTaken ? "taken" : ""}`}>
																			<span className="dose-time">{dose.timeStr}</span>
																			<span className="dose-usage">{dose.usage} {dose.usage !== 1 ? t('common.pills') : t('common.pill')}{med?.pillWeightMg && ` (${dose.usage * med.pillWeightMg} mg)`}{med?.takenBy && <span className="taken-by-inline"> {t('dose.takenBy')} <span className="taken-by-name clickable" onClick={() => setSelectedUser(med.takenBy!)}>{med.takenBy}</span></span>}</span>
																			{isTaken ? (
																				<button className="dose-btn undo" onClick={() => undoDoseTaken(dose.id)} title={t('common.undo')}>↩</button>
																			) : (
																				<button className="dose-btn take" onClick={() => markDoseTaken(dose.id)} title={t('dose.markAsTaken')}>✓</button>
																			)}
																		</div>
																	);
																})}
															</div>
														</div>
													);
												})}
											</div>
										);
									})}
									{/* Current and future days */}
									{futureDays.map((day) => {
										// Check if all doses in this day are taken (auto-collapse)
										const allDoseIds = day.meds.flatMap((item) => item.doses.map((d) => d.id));
										const allDayTaken = allDoseIds.length > 0 && allDoseIds.every((id) => takenDoses.has(id));
										const takenCount = allDoseIds.filter((id) => takenDoses.has(id)).length;
										
										// Calculate worst stock status for this day
										const dayStockStatuses = day.meds.map((item) => {
											const medCoverage = coverageByMed[item.medName];
											const depletionTime = depletionByMed[item.medName];
											const willBeOutOfStock = typeof depletionTime === "number" && item.lastWhen > depletionTime;
											if (willBeOutOfStock) return "danger";
											if (!medCoverage) return "success";
											const status = getStockStatus(medCoverage.daysLeft, medCoverage.medsLeft, settings);
											return status.className;
										});
										const worstStatus = dayStockStatuses.includes("danger") ? "danger" : dayStockStatuses.includes("warning") ? "warning" : "success";
										
										// Check if this is today, past, or future
										const today = new Date();
										today.setHours(0, 0, 0, 0);
										const dayDate = new Date(day.date);
										dayDate.setHours(0, 0, 0, 0);
										const isToday = dayDate.getTime() === today.getTime();
										
										// Determine if day should be collapsed: only today is expanded by default
										const isAutoCollapsed = allDayTaken || !isToday;
										const isManuallyExpanded = manuallyExpandedDays.has(day.dateStr);
										const isManuallyCollapsed = manuallyCollapsedDays.has(day.dateStr);
										const isCollapsed = isAutoCollapsed ? !isManuallyExpanded : isManuallyCollapsed;
										
										return (
											<div key={day.dateStr} className={`day-block ${isCollapsed ? "collapsed" : ""} ${allDayTaken ? "all-taken" : ""} ${isToday ? "today" : ""} ${worstStatus ? `stock-${worstStatus}` : ""}`}>
												<div 
													className="day-divider clickable" 
													onClick={() => toggleDayCollapse(day.dateStr, isAutoCollapsed)}
													title={isCollapsed ? t('common.expand') : t('common.collapse')}
												>
													<span className="day-collapse-icon">{isCollapsed ? "▶" : "▼"}</span>
													<span className="day-date">{day.dateStr}</span>
													<span className="day-summary">
														{allDayTaken ? (
															<span className="day-complete">✓ {t('dashboard.schedules.allTaken')}</span>
														) : (
															<span className="day-progress">{takenCount}/{allDoseIds.length}</span>
														)}
													</span>
												</div>
												{!isCollapsed && day.meds.map((item) => {
													const medCoverage = coverageByMed[item.medName];
													const med = meds.find(m => m.name === item.medName);
													const depletionTime = depletionByMed[item.medName];
													// Check if this dose is scheduled after medication runs out
													const willBeOutOfStock = typeof depletionTime === "number" && item.lastWhen > depletionTime;
													const status = willBeOutOfStock 
														? { className: "danger", label: "status.outOfStock" }
														: medCoverage ? getStockStatus(medCoverage.daysLeft, medCoverage.medsLeft, settings) : null;
													const allTaken = item.doses.every((d) => takenDoses.has(d.id));
													return (
														<div key={`${day.dateStr}-${item.medName}`} className={`time-row ${allTaken ? "taken" : ""}`}>
															<div className="time-main">
																<div className="med-name"><MedicationAvatar name={item.medName} imageUrl={med?.imageUrl} size="sm" /><span className="med-name-text">{item.medName}</span>{med?.intakeRemindersEnabled && <span className="reminder-icon info-tooltip" data-tooltip={t('tooltips.intakeReminders')}>🔔</span>}</div>
																<div className="tag-row">
																	<span className="tag subtle">{item.total} {t('common.pills')} {t('common.total')}</span>
																	{status && <span className={`tag ${status.className}`}>
																		{t(status.label)}
																	</span>}
																</div>
															</div>
															<div className="doses-col">
																{item.doses.map((dose) => {
																	const isTaken = takenDoses.has(dose.id);
																	const isOverdue = dose.when < Date.now();
																	// Only disable doses on future DAYS, not later today
																	const doseDate = new Date(dose.when);
																	doseDate.setHours(0, 0, 0, 0);
																	const todayMidnight = new Date();
																	todayMidnight.setHours(0, 0, 0, 0);
																	const isFutureDose = doseDate.getTime() > todayMidnight.getTime();
																	return (
																		<div key={dose.id} className={`dose-item ${isTaken ? "taken" : ""} ${isOverdue ? "overdue" : ""} ${isFutureDose ? "future" : ""}`}>
																			<span className="dose-time">{dose.timeStr}</span>
																			<span className="dose-usage">{dose.usage} {dose.usage !== 1 ? t('common.pills') : t('common.pill')}{med?.pillWeightMg && ` (${dose.usage * med.pillWeightMg} mg)`}{med?.takenBy && <span className="taken-by-inline"> {t('dose.takenBy')} <span className="taken-by-name clickable" onClick={() => setSelectedUser(med.takenBy!)}>{med.takenBy}</span></span>}</span>
																			{isTaken ? (
																				<button className="dose-btn undo" onClick={() => undoDoseTaken(dose.id)} title={t('common.undo')}>↩</button>
																			) : (
																				<button className="dose-btn take" onClick={() => markDoseTaken(dose.id)} title={t('dose.markAsTaken')} disabled={isFutureDose}>✓</button>
																			)}
																		</div>
																	);
																})}
															</div>
														</div>
													);
												})}
											</div>
										);
									})}
								</div>
							</article>
						</section>
					</>
				} />

				<Route path="/medications" element={
					<section className="grid">
						<article className="card meds">
							<div className="card-head">
								<h2>{t('medications.list.title')}</h2>
							</div>
							<div className="med-list">
								{meds.map((med) => (
									<div key={med.id} className="med-row">
										<div className="med-header">
											<div className="med-info">
												<div className="med-name-row">
													<MedicationAvatar name={med.name} imageUrl={med.imageUrl} size="lg" />
													<div className="med-name">{med.name}</div>
												</div>
												<div className="med-details">
													<span>{t('medications.details.packs')}: <strong>{med.packCount ?? 1}</strong></span>
													<span>{t('medications.details.blisters')}: <strong>{med.stripsPerPack ?? med.strips ?? 1}</strong></span>
													<span>{t('medications.details.pillsPerBlister')}: <strong>{med.tabsPerStrip ?? med.stripSize}</strong></span>
													<span>{t('medications.details.loose')}: <strong>{med.looseTablets ?? 0}</strong></span>
												</div>
												<div className="med-total">{t('medications.details.total')}: {med.count} {t('common.pills')}</div>
											</div>
											<div className="med-actions">
												<button className="ghost" onClick={() => startEdit(med)}>{t('common.edit')}</button>
												<button className="ghost danger" onClick={() => deleteMed(med.id)}>{t('common.delete')}</button>
											</div>
										</div>
										<div className="blister-list">
											{med.blisters.map((s, idx) => (
												<div key={`${med.id}-${idx}`} className="blister-row-simple">
													{s.usage} {s.usage === 1 ? t('common.pill') : t('common.pills')} · {t('form.blisters.every')} {s.every} {s.every === 1 ? t('common.day') : t('common.days')} · {t('form.blisters.from')} {formatDateTime(s.start, i18n.language)}
												</div>
											))}
										</div>
									</div>
								))}
							</div>
						</article>

						<article className="card form desktop-only">
							<div className="card-head">
								<h2>{editingId ? t('form.editEntry') : t('form.newEntry')}</h2>
							</div>
							<form className="form-grid" onSubmit={saveMedication}>
								<label>
									{t('form.commercialName')}
									<input value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} placeholder={t('form.placeholders.commercial')} required />
								</label>
								<label>
									{t('form.genericName')}
									<input value={form.genericName} onChange={(e) => setForm({ ...form, genericName: e.target.value })} placeholder={t('form.placeholders.generic')} />
								</label>
								<label>
									{t('form.takenBy')}
									<input value={form.takenBy} onChange={(e) => setForm({ ...form, takenBy: e.target.value })} placeholder={t('form.placeholders.takenBy')} />
								</label>
								<label>
									{t('form.packs')}
									<input type="number" min="0" value={form.packCount} onChange={(e) => handleValueChange("packCount", e.target.value)} />
								</label>
								<label>
									{t('form.blistersPerPack')}
									<input type="number" min="1" value={form.stripsPerPack} onChange={(e) => handleValueChange("stripsPerPack", e.target.value)} />
								</label>
								<label>
									{t('form.pillsPerBlister')}
									<input type="number" min="1" value={form.tabsPerStrip} onChange={(e) => handleValueChange("tabsPerStrip", e.target.value)} />
								</label>
								<label>
									{t('form.loosePills')}
									<input type="number" min="0" value={form.looseTablets} onChange={(e) => handleValueChange("looseTablets", e.target.value)} />
								</label>
								<label>
									{t('form.pillWeight')}
									<input type="number" min="1" value={form.pillWeightMg} onChange={(e) => handleValueChange("pillWeightMg", e.target.value)} placeholder={t('form.placeholders.weight')} />
								</label>
								<label>
									{t('form.total')}
									<div className="static-value">{formatNumber(totalTablets)}</div>
								</label>
								<label>
									{t('form.expiryDate')}
									<input type="date" value={form.expiryDate} onChange={(e) => handleValueChange("expiryDate", e.target.value)} placeholder={t('common.optional')} />
								</label>

								<label className="full">
									{t('form.notes')}
									<textarea 
										value={form.notes} 
										onChange={(e) => handleValueChange("notes", e.target.value)} 
										placeholder={t('form.placeholders.notes')}
										rows={2}
										maxLength={500}
									/>
								</label>

<div className="full blisters">
									<div className="card-head">
											<h3>{t('form.blisters.title')}</h3>
											<div className="blisters-actions">
												<label className="inline-checkbox" title={t('form.blisters.remindTooltip')}>
													<input 
														type="checkbox" 
														checked={form.intakeRemindersEnabled} 
														onChange={(e) => setForm(prev => ({ ...prev, intakeRemindersEnabled: e.target.checked }))}
													/>
													<span>🔔 {t('form.blisters.remind')}</span>
												</label>
												<button type="button" className="ghost" onClick={addBlister}>+ {t('form.blisters.addIntake')}</button>
											</div>
									</div>
									{form.blisters.map((s, idx) => (
										<div key={idx} className="blister-row">
											<div className="blister-inputs">
												<label>
													{t('form.blisters.usage')}
													<input type="number" min="0" step="0.1" value={s.usage} onChange={(e) => setBlisterValue(idx, "usage", e.target.value)} />
												</label>
												<label>
													{t('form.blisters.everyDays')}
													<input type="number" min="1" value={s.every} onChange={(e) => setBlisterValue(idx, "every", e.target.value)} />
												</label>
												<label>
													{t('form.blisters.startDate')}
													<input type="date" value={s.startDate} onChange={(e) => setBlisterValue(idx, "startDate", e.target.value)} />
												</label>
												<label>
													{t('form.blisters.startTime')}
													<input type="time" value={s.startTime} onChange={(e) => setBlisterValue(idx, "startTime", e.target.value)} />
												</label>
											</div>
											{form.blisters.length > 1 && (
												<button type="button" className="ghost" onClick={() => removeBlister(idx)}>{t('common.remove')}</button>
											)}
										</div>
									))}
								</div>

								<div className="full image-upload-section">
									<label className="setting-label">{t('form.medicationImage')}</label>
									{(() => {
										// When editing an existing medication
										if (editingId) {
											const currentMed = meds.find(m => m.id === editingId);
											if (currentMed?.imageUrl) {
												return (
													<div className="image-preview">
														<img src={`/api/images/${currentMed.imageUrl}`} alt={currentMed.name} />
														<button type="button" className="ghost danger" onClick={() => deleteMedImage(editingId)}>{t('form.removeImage')}</button>
													</div>
												);
											}
											return (
												<input 
													type="file" 
													accept="image/jpeg,image/png,image/webp,image/gif"
													onChange={(e) => e.target.files?.[0] && uploadMedImage(editingId, e.target.files[0])}
													disabled={uploadingImage}
												/>
											);
										}
										// When creating a new medication
										if (pendingImagePreview) {
											return (
												<div className="image-preview">
													<img src={pendingImagePreview} alt="Preview" />
													<button type="button" className="ghost danger" onClick={() => { setPendingImage(null); setPendingImagePreview(null); }}>{t('form.removeImage')}</button>
												</div>
											);
										}
										return (
											<input 
												type="file" 
												accept="image/jpeg,image/png,image/webp,image/gif"
												onChange={(e) => {
													const file = e.target.files?.[0];
													if (file) {
														setPendingImage(file);
														const reader = new FileReader();
														reader.onload = (ev) => setPendingImagePreview(ev.target?.result as string);
														reader.readAsDataURL(file);
													}
												}}
											/>
										);
									})()}
								</div>

								<div className="full align-end gap">
									{editingId && (
										<button type="button" className="ghost" onClick={resetForm}>
											{t('common.cancel')}
										</button>
									)}
									<button type="submit" disabled={saving}>{saving ? t('common.saving') : t('common.save')}</button>
								</div>
							</form>
						</article>
					</section>
				} />

				<Route path="/planner" element={
					<section className="grid">
						<article className="card">
							<div className="card-head">
								<h2>{t('planner.title')}</h2>
							</div>
							<form className="planner" onSubmit={runPlanner}>
								<label>
									{t('planner.from')}
									<input type="datetime-local" step="60" value={range.start} onChange={(e) => setRange({ ...range, start: e.target.value })} />
								</label>
								<label>
									{t('planner.until')}
									<input type="datetime-local" step="60" value={range.end} onChange={(e) => setRange({ ...range, end: e.target.value })} />
								</label>
								<div className="planner-actions">
									<button type="button" className="ghost" onClick={resetRange}>{t('common.reset')}</button>
									<button type="submit" disabled={plannerLoading}>{plannerLoading ? t('planner.calculating') : t('planner.calculate')}</button>
								</div>
							</form>
							{plannerRows.length > 0 && (
								<>
									<div className="table">
										<div className="table-head">
											<span>{t('planner.table.medication')}</span>
											<span>{t('planner.table.usage')}</span>
											<span>{t('planner.table.blistersNeeded')}</span>
											<span>{t('planner.table.available')}</span>
											<span>{t('table.status')}</span>
										</div>
										{plannerRows.map((row) => {
											const med = meds.find(m => m.name === row.medicationName);
											return (
												<div key={row.medicationId} className="table-row clickable" onClick={() => med && setSelectedMed(med)}>
													<span data-label={t('planner.table.medication')} className="cell-with-avatar"><MedicationAvatar name={row.medicationName} imageUrl={med?.imageUrl} />{row.medicationName}</span>
													<span data-label={t('planner.table.usage')}><strong>{row.plannerUsage}</strong>&nbsp;{t('common.pills')}</span>
													<span data-label={t('planner.table.blisters')}>{row.stripsNeeded} × {row.stripSize}</span>
													<span data-label={t('planner.table.available')}>
														{row.fullBlisters} {t('common.blisters')}{row.loosePills > 0 && ` + ${row.loosePills} ${t('common.pills')}`}
													</span>
													<span data-label={t('table.status')} className={row.enough ? "status-chip success" : "status-chip danger"}>{row.enough ? t('status.enough') : t('status.outOfStock')}</span>
												</div>
											);
										})}
									</div>
									{settings.emailEnabled && settings.notificationEmail && (
										<div className="planner-email-action">
											<button type="button" className="ghost" onClick={sendPlannerEmail} disabled={sendingPlannerEmail}>
												{sendingPlannerEmail ? t('common.sending') : t('planner.sendEmail')}
											</button>
											{plannerEmailResult && (
												<span className={plannerEmailResult.success ? "success-text" : "danger-text"}>
													{plannerEmailResult.message}
												</span>
											)}
										</div>
									)}
								</>
							)}
						</article>
					</section>
				} />

				<Route path="/settings" element={
					<section className="grid">
						{settingsLoading ? (
							<p>{t('settings.loading')}</p>
						) : (
							<form className="settings-form" onSubmit={saveSettings}>
								{/* Language */}
								<article className="card">
									<div className="card-head">
										<h2>{t('settings.language.title')}</h2>
									</div>
									<div className="setting-section">
										<label className="setting-row language-row">
											<span className="setting-label">{t('settings.language.select')}</span>
											<select
												value={i18n.language}
												onChange={(e) => i18n.changeLanguage(e.target.value)}
												className="language-select"
											>
												<option value="en">🇬🇧 English</option>
												<option value="de">🇩🇪 Deutsch</option>
											</select>
										</label>
									</div>
								</article>

								{/* Notifications */}
								<article className="card">
									<div className="card-head">
										<h2>{t('settings.notifications.title')}</h2>
									</div>
									
									<div className="setting-section">
										<div className="section-header">
											<h3>{t('settings.notifications.channels')}</h3>
										</div>
										<div className="notification-matrix">
											<div className="matrix-header">
												<div className="matrix-label"></div>
												<div className="matrix-channel">{t('settings.notifications.email')}</div>
												<div className="matrix-channel">{t('settings.notifications.push')}</div>
											</div>
											<div className="matrix-row">
												<div className="matrix-label">{t('settings.notifications.stockReminders')}</div>
												<div className="matrix-cell">
													<label className={`toggle-switch small${!settings.emailEnabled ? ' disabled' : ''}`}>
														<input
															type="checkbox"
															checked={settings.emailStockReminders}
															onChange={(e) => setSettings({ ...settings, emailStockReminders: e.target.checked })}
															disabled={!settings.emailEnabled}
														/>
														<span className="toggle-slider"></span>
													</label>
												</div>
												<div className="matrix-cell">
													<label className={`toggle-switch small${!settings.shoutrrrEnabled ? ' disabled' : ''}`}>
														<input
															type="checkbox"
															checked={settings.shoutrrrStockReminders}
															onChange={(e) => setSettings({ ...settings, shoutrrrStockReminders: e.target.checked })}
															disabled={!settings.shoutrrrEnabled}
														/>
														<span className="toggle-slider"></span>
													</label>
												</div>
											</div>
											<div className="matrix-row">
												<div className="matrix-label">{t('settings.notifications.intakeReminders')}</div>
												<div className="matrix-cell">
													<label className={`toggle-switch small${!settings.emailEnabled ? ' disabled' : ''}`}>
														<input
															type="checkbox"
															checked={settings.emailIntakeReminders}
															onChange={(e) => setSettings({ ...settings, emailIntakeReminders: e.target.checked })}
															disabled={!settings.emailEnabled}
														/>
														<span className="toggle-slider"></span>
													</label>
												</div>
												<div className="matrix-cell">
													<label className={`toggle-switch small${!settings.shoutrrrEnabled ? ' disabled' : ''}`}>
														<input
															type="checkbox"
															checked={settings.shoutrrrIntakeReminders}
															onChange={(e) => setSettings({ ...settings, shoutrrrIntakeReminders: e.target.checked })}
															disabled={!settings.shoutrrrEnabled}
														/>
														<span className="toggle-slider"></span>
													</label>
												</div>
											</div>
										</div>
										{!settings.emailEnabled && !settings.shoutrrrEnabled && (
											<p className="hint-text">{t('settings.notifications.enableHint')}</p>
										)}
									</div>

									<div className="setting-section">
										<div className="section-header">
											<h3>{t('settings.notifications.email')}</h3>
											<label className="toggle-switch small">
												<input
													type="checkbox"
													checked={settings.emailEnabled}
													onChange={(e) => setSettings({ ...settings, emailEnabled: e.target.checked })}
												/>
												<span className="toggle-slider"></span>
											</label>
										</div>
										{settings.emailEnabled && (
											<>
												<div className="setting-group">
													<label className="full">
														<span className="field-label">{t('settings.email.recipient')}</span>
														<div className="input-with-tooltip">
															<input
																type="email"
																value={settings.notificationEmail}
																onChange={(e) => setSettings({ ...settings, notificationEmail: e.target.value })}
																placeholder="your@email.com"
																pattern="[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,}$"
																autoComplete="email"
															/>
															<span className="info-tooltip" data-tooltip={`SMTP: ${settings.smtpHost || t('settings.email.notConfigured')}:${settings.smtpPort}${settings.hasSmtpPassword ? '\nPassword: ✓' : ''}`}>ⓘ</span>
														</div>
													</label>
												</div>
												<div className="setting-actions">
													<button type="button" className="ghost" onClick={testEmail} disabled={testingEmail || !settings.notificationEmail}>
														{testingEmail ? t('common.sending') : t('common.test')}
													</button>
													{testEmailResult && (
														<span className={testEmailResult.success ? "success-text" : "danger-text"}>
															{testEmailResult.message}
														</span>
													)}
												</div>
											</>
										)}
									</div>

									<div className="setting-section">
										<div className="section-header">
											<h3>{t('settings.notifications.push')}</h3>
											<label className="toggle-switch small">
												<input
													type="checkbox"
													checked={settings.shoutrrrEnabled}
													onChange={(e) => setSettings({ ...settings, shoutrrrEnabled: e.target.checked })}
												/>
												<span className="toggle-slider"></span>
											</label>
										</div>
										{settings.shoutrrrEnabled && (
											<>
												<div className="setting-group">
													<label className="full">
														<span className="field-label">{t('settings.push.url')}</span>
														<div className="input-with-tooltip">
															<input
																type="url"
																value={settings.shoutrrrUrl}
																onChange={(e) => setSettings({ ...settings, shoutrrrUrl: e.target.value })}
																placeholder="https://ntfy.sh/your-topic"
															/>
															<span className="info-tooltip" data-tooltip={t('settings.push.supports')}>ⓘ</span>
														</div>
													</label>
												</div>
												<div className="setting-actions">
													<button type="button" className="ghost" onClick={testShoutrrr} disabled={testingShoutrrr || !settings.shoutrrrUrl}>
														{testingShoutrrr ? t('common.sending') : t('common.test')}
													</button>
													{testShoutrrrResult && (
														<span className={testShoutrrrResult.success ? "success-text" : "danger-text"}>
															{testShoutrrrResult.message}
														</span>
													)}
												</div>
											</>
										)}
									</div>

									<div className="schedule-overview">
										<div className="schedule-header">
											<span className="schedule-title">{t('settings.schedule.title')}</span>
											<span className="info-tooltip" data-tooltip={t('settings.schedule.envHint')}>ⓘ</span>
										</div>
										<div className="schedule-row">
											<span className="schedule-label">{t('settings.schedule.stockCheck')}</span>
											<span className="schedule-value">{t('settings.schedule.dailyAt6')}</span>
										</div>
										<div className="schedule-row">
											<span className="schedule-label">{t('settings.schedule.intakeCheck')}</span>
											<span className="schedule-value">{t('settings.schedule.15minBefore')}</span>
										</div>
										{settings.nextScheduledCheck && (
											<div className="schedule-row">
												<span className="schedule-label">{t('settings.schedule.nextCheck')}</span>
												<span className="schedule-value">{new Date(settings.nextScheduledCheck).toLocaleString(i18n.language, { day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit" })}</span>
											</div>
										)}
										{settings.lastAutoEmailSent && (
											<div className="schedule-row">
												<span className="schedule-label">{t('settings.schedule.lastSent')}</span>
												<span className="schedule-value">{new Date(settings.lastAutoEmailSent).toLocaleString(i18n.language, { day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit" })}</span>
											</div>
										)}
									</div>
								</article>

								{/* Stock Settings */}
								<article className="card">
									<div className="card-head">
										<h2>{t('settings.stock.title')}</h2>
									</div>
									
									<div className="setting-section">
										<div className="section-header">
											<h3>{t('settings.stock.threshold')}</h3>
										</div>
										<div className="threshold-input">
											<label>
												<span className="threshold-label">{t('settings.stock.remindWhen')}</span>
												<div className="threshold-field">
													<input
														type="number"
														min="1"
														max="90"
														value={settings.reminderDaysBefore}
														onChange={(e) => setSettings({ ...settings, reminderDaysBefore: Number(e.target.value) || 7 })}
													/>
													<span className="threshold-unit">{t('common.days')}</span>
												</div>
											</label>
										</div>
										<div className="setting-row compact">
											<label className="setting-label">
												{t('settings.stock.repeatDaily')}
												<span className="info-tooltip small" data-tooltip={t('settings.stock.repeatTooltip')}>ⓘ</span>
											</label>
											<label className={`toggle-switch small${!((settings.emailEnabled && settings.emailStockReminders && settings.notificationEmail) || (settings.shoutrrrEnabled && settings.shoutrrrStockReminders && settings.shoutrrrUrl)) ? ' disabled' : ''}`}>
												<input
													type="checkbox"
													checked={settings.repeatDailyReminders}
													onChange={(e) => setSettings({ ...settings, repeatDailyReminders: e.target.checked })}
													disabled={!((settings.emailEnabled && settings.emailStockReminders && settings.notificationEmail) || (settings.shoutrrrEnabled && settings.shoutrrrStockReminders && settings.shoutrrrUrl))}
												/>
												<span className="toggle-slider"></span>
											</label>
										</div>
									</div>

									<div className="setting-section">
										<div className="section-header">
											<h3>{t('settings.stock.display')}</h3>
										</div>
										<div className="setting-group">
											<label>
												<span className="field-label">{t('settings.stock.lowStockDays')}</span>
												<div className="input-with-tooltip">
													<input
														type="number"
														min="1"
														max="365"
														value={settings.lowStockDays}
														onChange={(e) => setSettings({ ...settings, lowStockDays: Number(e.target.value) || 30 })}
													/>
													<span className="info-tooltip" data-tooltip={t('settings.stock.lowStockTooltip')}>ⓘ</span>
												</div>
											</label>
											<label>
												<span className="field-label">{t('settings.stock.highStockDays')}</span>
												<div className="input-with-tooltip">
													<input
														type="number"
														min="1"
														max="730"
														value={settings.highStockDays}
														onChange={(e) => setSettings({ ...settings, highStockDays: Number(e.target.value) || 180 })}
													/>
													<span className="info-tooltip" data-tooltip={t('settings.stock.highStockTooltip')}>ⓘ</span>
												</div>
											</label>
										</div>
									</div>
								</article>

								<div className="form-footer">
									<button type="submit" disabled={settingsSaving || (!settingsChanged && settingsSaved)}>
										{settingsSaving ? t('common.saving') : settingsSaved && !settingsChanged ? t('common.saved') : t('settings.saveSettings')}
									</button>
								</div>
							</form>
						)}
					</section>
				} />

				<Route path="/schedule" element={
					<section className="grid">
						<article className="card schedule-full">
							<div className="card-head">
								<h2>{t('dashboard.schedules.title')}</h2>
								<select 
									className="schedule-days-select"
									value={scheduleDays}
									onChange={(e) => {
										const val = Number(e.target.value);
										setScheduleDays(val);
										if (user?.id) localStorage.setItem(userStorageKey(user.id, "scheduleDays"), String(val));
									}}
								>
									<option value={30}>{t('dashboard.schedules.1month')}</option>
									<option value={90}>{t('dashboard.schedules.3months')}</option>
									<option value={180}>{t('dashboard.schedules.6months')}</option>
								</select>
							</div>
							<div className="timeline">
								{/* Past days toggle */}
								{pastDays.length > 0 && (() => {
									const totalPastDoses = pastDays.flatMap(d => d.meds.flatMap(m => m.doses.map(dose => dose.id)));
									const missedPastDoses = totalPastDoses.filter(id => !takenDoses.has(id)).length;
									return (
										<div 
											className={`past-days-toggle ${showPastDays ? 'expanded' : ''} ${missedPastDoses > 0 ? 'has-missed' : ''}`}
											onClick={() => setShowPastDays(!showPastDays)}
										>
											<span className="past-days-icon">{showPastDays ? '▼' : '▶'}</span>
											<span className="past-days-label">
												{showPastDays ? t('dashboard.schedules.hidePastDays') : t('dashboard.schedules.showPastDays')}
											</span>
											<span className="past-days-count">({t('dashboard.schedules.pastDaysCount', { count: pastDays.length })})</span>
											{missedPastDoses > 0 && <span className="past-days-warning" title={t('dashboard.schedules.missedDoses', { count: missedPastDoses })}>⚠️ {missedPastDoses}</span>}
										</div>
									);
								})()}
								{/* Past days (when expanded) */}
								{showPastDays && pastDays.map((day) => {
									const allDoseIds = day.meds.flatMap((item) => item.doses.map((d) => d.id));
									const allDayTaken = allDoseIds.length > 0 && allDoseIds.every((id) => takenDoses.has(id));
									const takenCount = allDoseIds.filter((id) => takenDoses.has(id)).length;
									const isManuallyExpanded = manuallyExpandedDays.has(day.dateStr);
									const isCollapsed = !isManuallyExpanded;
									const worstStatus = getDayStockStatus(day.meds);
									
									return (
										<div key={day.dateStr} className={`day-block past ${isCollapsed ? "collapsed" : ""} ${allDayTaken ? "all-taken" : ""} stock-${worstStatus}`}>
											<div 
												className="day-divider clickable" 
												onClick={() => toggleDayCollapse(day.dateStr, true)}
												title={isCollapsed ? t('common.expand') : t('common.collapse')}
											>
												<span className="day-collapse-icon">{isCollapsed ? "▶" : "▼"}</span>
												<span className="day-date">{day.dateStr}</span>
												<span className="day-summary">
													{allDayTaken ? (
														<span className="day-complete">✓ {t('dashboard.schedules.allTaken')}</span>
													) : (
														<><span className="day-warning" title={t('dashboard.schedules.missedDoses', { count: allDoseIds.length - takenCount })}>⚠️</span><span className="day-progress">{takenCount}/{allDoseIds.length}</span></>
													)}
												</span>
											</div>
											{!isCollapsed && day.meds.map((item) => {
												const med = meds.find(m => m.name === item.medName);
												const allTaken = item.doses.every((d) => takenDoses.has(d.id));
												return (
													<div key={`${day.dateStr}-${item.medName}`} className={`time-row ${allTaken ? "taken" : ""}`}>
														<div className="time-main">
															<div className="med-name"><MedicationAvatar name={item.medName} imageUrl={med?.imageUrl} size="sm" /><span className="med-name-text">{item.medName}</span>{med?.intakeRemindersEnabled && <span className="reminder-icon info-tooltip" data-tooltip={t('tooltips.intakeReminders')}>🔔</span>}</div>
															<div className="tag-row">
																<span className="tag subtle">{item.total} {t('common.pills')} {t('common.total')}</span>
															</div>
														</div>
														<div className="doses-col">
															{item.doses.map((dose) => {
																const isTaken = takenDoses.has(dose.id);
																return (
																	<div key={dose.id} className={`dose-item past ${isTaken ? "taken" : ""}`}>
																		<span className="dose-time">{dose.timeStr}</span>
																		<span className="dose-usage">{dose.usage} {dose.usage !== 1 ? t('common.pills') : t('common.pill')}{med?.pillWeightMg && ` (${dose.usage * med.pillWeightMg} mg)`}{med?.takenBy && <span className="taken-by-inline"> {t('dose.takenBy')} <span className="taken-by-name clickable" onClick={() => setSelectedUser(med.takenBy!)}>{med.takenBy}</span></span>}</span>
																		{isTaken ? (
																			<button className="dose-btn undo" onClick={() => undoDoseTaken(dose.id)} title={t('common.undo')}>↩</button>
																		) : (
																			<button className="dose-btn take" onClick={() => markDoseTaken(dose.id)} title={t('dose.markAsTaken')}>✓</button>
																		)}
																	</div>
																);
															})}
														</div>
													</div>
												);
											})}
										</div>
									);
								})}
								{/* Current and future days */}
								{futureDays.map((day) => {
									const today = new Date();
									today.setHours(0, 0, 0, 0);
									const dayDate = new Date(day.date);
									dayDate.setHours(0, 0, 0, 0);
									const isToday = dayDate.getTime() === today.getTime();
									return (
									<div key={day.dateStr} className={`day-block ${isToday ? "today" : ""}`}>
										<div className="day-divider">{day.dateStr}</div>
										{day.meds.map((item) => {
											const medCoverage = coverageByMed[item.medName];
											const med = meds.find(m => m.name === item.medName);
											const depletionTime = depletionByMed[item.medName];
											// Check if this dose is scheduled after medication runs out
											const willBeOutOfStock = typeof depletionTime === "number" && item.lastWhen > depletionTime;
											const status = willBeOutOfStock 
												? { className: "danger", label: "status.outOfStock" }
												: medCoverage ? getStockStatus(medCoverage.daysLeft, medCoverage.medsLeft, settings) : null;
											const allTaken = item.doses.every((d) => takenDoses.has(d.id));
											return (
												<div key={`${day.dateStr}-${item.medName}`} className={`time-row ${allTaken ? "taken" : ""}`}>
													<div className="time-main">
														<div className="med-name"><MedicationAvatar name={item.medName} imageUrl={med?.imageUrl} size="sm" /><span className="med-name-text">{item.medName}</span>{med?.intakeRemindersEnabled && <span className="reminder-icon info-tooltip" data-tooltip={t('tooltips.intakeReminders')}>🔔</span>}</div>
														<div className="tag-row">
															<span className="tag subtle">{item.total} {t('common.pills')} {t('common.total')}</span>
															{status && <span className={`tag ${status.className}`}>
																{t(status.label)}
															</span>}
														</div>
													</div>
													<div className="doses-col">
														{item.doses.map((dose) => {
															const isTaken = takenDoses.has(dose.id);
															const isOverdue = !isTaken && dose.when < Date.now();
															return (
																<div key={dose.id} className={`dose-item ${isTaken ? "taken" : ""} ${isOverdue ? "overdue" : ""}`}>
																	<span className="dose-time">{dose.timeStr}</span>
																	<span className="dose-usage">{dose.usage} {dose.usage !== 1 ? t('common.pills') : t('common.pill')}{med?.pillWeightMg && ` (${dose.usage * med.pillWeightMg} mg)`}{med?.takenBy && <span className="taken-by-inline"> {t('dose.takenBy')} <span className="taken-by-name clickable" onClick={() => setSelectedUser(med.takenBy!)}>{med.takenBy}</span></span>}</span>
																	{isTaken ? (
																		<button className="dose-btn undo" onClick={() => undoDoseTaken(dose.id)} title={t('common.undo')}>↩</button>
																	) : (
																		<button className="dose-btn take" onClick={() => markDoseTaken(dose.id)} title={t('dose.markAsTaken')}>✓</button>
																	)}
																</div>
															);
														})}
													</div>
												</div>
											);
										})}
									</div>
								);})}
							</div>
						</article>
					</section>
				} />
				{/* Catch-all: redirect unknown routes to dashboard */}
				<Route path="*" element={<Navigate to="/dashboard" replace />} />
			</Routes>

			{/* Medication Detail Modal */}
			{selectedMed && (
				<div className="modal-overlay" onClick={() => setSelectedMed(null)}>
					<div className="modal-content med-detail-modal" onClick={(e) => e.stopPropagation()}>
						<button className="modal-close" onClick={() => setSelectedMed(null)}>×</button>
						
						<div className="med-detail-header">
							<div 
								className={`med-detail-avatar-wrapper ${selectedMed.imageUrl ? 'clickable' : ''}`}
								onClick={() => selectedMed.imageUrl && setShowImageLightbox(true)}
							>
								<MedicationAvatar name={selectedMed.name} imageUrl={selectedMed.imageUrl} size="lg" />
								{selectedMed.imageUrl && <span className="expand-icon">🔍</span>}
							</div>
							<div className="med-detail-titles">
								<h2>{selectedMed.name}</h2>
								{selectedMed.genericName && <span className="med-generic-name">{selectedMed.genericName}</span>}
								{selectedMed.takenBy && <span className="med-taken-by">{t('modal.for')} {selectedMed.takenBy}</span>}
							</div>
						</div>

						<div className="med-detail-body">
							<div className="med-detail-section">
								<h3>{t('modal.stockInfo')}</h3>
								{(() => {
									const medCoverage = coverage.all.find(c => c.name === selectedMed.name);
									const currentStock = medCoverage ? Math.round(medCoverage.medsLeft) : selectedMed.count;
									const totalStock = (selectedMed.packCount ?? 1) * (selectedMed.stripsPerPack ?? 1) * (selectedMed.tabsPerStrip ?? 1) + (selectedMed.looseTablets ?? 0);
									const status = medCoverage ? getStockStatus(medCoverage.daysLeft, medCoverage.medsLeft, settings) : null;
									const textClass = status?.className === "danger" ? "danger-text" : status?.className === "warning" ? "warning-text" : "success-text";
									const stock = getBlisterStock(
										currentStock, 
										selectedMed.tabsPerStrip ?? 1,
										selectedMed.looseTablets ?? 0,
										selectedMed.count
									);
									return (
								<div className="med-detail-grid">
									<div className="med-detail-item">
										<span className="med-detail-label">{t('table.fullBlisters')}</span>
										<span className={`med-detail-value ${textClass}`}>{formatFullBlisters(stock.fullBlisters, t)}</span>
									</div>
									<div className="med-detail-item">
										<span className="med-detail-label">{t('table.openBlister')}</span>
										<span className={`med-detail-value ${textClass}`}>{formatOpenBlisterAndLoose(stock.openBlisterPills, stock.loosePills, selectedMed.tabsPerStrip ?? 1, t)}</span>
									</div>
									<div className="med-detail-item full-width">
										<span className="med-detail-label">{t('modal.currentStock')}</span>
										<span className={`med-detail-value ${textClass}`}>{currentStock} / {totalStock}</span>
									</div>
								</div>
									);
								})()}
							</div>

							<div className="med-detail-section">
								<h3>{t('modal.packageDetails')}</h3>
								<div className="med-detail-grid">
									<div className="med-detail-item">
										<span className="med-detail-label">{t('modal.packs')}</span>
										<span className="med-detail-value">{selectedMed.packCount ?? 0}</span>
									</div>
									<div className="med-detail-item">
										<span className="med-detail-label">{t('modal.blistersPerPack')}</span>
										<span className="med-detail-value">{selectedMed.stripsPerPack ?? 0}</span>
									</div>
									<div className="med-detail-item">
										<span className="med-detail-label">{t('modal.pillsPerBlister')}</span>
										<span className="med-detail-value">{selectedMed.tabsPerStrip ?? 1}</span>
									</div>
									{selectedMed.pillWeightMg && (
										<div className="med-detail-item">
											<span className="med-detail-label">{t('modal.pillWeight')}</span>
											<span className="med-detail-value">{selectedMed.pillWeightMg} mg</span>
										</div>
									)}
									{selectedMed.expiryDate && (
										<div className="med-detail-item">
											<span className="med-detail-label">{t('modal.expiryDate')}</span>
											<span className={`med-detail-value ${new Date(selectedMed.expiryDate) < new Date() ? 'danger-text' : ''}`}>
												{new Date(selectedMed.expiryDate).toLocaleDateString(i18n.language, { day: "2-digit", month: "short", year: "numeric" })}
											</span>
										</div>
									)}
								</div>
						</div>

							{selectedMed.blisters.length > 0 && (
								<div className="med-detail-section">
									<h3>{t('modal.intakeSchedule')} {selectedMed.intakeRemindersEnabled && <span className="reminder-icon info-tooltip" data-tooltip={t('tooltips.intakeReminders')}>🔔</span>}</h3>
									<div className="med-detail-schedules">
										{selectedMed.blisters.map((blister, idx) => (
											<div key={idx} className="med-schedule-item">
												<span className="med-schedule-usage">{blister.usage} {blister.usage !== 1 ? t('common.pills') : t('common.pill')}{selectedMed.pillWeightMg && ` (${blister.usage * selectedMed.pillWeightMg} mg)`}</span>
												<span className="med-schedule-freq">{t('form.blisters.every')} {blister.every} {blister.every !== 1 ? t('common.days') : t('common.day')}</span>
												<span className="med-schedule-time">{t('modal.at')} {new Date(blister.start).toLocaleTimeString(i18n.language, { hour: "2-digit", minute: "2-digit" })}</span>
											</div>
										))}
									</div>
								</div>
							)}

							{(() => {
								const medCoverage = coverage.all.find(c => c.name === selectedMed.name);
								if (!medCoverage) return null;
								const status = getStockStatus(medCoverage.daysLeft, medCoverage.medsLeft, settings);
								return (
									<div className="med-detail-section">
										<h3 className="section-header-with-badge">
											{t('modal.coverageStatus')}
											<span className={`status-chip small ${status.className}`}>{t(status.label)}</span>
										</h3>
										<div className="med-detail-grid">
											<div className="med-detail-item">
												<span className="med-detail-label">{t('modal.daysLeft')}</span>
												<span className="med-detail-value">{medCoverage.daysLeft !== null ? formatNumber(medCoverage.daysLeft) : "—"}</span>
											</div>
											<div className="med-detail-item">
												<span className="med-detail-label">{t('modal.runsOut')}</span>
												<span className="med-detail-value">{medCoverage.depletionDate ?? "—"}</span>
											</div>
										</div>
									</div>
								);
							})()}

							{selectedMed.notes && (
								<div className="med-detail-section">
									<h3>📝 {t('modal.notes')}</h3>
									<div className="med-notes-content">
										{selectedMed.notes}
									</div>
								</div>
							)}
						</div>

						<div className="med-detail-footer">
							<button onClick={() => { setSelectedMed(null); setShowImageLightbox(false); }}>
								{t('common.close')}
							</button>
							<div className="footer-actions">
								<button className="ghost" onClick={() => { setSelectedMed(null); setShowImageLightbox(false); navigate("/medications"); startEdit(selectedMed); }}>
									{t('common.edit')}
								</button>
								{selectedMed.blisters.length > 0 && (
									<button className="ghost icon-only" onClick={() => generateICS(selectedMed)} title={t('modal.exportTooltip')}>
										📅
									</button>
								)}
							</div>
						</div>
					</div>

					{/* Image Lightbox */}
					{showImageLightbox && selectedMed.imageUrl && (
						<div className="lightbox-overlay" onClick={(e) => { e.stopPropagation(); setShowImageLightbox(false); }}>
							<button className="lightbox-close" onClick={(e) => { e.stopPropagation(); setShowImageLightbox(false); }}>×</button>
							<img 
								src={`/api/images/${selectedMed.imageUrl}`} 
								alt={selectedMed.name} 
								className="lightbox-image"
								onClick={(e) => e.stopPropagation()}
							/>
						</div>
					)}
				</div>
			)}

			{/* User Medications Modal */}
			{selectedUser && (
				<div className="modal-overlay" onClick={() => setSelectedUser(null)}>
					<div className="modal-content user-meds-modal" onClick={(e) => e.stopPropagation()}>
						<button className="modal-close" onClick={() => setSelectedUser(null)}>×</button>
						
						<div className="user-meds-header">
							<div className="user-avatar">{selectedUser.charAt(0).toUpperCase()}</div>
							<h2>{t('modal.userMedications', { name: selectedUser })}</h2>
						</div>

						<div className="user-meds-list">
							{meds.filter(m => m.takenBy === selectedUser).map((med) => {
								const medCoverage = coverage.all.find(c => c.name === med.name);
								const status = medCoverage ? getStockStatus(medCoverage.daysLeft, medCoverage.medsLeft, settings) : null;
								const currentStock = medCoverage ? formatNumber(medCoverage.medsLeft) : formatNumber(med.count);
								return (
									<div 
										key={med.id} 
										className="user-med-item clickable"
										onClick={() => { setSelectedUser(null); setSelectedMed(med); }}
									>
										<MedicationAvatar name={med.name} imageUrl={med.imageUrl} size="sm" />
										<div className="user-med-info">
											<span className="user-med-name">{med.name}</span>
											{med.genericName && <span className="user-med-generic">{med.genericName}</span>}
										</div>
										<div className="user-med-stats">
											<span className="user-med-pills">{currentStock}/{formatNumber(med.count)} {t('common.pills')}</span>
											{status && <span className={`status-chip ${status.className}`}>{t(status.label)}</span>}
										</div>
									</div>
								);
							})}
							{meds.filter(m => m.takenBy === selectedUser).length === 0 && (
								<div className="user-meds-empty">{t('modal.noMedsForUser', { name: selectedUser })}</div>
							)}
						</div>

						<div className="user-meds-footer">
							<button onClick={() => setSelectedUser(null)}>{t('common.close')}</button>
						</div>
					</div>
				</div>
			)}

			{/* Share Dialog Modal */}
			{showShareDialog && (
				<div className="modal-overlay" onClick={closeShareDialog}>
					<div className="modal-content share-dialog-modal" onClick={(e) => e.stopPropagation()}>
						<button className="modal-close" onClick={closeShareDialog}>×</button>
						
						<div className="share-dialog-header">
							<h2>🔗 {t('share.title')}</h2>
							<p className="share-dialog-description">{t('share.description')}</p>
						</div>

						{sharePeople.length === 0 ? (
							<div className="share-dialog-empty">
								<p>{t('share.noPeople')}</p>
							</div>
						) : shareLink ? (
							<div className="share-dialog-result">
								<p className="share-success">{t('share.linkGenerated')}</p>
								<div className="share-link-box">
									<input
										type="text"
										value={shareLink}
										readOnly
										className="share-link-input"
										onClick={(e) => (e.target as HTMLInputElement).select()}
									/>
									<button className="btn-copy" onClick={copyShareLink}>
										{shareCopied ? "✓" : "📋"}
									</button>
								</div>
								{shareCopied && <span className="share-copied-hint">{t('share.copied')}</span>}
								<div className="share-dialog-footer">
									<button className="ghost" onClick={() => { setShareLink(null); setShareCopied(false); }}>
										{t('share.generateAnother')}
									</button>
									<button onClick={closeShareDialog}>{t('common.close')}</button>
								</div>
							</div>
						) : (
							<div className="share-dialog-form">
								<div className="form-group">
									<label>{t('share.selectPerson')}</label>
									<select 
										value={shareSelectedPerson} 
										onChange={(e) => setShareSelectedPerson(e.target.value)}
									>
										{sharePeople.map((person) => (
											<option key={person} value={person}>{person}</option>
										))}
									</select>
								</div>
								
								<div className="form-group">
									<label>{t('share.selectPeriod')}</label>
									<select 
										value={shareSelectedDays} 
										onChange={(e) => setShareSelectedDays(Number(e.target.value))}
									>
										<option value={30}>{t('dashboard.schedules.1month')}</option>
										<option value={90}>{t('dashboard.schedules.3months')}</option>
										<option value={180}>{t('dashboard.schedules.6months')}</option>
									</select>
								</div>

								<div className="share-dialog-footer">
									<button className="ghost" onClick={closeShareDialog}>{t('common.cancel')}</button>
									<button onClick={generateShareLink} disabled={shareGenerating || !shareSelectedPerson}>
										{shareGenerating ? t('share.generating') : t('share.generateLink')}
									</button>
								</div>
							</div>
						)}
					</div>
				</div>
			)}

			{/* Mobile Edit Modal */}
			{showEditModal && (
				<div className="modal-overlay" onClick={() => setShowEditModal(false)}>
					<div className="modal-content edit-modal" onClick={(e) => e.stopPropagation()}>
						<button className="modal-close" onClick={() => { setShowEditModal(false); resetForm(); }}>×</button>
						<div className="edit-modal-header">
							<h2>{editingId ? t('form.editEntry') : t('form.newEntry')}</h2>
						</div>
						<form className="form-grid mobile-edit-form" onSubmit={(e) => { saveMedication(e); setShowEditModal(false); }}>
							<label className="full">
								{t('form.commercialName')}
								<input value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} placeholder={t('form.placeholders.commercial')} required />
							</label>
							<label className="full">
								{t('form.genericName')}
								<input value={form.genericName} onChange={(e) => setForm({ ...form, genericName: e.target.value })} placeholder={t('form.placeholders.generic')} />
							</label>
							<label className="full">
								{t('form.takenBy')}
								<input value={form.takenBy} onChange={(e) => setForm({ ...form, takenBy: e.target.value })} placeholder={t('form.placeholders.takenBy')} />
							</label>
							<label>
								{t('form.packs')}
								<input type="number" min="0" value={form.packCount} onChange={(e) => handleValueChange("packCount", e.target.value)} />
							</label>
							<label>
								{t('form.blistersPerPack')}
								<input type="number" min="0" value={form.stripsPerPack} onChange={(e) => handleValueChange("stripsPerPack", e.target.value)} />
							</label>
							<label>
								{t('form.pillsPerBlister')}
								<input type="number" min="1" value={form.tabsPerStrip} onChange={(e) => handleValueChange("tabsPerStrip", e.target.value)} />
							</label>
							<label>
								{t('form.loosePills')}
								<input type="number" min="0" value={form.looseTablets} onChange={(e) => handleValueChange("looseTablets", e.target.value)} />
							</label>
							<div className="full">
								<p className="sub"><strong>{t('form.total')}:</strong> {deriveTotal(form)} {t('common.pills')}</p>
							</div>
							<label className="full">
								{t('form.pillWeight')}
								<input type="number" min="0" step="0.1" value={form.pillWeightMg} onChange={(e) => setForm({ ...form, pillWeightMg: e.target.value })} placeholder={t('form.placeholders.weight')} />
							</label>
							<label className="full">
								{t('form.expiryDate')}
								<input type="date" value={form.expiryDate} onChange={(e) => setForm({ ...form, expiryDate: e.target.value })} />
							</label>
							<label className="full">
								{t('form.notes')}
								<textarea value={form.notes} onChange={(e) => setForm({ ...form, notes: e.target.value })} placeholder={t('form.placeholders.notes')} rows={2} />
							</label>

							{editingId && (() => {
								const currentMed = meds.find(m => m.id === editingId);
								if (currentMed?.imageUrl) {
									return (
										<div className="full image-field">
											<span className="field-label">{t('form.medicationImage')}</span>
											<div className="image-preview">
												<img src={currentMed.imageUrl} alt={currentMed.name} />
												<button type="button" className="ghost danger" onClick={() => deleteMedImage(editingId)}>{t('form.removeImage')}</button>
											</div>
										</div>
									);
								}
								return (
									<label className="full">
										{t('form.medicationImage')}
										<input type="file" accept="image/*" onChange={(e) => e.target.files?.[0] && uploadMedImage(editingId, e.target.files[0])} />
									</label>
								);
							})()}

							<fieldset className="full blister-section">
								<legend>
									{t('form.blisters.title')}
									<label className="toggle-switch small" title={t('form.blisters.remindTooltip')}>
										<input type="checkbox" checked={form.intakeRemindersEnabled} onChange={(e) => setForm({ ...form, intakeRemindersEnabled: e.target.checked })} />
										<span className="toggle-slider"></span>
									</label>
									<span className="legend-hint">{t('form.blisters.remind')}</span>
								</legend>
								{form.blisters.map((b, idx) => (
									<div key={idx} className="blister-row">
										<label className="compact">
											<span>{t('form.blisters.usage')}</span>
											<input type="number" min="0.5" step="0.5" value={b.usage} onChange={(e) => setBlisterValue(idx, "usage", e.target.value)} />
										</label>
										<label className="compact">
											<span>{t('form.blisters.everyDays')}</span>
											<input type="number" min="1" value={b.every} onChange={(e) => setBlisterValue(idx, "every", e.target.value)} />
										</label>
										<label className="compact full-row">
											<span>{t('form.blisters.startDate')}</span>
											<input type="date" value={b.startDate} onChange={(e) => setBlisterValue(idx, "startDate", e.target.value)} />
										</label>
										<label className="compact time-label">
											<span>{t('form.blisters.startTime')}</span>
											<input type="time" value={b.startTime} onChange={(e) => setBlisterValue(idx, "startTime", e.target.value)} />
										</label>
										{form.blisters.length > 1 && <button type="button" className="ghost danger remove-blister-btn" onClick={() => removeBlister(idx)} title={t('common.delete')}>🗑</button>}
									</div>
								))}
								<button type="button" className="ghost add-blister" onClick={addBlister}>+ {t('form.blisters.addIntake')}</button>
							</fieldset>

							<div className="modal-footer">
								<button type="button" className="ghost" onClick={() => { setShowEditModal(false); resetForm(); }}>
									{t('common.cancel')}
								</button>
								<button type="submit" disabled={saving}>{saving ? t('common.saving') : t('common.save')}</button>
							</div>
						</form>
					</div>
				</div>
			)}
		</main>
	);
}

function deriveTotal(form: FormState) {
	const packCount = Number(form.packCount) || 0;
	const stripsPerPack = Number(form.stripsPerPack) || 0;
	const tabsPerStrip = Number(form.tabsPerStrip) || 1;
	const looseTablets = Number(form.looseTablets) || 0;
	return packCount * stripsPerPack * tabsPerStrip + looseTablets;
}

function toIsoString(value: string) {
	if (!value) return new Date().toISOString();
	// datetime-local input gives us local time without timezone info
	// We need to treat it as local time and convert to ISO
	const date = new Date(value);
	return Number.isNaN(date.getTime()) ? new Date().toISOString() : date.toISOString();
}

function toDateValue(date: Date | string): string {
	const d = typeof date === 'string' ? new Date(date) : date;
	if (Number.isNaN(d.getTime())) {
		const now = new Date();
		return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
	}
	return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
}

function toTimeValue(date: Date | string): string {
	const d = typeof date === 'string' ? new Date(date) : date;
	if (Number.isNaN(d.getTime())) {
		const now = new Date();
		return `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;
	}
	return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
}

function combineDateAndTime(dateStr: string, timeStr: string): string {
	// Combine separate date and time strings into ISO format
	return `${dateStr}T${timeStr}`;
}

function toInputValue(value: string) {
	const date = new Date(value);
	if (Number.isNaN(date.getTime())) {
		// Return current local time in datetime-local format
		const now = new Date();
		const year = now.getFullYear();
		const month = String(now.getMonth() + 1).padStart(2, '0');
		const day = String(now.getDate()).padStart(2, '0');
		const hours = String(now.getHours()).padStart(2, '0');
		const minutes = String(now.getMinutes()).padStart(2, '0');
		return `${year}-${month}-${day}T${hours}:${minutes}`;
	}
	// Convert to local time format for datetime-local input
	const year = date.getFullYear();
	const month = String(date.getMonth() + 1).padStart(2, '0');
	const day = String(date.getDate()).padStart(2, '0');
	const hours = String(date.getHours()).padStart(2, '0');
	const minutes = String(date.getMinutes()).padStart(2, '0');
	return `${year}-${month}-${day}T${hours}:${minutes}`;
}

function formatDateTime(value: string, locale: string) {
	const d = new Date(value);
	if (Number.isNaN(d.getTime())) return value;
	return d.toLocaleString(locale, { weekday: "short", day: "2-digit", month: "short", hour: "2-digit", minute: "2-digit" });
}

function generateICS(med: Medication) {
	const formatICSDate = (date: Date) => {
		return date.toISOString().replace(/[-:]/g, '').replace(/\.\d{3}/, '');
	};
	
	const events = med.blisters.map((blister, idx) => {
		const start = new Date(blister.start);
		const end = new Date(start.getTime() + 15 * 60 * 1000); // 15 min duration
		const interval = blister.every;
		
		const pillInfo = `${blister.usage} pill${blister.usage !== 1 ? 's' : ''}${med.pillWeightMg ? ` (${blister.usage * med.pillWeightMg} mg)` : ''}`;
		const summary = `💊 ${med.name} - ${pillInfo}`;
		const description = [
			`Medication: ${med.name}`,
			med.genericName ? `Generic: ${med.genericName}` : '',
			med.takenBy ? `For: ${med.takenBy}` : '',
			`Dosage: ${pillInfo}`,
			`Frequency: every ${interval} day${interval !== 1 ? 's' : ''}`,
			med.notes ? `Notes: ${med.notes}` : '',
		].filter(Boolean).join('\\n');
		
		return `BEGIN:VEVENT
UID:medassist-ng-${med.id}-${idx}@medassist-ng
DTSTAMP:${formatICSDate(new Date())}
DTSTART:${formatICSDate(start)}
DTEND:${formatICSDate(end)}
RRULE:FREQ=DAILY;INTERVAL=${interval}
SUMMARY:${summary}
DESCRIPTION:${description}
BEGIN:VALARM
TRIGGER:-PT5M
ACTION:DISPLAY
DESCRIPTION:Time to take ${med.name}
END:VALARM
END:VEVENT`;
	}).join('\n');
	
	const ics = `BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//MedAssist-ng//Medication Schedule//EN
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:${med.name} Schedule
${events}
END:VCALENDAR`;
	
	const blob = new Blob([ics], { type: 'text/calendar;charset=utf-8' });
	const url = URL.createObjectURL(blob);
	const link = document.createElement('a');
	link.href = url;
	link.download = `${med.name.replace(/[^a-zA-Z0-9]/g, '_')}_schedule.ics`;
	document.body.appendChild(link);
	link.click();
	document.body.removeChild(link);
	URL.revokeObjectURL(url);
}

function buildSchedulePreview(meds: Medication[], locale: string, includePast: boolean = false) {
	const events: Array<{ id: string; medName: string; timeStr: string; dateStr: string; usage: number; when: number; isPast: boolean }> = [];
	const now = new Date();
	const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate()); // Midnight today
	const end = new Date();
	end.setDate(end.getDate() + 180); // 6 months horizon

	meds.forEach((med) => {
		med.blisters.forEach((blister, idx) => {
			const start = new Date(blister.start);
			if (Number.isNaN(start.getTime())) return;
			for (let d = new Date(start); d <= end; d.setDate(d.getDate() + blister.every)) {
				const isPast = d < todayStart;
				// Skip past events unless includePast is true
				if (isPast && !includePast) continue;
				const whenMs = d.getTime();
				events.push({
					id: `${med.id}-${idx}-${whenMs}`,
					medName: med.name,
					usage: blister.usage,
					when: whenMs,
					isPast,
					timeStr: d.toLocaleTimeString(locale, { hour: "2-digit", minute: "2-digit" }),
					dateStr: d.toLocaleDateString(locale, { weekday: "short", day: "2-digit", month: "short" }),
				});
			}
		});
	});

	events.sort((a, b) => a.when - b.when);

	const todayCount = events.filter((e) => {
		const t = new Date(e.when);
		const n = new Date();
		return t.getFullYear() === n.getFullYear() && t.getMonth() === n.getMonth() && t.getDate() === n.getDate();
	}).length;

	return { events, today: todayCount, nextThree: events.length, totalBlisters: meds.reduce((acc, m) => acc + m.blisters.length, 0) };
}

function formatNumber(value: number | null) {
	if (value === null || Number.isNaN(value)) return "-";
	if (Math.abs(value % 1) < 0.05) return Math.round(value).toLocaleString();
	return value.toFixed(1);
}

// Calculate blister stock with realistic consumption order:
// Loose pills are consumed FIRST, then blisters are opened
function getBlisterStock(
	currentPills: number, 
	tabsPerStrip: number, 
	originalLooseTablets: number,
	originalTotalPills: number
): { fullBlisters: number; openBlisterPills: number; loosePills: number } {
	if (tabsPerStrip <= 0 || tabsPerStrip === 1) {
		return { fullBlisters: 0, openBlisterPills: 0, loosePills: currentPills };
	}
	
	// Calculate how many pills have been consumed
	const consumed = originalTotalPills - currentPills;
	
	// Loose pills are consumed first
	const looseConsumed = Math.min(consumed, originalLooseTablets);
	const loosePillsRemaining = originalLooseTablets - looseConsumed;
	
	// Remaining consumption comes from blisters
	const blisterPillsConsumed = consumed - looseConsumed;
	const originalBlisterPills = originalTotalPills - originalLooseTablets;
	const blisterPillsRemaining = originalBlisterPills - blisterPillsConsumed;
	
	// Calculate full blisters and open blister
	const fullBlisters = Math.floor(blisterPillsRemaining / tabsPerStrip);
	const openBlisterPills = blisterPillsRemaining % tabsPerStrip;
	
	return { fullBlisters, openBlisterPills, loosePills: loosePillsRemaining };
}

// Format full blisters column
function formatFullBlisters(fullBlisters: number, t: (key: string) => string): string {
	if (fullBlisters === 0) return "—";
	return `${fullBlisters} ${fullBlisters === 1 ? t('common.blister') : t('common.blisters')}`;
}

// Format open blister + loose pills column
function formatOpenBlisterAndLoose(
	openBlisterPills: number, 
	loosePills: number, 
	tabsPerStrip: number, 
	t: (key: string) => string
): string {
	// Format open blister part
	const openBlisterText = openBlisterPills > 0 
		? `${openBlisterPills} ${t('common.of')} ${tabsPerStrip} ${t('common.pills')}`
		: t('common.none');
	
	// Format loose pills part (if any)
	if (loosePills > 0) {
		return `${openBlisterText} + ${loosePills} ${t('common.loose')}`;
	}
	
	// No loose pills
	if (openBlisterPills === 0) return "—";
	return openBlisterText;
}

function getExpiryClass(expiryDate: string | null | undefined, expiryWarningDays: number = 30): string {
	if (!expiryDate) return "";
	const now = new Date();
	const expiry = new Date(expiryDate);
	const diffMs = expiry.getTime() - now.getTime();
	const diffDays = diffMs / (1000 * 60 * 60 * 24);
	
	if (diffDays <= 7) return "danger-text"; // 1 week or less (or expired)
	if (diffDays <= expiryWarningDays) return "warning-text"; // within warning period
	return "success-text"; // outside warning period
}

function calculateCoverage(meds: Medication[], events: Array<{ medName: string; when: number }>, locale: string, reminderDaysBefore: number) {
	const MS_PER_DAY = 86_400_000;
	const now = Date.now();

	const coverage: Coverage[] = meds.map((m) => {
		const dailyRate = m.blisters.reduce((sum, s) => sum + (s.every > 0 ? s.usage / s.every : 0), 0);

		let consumed = 0;
		m.blisters.forEach((s) => {
			const start = new Date(s.start).getTime();
			if (Number.isNaN(start) || start > now) return;
			const period = Math.max(1, s.every) * MS_PER_DAY;
			const occurrences = Math.floor((now - start) / period) + 1; // include today if started
			consumed += occurrences * s.usage;
		});

		const medsLeft = Math.max(0, m.count - consumed);
		const rawDaysLeft = dailyRate > 0 ? medsLeft / dailyRate : null;
		const daysLeft = rawDaysLeft !== null ? Math.max(0, Math.floor(rawDaysLeft)) : null; // conservative: round down
		const depletionMs = daysLeft !== null ? now + daysLeft * MS_PER_DAY : null;
		const depletionDate = depletionMs !== null ? new Date(depletionMs).toLocaleDateString(locale, { weekday: "short", day: "2-digit", month: "short" }) : null;
		const nextEvent = events.find((e) => e.medName === m.name);

		return {
			name: m.name,
			medsLeft: Number(medsLeft.toFixed(1)),
			daysLeft,
			depletionDate,
			depletionTime: depletionMs,
			nextDose: nextEvent ? new Date(nextEvent.when).toLocaleString(locale, { weekday: "short", day: "2-digit", month: "short", hour: "2-digit", minute: "2-digit" }) : null,
		};
	});

	const low = coverage.filter((c) => c.medsLeft <= 0 || (c.daysLeft !== null && c.daysLeft <= reminderDaysBefore));
	return { low, all: coverage };
}

function getReminderStatusText(
	reminderDaysBefore: number,
	lowStockDays: number,
	lowStock: Coverage[], 
	allCoverage: Coverage[],
	lastSent: string | null, 
	lastType: "stock" | "intake" | null,
	lastChannel: "email" | "push" | "both" | null,
	t: (key: string, options?: Record<string, unknown>) => string, 
	locale: string
): React.ReactNode {
	// Find the earliest medication that needs a reminder (based on reminderDaysBefore)
	const medsNeedingReminder = lowStock
		.filter((c) => c.depletionTime !== null && c.daysLeft !== null && c.daysLeft <= reminderDaysBefore)
		.sort((a, b) => (a.daysLeft ?? 0) - (b.daysLeft ?? 0));

	const formatLastSent = (iso: string) => {
		const date = new Date(iso);
		return date.toLocaleDateString(locale, { day: "2-digit", month: "short", hour: "2-digit", minute: "2-digit" });
	};

	const getTypeLabel = () => lastType === "intake" ? t('dashboard.reminders.typeIntake') : t('dashboard.reminders.typeStock');
	const getChannelLabel = () => {
		if (lastChannel === "both") return t('dashboard.reminders.channelBoth');
		if (lastChannel === "push") return t('dashboard.reminders.channelPush');
		return t('dashboard.reminders.channelEmail');
	};

	const formatLastInfo = (iso: string) => {
		const dateStr = formatLastSent(iso);
		if (lastType && lastChannel) {
			return `${dateStr} (${getTypeLabel()}, ${getChannelLabel()})`;
		}
		return dateStr;
	};

	if (medsNeedingReminder.length > 0) {
		// There are medications that need reminders
		if (lastSent) {
			return (
				<>
					<strong className="warning-text">⚠ {t('dashboard.reminders.needReorder', { count: medsNeedingReminder.length })}</strong>
					{" · "}{t('dashboard.reminders.lastReminder')}: {formatLastInfo(lastSent)}
				</>
			);
		}
		return <strong className="warning-text">⚠ {t('dashboard.reminders.needReorder', { count: medsNeedingReminder.length })} — {t('dashboard.reminders.waitingFirstCheck')}</strong>;
	}

	// Check if there are low stock medications (not yet needing reminder but running low)
	const lowStockNotYetCritical = allCoverage.filter(
		(c) => c.daysLeft !== null && c.daysLeft > reminderDaysBefore && c.daysLeft < lowStockDays
	);

	if (lowStockNotYetCritical.length > 0) {
		// There are low stock meds but not critical yet
		const nextMed = lowStockNotYetCritical.sort((a, b) => (a.daysLeft ?? 0) - (b.daysLeft ?? 0))[0];
		const daysUntilReminder = (nextMed.daysLeft ?? 0) - reminderDaysBefore;
		return (
			<>
				<span className="warning-text">{t('dashboard.reminders.lowWarning', { count: lowStockNotYetCritical.length })}</span>
				{" · "}{t('dashboard.reminders.nextIn')}: <strong>{nextMed.name}</strong> {t('dashboard.reminders.inDays', { days: daysUntilReminder })}
			</>
		);
	}

	// Calculate when next reminder would be triggered
	const allWithDepletion = lowStock
		.filter((c) => c.depletionTime !== null && c.daysLeft !== null)
		.sort((a, b) => (a.daysLeft ?? Infinity) - (b.daysLeft ?? Infinity));

	if (allWithDepletion.length > 0) {
		const nextMed = allWithDepletion[0];
		const daysUntilReminder = (nextMed.daysLeft ?? 0) - reminderDaysBefore;
		if (daysUntilReminder > 0) {
			return (
				<>
					<span className="success-text">✓ {t('dashboard.reminders.allOk')}</span>
					{" · "}{t('dashboard.reminders.nextIn')}: <strong>{nextMed.name}</strong> {t('dashboard.reminders.inDays', { days: daysUntilReminder })}
				</>
			);
		}
	}

	// No low stock medications at all
	if (lastSent) {
		return (
			<>
				<span className="success-text">✓ {t('dashboard.reminders.allStockOk')}</span>
				{" · "}{t('dashboard.reminders.lastReminder')}: {formatLastInfo(lastSent)}
			</>
		);
	}
	return <span className="success-text">✓ {t('dashboard.reminders.allStockOk')} — {t('dashboard.reminders.noRemindersNeeded')}</span>;
}

function getNextReminderForMed(med: Coverage, reminderDaysBefore: number, locale: string): string {
	if (!med.depletionTime) return "—";
	
	const reminderTime = med.depletionTime - reminderDaysBefore * 86_400_000;
	const now = Date.now();
	
	if (reminderTime <= now) {
		return "Due now";
	}
	
	return new Date(reminderTime).toLocaleDateString(locale, {
		day: "2-digit",
		month: "short",
	});
}

type StockStatus = {
	level: "out-of-stock" | "low" | "normal" | "high";
	className: string;
	label: string;
};

type StockThresholds = {
	lowStockDays: number;
	normalStockDays: number;
	highStockDays: number;
};

function getStockStatus(daysLeft: number | null, medsLeft: number, thresholds: StockThresholds): StockStatus {
	// Out of stock: 0 pills
	if (medsLeft <= 0 || daysLeft === 0) {
		return { level: "out-of-stock", className: "danger", label: "status.outOfStock" };
	}
	
	// No schedule set (no daysLeft calculation possible)
	if (daysLeft === null) {
		return { level: "normal", className: "success", label: "status.noSchedule" };
	}
	
	// High stock: > highStockDays (e.g. > 180 days)
	if (daysLeft > thresholds.highStockDays) {
		return { level: "high", className: "high", label: "status.highStock" };
	}
	
	// Normal stock: between lowStockDays and highStockDays
	if (daysLeft >= thresholds.lowStockDays) {
		return { level: "normal", className: "success", label: "status.normal" };
	}
	
	// Low stock: < lowStockDays (e.g. < 30 days)
	return { level: "low", className: "warning", label: "status.lowStock" };
}

function MedicationAvatar({ name, imageUrl, size = "sm" }: { name: string; imageUrl?: string | null; size?: "sm" | "md" | "lg" }) {
	const initials = name.split(" ").map(w => w[0]).join("").toUpperCase().slice(0, 2) || "?";
	const sizeClass = `med-avatar med-avatar-${size}`;
	
	if (imageUrl) {
		return <img src={`/api/images/${imageUrl}`} alt={name} className={sizeClass} />;
	}
	return <div className={`${sizeClass} med-avatar-initials`}>{initials}</div>;
}

// =============================================================================
// Shared Schedule Component - Public view for shared schedules
// =============================================================================
type SharedMedication = {
	id: number;
	name: string;
	genericName?: string | null;
	pillWeightMg?: number | null;
	imageUrl?: string | null;
	count?: number;
	tabsPerStrip?: number;
	blisters: Blister[];
};

type SharedScheduleData = {
	takenBy: string;
	scheduleDays: number;
	medications: SharedMedication[];
	stockThresholds?: {
		lowStockDays: number;
	};
};

function SharedSchedule() {
	const { token } = useParams<{ token: string }>();
	const { t, i18n } = useTranslation();
	const [data, setData] = useState<SharedScheduleData | null>(null);
	const [loading, setLoading] = useState(true);
	const [error, setError] = useState<string | null>(null);
	const [takenDoses, setTakenDoses] = useState<Set<string>>(new Set());
	const [lightboxImage, setLightboxImage] = useState<{ url: string; name: string } | null>(null);
	const [showPastDays, setShowPastDays] = useState(false);
	// Collapsed days state for SharedSchedule (token-specific localStorage)
	const [manuallyCollapsedDays, setManuallyCollapsedDays] = useState<Set<string>>(new Set());
	const [manuallyExpandedDays, setManuallyExpandedDays] = useState<Set<string>>(new Set());

	// Load collapsed/expanded state from localStorage
	useEffect(() => {
		if (token && typeof window !== "undefined") {
			const storedCollapsed = localStorage.getItem(`share_${token}_collapsedDays`);
			const storedExpanded = localStorage.getItem(`share_${token}_expandedDays`);
			try {
				setManuallyCollapsedDays(storedCollapsed ? new Set(JSON.parse(storedCollapsed)) : new Set());
				setManuallyExpandedDays(storedExpanded ? new Set(JSON.parse(storedExpanded)) : new Set());
			} catch {
				setManuallyCollapsedDays(new Set());
				setManuallyExpandedDays(new Set());
			}
		}
	}, [token]);

	// Toggle day collapse/expand for SharedSchedule
	function toggleDayCollapse(dateStr: string, isAutoCollapsed: boolean) {
		if (isAutoCollapsed) {
			setManuallyExpandedDays((prev) => {
				const next = new Set(prev);
				if (next.has(dateStr)) {
					next.delete(dateStr);
				} else {
					next.add(dateStr);
				}
				if (token) localStorage.setItem(`share_${token}_expandedDays`, JSON.stringify([...next]));
				return next;
			});
		} else {
			setManuallyCollapsedDays((prev) => {
				const next = new Set(prev);
				if (next.has(dateStr)) {
					next.delete(dateStr);
				} else {
					next.add(dateStr);
				}
				if (token) localStorage.setItem(`share_${token}_collapsedDays`, JSON.stringify([...next]));
				return next;
			});
		}
	}

	// Close lightbox on Escape key
	useEffect(() => {
		function handleKeyDown(e: KeyboardEvent) {
			if (e.key === "Escape" && lightboxImage) {
				setLightboxImage(null);
			}
		}
		window.addEventListener("keydown", handleKeyDown);
		return () => window.removeEventListener("keydown", handleKeyDown);
	}, [lightboxImage]);

	// Load taken doses from server with polling for real-time sync
	useEffect(() => {
		if (token) {
			async function loadTakenDoses() {
				try {
					const res = await fetch(`/api/share/${token}/doses`);
					if (res.ok) {
						const data = await res.json();
						setTakenDoses(new Set(data.doses.map((d: { doseId: string }) => d.doseId)));
					} else {
						setTakenDoses(new Set());
					}
				} catch {
					setTakenDoses(new Set());
				}
			}
			loadTakenDoses();
			
			// Poll for updates every 5 seconds (real-time sync with dashboard)
			const interval = setInterval(loadTakenDoses, 5000);
			return () => clearInterval(interval);
		}
	}, [token]);

	async function markDoseTaken(doseId: string) {
		// Optimistic update
		setTakenDoses((prev) => {
			const next = new Set(prev);
			next.add(doseId);
			return next;
		});
		
		// Send to server
		try {
			await fetch(`/api/share/${token}/doses`, {
				method: "POST",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify({ doseId }),
			});
		} catch {
			// Revert on error
			setTakenDoses((prev) => {
				const next = new Set(prev);
				next.delete(doseId);
				return next;
			});
		}
	}

	async function undoDoseTaken(doseId: string) {
		// Optimistic update
		setTakenDoses((prev) => {
			const next = new Set(prev);
			next.delete(doseId);
			return next;
		});
		
		// Send to server
		try {
			await fetch(`/api/share/${token}/doses/${encodeURIComponent(doseId)}`, {
				method: "DELETE",
			});
		} catch {
			// Revert on error
			setTakenDoses((prev) => {
				const next = new Set(prev);
				next.add(doseId);
				return next;
			});
		}
	}

	useEffect(() => {
		async function fetchData() {
			if (!token) {
				setError("Invalid link");
				setLoading(false);
				return;
			}

			try {
				const res = await fetch(`/api/share/${token}`);
				if (res.ok) {
					const json = await res.json();
					setData(json);
				} else {
					setError("Share link not found or expired");
				}
			} catch {
				setError("Failed to load schedule");
			} finally {
				setLoading(false);
			}
		}
		fetchData();
	}, [token]);

	// Build schedule from medications
	const schedule = useMemo(() => {
		if (!data) return [];

		const now = Date.now();
		const todayStart = new Date();
		todayStart.setHours(0, 0, 0, 0);
		const todayStartTime = todayStart.getTime();
		const endTime = now + data.scheduleDays * 24 * 60 * 60 * 1000;
		const doses: { id: string; when: number; medName: string; usage: number; timeStr: string; isPast: boolean }[] = [];

		for (const med of data.medications) {
			med.blisters.forEach((blister, blisterIdx) => {
				const startDate = new Date(blister.start);
				const intervalMs = blister.every * 24 * 60 * 60 * 1000;
				let t = startDate.getTime();

				// Start from the very first dose (blister start)
				while (t <= endTime) {
					const d = new Date(t);
					const isPast = t < todayStartTime;
					// Generate dose ID matching Dashboard format: ${med.id}-${blisterIdx}-${whenMs}
					const doseId = `${med.id}-${blisterIdx}-${t}`;
					doses.push({
						id: doseId,
						when: t,
						medName: med.name,
						usage: blister.usage,
						isPast,
						timeStr: d.toLocaleTimeString(i18n.language, { hour: "2-digit", minute: "2-digit" }),
					});
					t += intervalMs;
				}
			});
		}

		doses.sort((a, b) => a.when - b.when);

		// Group by date
		const grouped: { dateStr: string; date: Date; isPast: boolean; meds: { medName: string; total: number; lastWhen: number; doses: typeof doses }[] }[] = [];
		const byDate = new Map<string, typeof doses>();

		for (const dose of doses) {
			const dateKey = new Date(dose.when).toLocaleDateString(i18n.language, {
				weekday: "long",
				day: "2-digit",
				month: "short",
			});
			if (!byDate.has(dateKey)) byDate.set(dateKey, []);
			byDate.get(dateKey)!.push(dose);
		}

		for (const [dateStr, dayDoses] of byDate) {
			const byMed = new Map<string, typeof doses>();
			for (const dose of dayDoses) {
				if (!byMed.has(dose.medName)) byMed.set(dose.medName, []);
				byMed.get(dose.medName)!.push(dose);
			}
			const meds = Array.from(byMed.entries()).map(([medName, medDoses]) => ({
				medName,
				total: medDoses.reduce((sum, d) => sum + d.usage, 0),
				lastWhen: Math.max(...medDoses.map(d => d.when)),
				doses: medDoses,
			}));
			grouped.push({ dateStr, date: new Date(dayDoses[0].when), isPast: dayDoses[0].isPast, meds });
		}

		return grouped;
	}, [data, i18n.language]);

	const pastDays = useMemo(() => schedule.filter(d => d.isPast), [schedule]);
	const futureDays = useMemo(() => schedule.filter(d => !d.isPast), [schedule]);

	// Calculate coverage for stock status colors (matches main app logic)
	// This needs to account for taken doses and calculate depletion time
	const { coverageByMed, depletionByMed } = useMemo(() => {
		if (!data) return { coverageByMed: {}, depletionByMed: {} };
		const coverage: Record<string, { daysLeft: number | null; medsLeft: number; dailyUsage: number }> = {};
		const depletion: Record<string, number | null> = {};
		
		// Calculate total pills taken per medication from takenDoses
		const takenByMed: Record<string, number> = {};
		for (const dose of schedule.flatMap(d => d.meds.flatMap(m => m.doses))) {
			if (takenDoses.has(dose.id)) {
				takenByMed[dose.medName] = (takenByMed[dose.medName] || 0) + dose.usage;
			}
		}
		
		for (const med of data.medications) {
			const totalCount = med.count ?? 0;
			const taken = takenByMed[med.name] || 0;
			const currentCount = Math.max(0, totalCount - taken);
			// Calculate daily usage from blisters
			const dailyUsage = med.blisters.reduce((sum, b) => sum + (b.usage / b.every), 0);
			const daysLeft = dailyUsage > 0 ? currentCount / dailyUsage : null;
			coverage[med.name] = { daysLeft, medsLeft: currentCount, dailyUsage };
			
			// Calculate depletion time (when medication will run out)
			if (dailyUsage > 0 && currentCount > 0) {
				const daysUntilEmpty = currentCount / dailyUsage;
				depletion[med.name] = Date.now() + daysUntilEmpty * 24 * 60 * 60 * 1000;
			} else if (currentCount <= 0) {
				depletion[med.name] = Date.now(); // Already empty
			} else {
				depletion[med.name] = null; // No usage schedule
			}
		}
		return { coverageByMed: coverage, depletionByMed: depletion };
	}, [data, schedule, takenDoses]);

	// Stock thresholds from user settings (provided by API) or defaults
	const lowStockDays = data?.stockThresholds?.lowStockDays ?? 30;

	// Get worst stock status for a day's medications (matches main app logic with depletion)
	const getDayStockStatus = (meds: { medName: string; lastWhen: number }[]) => {
		const statuses = meds.map((item) => {
			const coverage = coverageByMed[item.medName];
			const depletionTime = depletionByMed[item.medName];
			
			// Will be out of stock by this day?
			if (typeof depletionTime === "number" && item.lastWhen > depletionTime) {
				return "danger";
			}
			
			if (!coverage) return "success";
			const { daysLeft, medsLeft } = coverage;
			
			// Currently out of stock
			if (medsLeft <= 0 || daysLeft === 0) return "danger";
			// No schedule (can't calculate)
			if (daysLeft === null) return "success";
			// Low stock: < lowStockDays (warning)
			if (daysLeft < lowStockDays) return "warning";
			// Normal/High stock
			return "success";
		});
		return statuses.includes("danger") ? "danger" : statuses.includes("warning") ? "warning" : "success";
	};

	if (loading) {
		return (
			<div className="shared-schedule-page">
				<div className="shared-schedule-loading">
					<h1>💊 MedAssist</h1>
					<p>{t('common.loading')}</p>
				</div>
			</div>
		);
	}

	if (error || !data) {
		return (
			<div className="shared-schedule-page">
				<div className="shared-schedule-error">
					<h1>💊 MedAssist</h1>
					<p className="error-message">{error || "Unknown error"}</p>
				</div>
			</div>
		);
	}

	return (
		<div className="shared-schedule-page">
			<div className="shared-schedule-container">
				<header className="shared-schedule-header">
					<h1>💊 {t('share.scheduleFor')} {data.takenBy}</h1>
					<p className="shared-schedule-period">
						{t('share.period')}: {data.scheduleDays === 30 ? t('dashboard.schedules.1month') : data.scheduleDays === 90 ? t('dashboard.schedules.3months') : t('dashboard.schedules.6months')}
					</p>
				</header>

				<div className="timeline">
					{schedule.length === 0 ? (
						<p className="shared-schedule-empty">{t('share.noSchedule')}</p>
					) : (
						<>
							{/* Past days toggle */}
							{pastDays.length > 0 && (() => {
								const totalPastDoses = pastDays.flatMap(d => d.meds.flatMap(m => m.doses.map(dose => dose.id)));
								const missedPastDoses = totalPastDoses.filter(id => !takenDoses.has(id)).length;
								return (
									<div 
										className={`past-days-toggle ${showPastDays ? 'expanded' : ''} ${missedPastDoses > 0 ? 'has-missed' : ''}`}
										onClick={() => setShowPastDays(!showPastDays)}
									>
										<span className="past-days-icon">{showPastDays ? '▼' : '▶'}</span>
										<span className="past-days-label">
											{showPastDays ? t('dashboard.schedules.hidePastDays') : t('dashboard.schedules.showPastDays')}
										</span>
										<span className="past-days-count">({t('dashboard.schedules.pastDaysCount', { count: pastDays.length })})</span>
										{missedPastDoses > 0 ? (
											<span className="past-days-warning" title={t('dashboard.schedules.missedDoses', { count: missedPastDoses })}>⚠️ {missedPastDoses}</span>
										) : totalPastDoses.length > 0 ? (
											<span className="past-days-complete" title={t('dashboard.schedules.allTaken')}>✓</span>
										) : null}
									</div>
								);
							})()}
							{/* Past days (when expanded) */}
							{showPastDays && pastDays.map((day) => {
								const allDoseIds = day.meds.flatMap((item) => item.doses.map((d) => d.id));
								const allDayTaken = allDoseIds.length > 0 && allDoseIds.every((id) => takenDoses.has(id));
								const takenCount = allDoseIds.filter((id) => takenDoses.has(id)).length;
								const isManuallyExpanded = manuallyExpandedDays.has(day.dateStr);
								const isCollapsed = !isManuallyExpanded;
								
								// Calculate stock status for this day
								const worstStatus = getDayStockStatus(day.meds);
								
								return (
									<div key={day.dateStr} className={`day-block past ${isCollapsed ? "collapsed" : ""} ${allDayTaken ? "all-taken" : ""} stock-${worstStatus}`}>
										<div 
											className="day-divider clickable" 
											onClick={() => toggleDayCollapse(day.dateStr, true)}
											title={isCollapsed ? t('common.expand') : t('common.collapse')}
										>
											<span className="day-collapse-icon">{isCollapsed ? "▶" : "▼"}</span>
											<span className="day-date">{day.dateStr}</span>
											<span className="day-summary">
												{allDayTaken ? (
													<span className="day-complete">✓ {t('dashboard.schedules.allTaken')}</span>
												) : (
													<><span className="day-warning" title={t('dashboard.schedules.missedDoses', { count: allDoseIds.length - takenCount })}>⚠️</span><span className="day-progress">{takenCount}/{allDoseIds.length}</span></>
												)}
											</span>
										</div>
										{!isCollapsed && day.meds.map((item) => {
											const med = data.medications.find(m => m.name === item.medName);
											const medCoverage = coverageByMed[item.medName];
											const depletionTime = depletionByMed[item.medName];
											const willBeOutOfStock = typeof depletionTime === "number" && item.lastWhen > depletionTime;
											
											// Calculate status for this medication on this day
											let status: { className: string; label: string } | null = null;
											if (willBeOutOfStock) {
												status = { className: "danger", label: "status.outOfStock" };
											} else if (medCoverage) {
												const { daysLeft, medsLeft } = medCoverage;
												if (medsLeft <= 0 || daysLeft === 0) {
													status = { className: "danger", label: "status.outOfStock" };
												} else if (daysLeft !== null && daysLeft < lowStockDays) {
													status = { className: "warning", label: "status.lowStock" };
												} else {
													status = { className: "success", label: "status.normal" };
												}
											}
											
											const allTaken = item.doses.every((d) => takenDoses.has(d.id));
											return (
												<div key={`${day.dateStr}-${item.medName}`} className={`time-row ${allTaken ? "taken" : ""}`}>
													<div className="time-main">
														<div className="med-name">
															<span 
																className={med?.imageUrl ? 'clickable' : ''}
																onClick={() => med?.imageUrl && setLightboxImage({ url: med.imageUrl, name: med.name })}
															>
																<MedicationAvatar name={item.medName} imageUrl={med?.imageUrl} size="sm" />
															</span>
															<span className="med-name-text">{item.medName}</span>
															{med?.genericName && <span className="med-generic-inline">({med.genericName})</span>}
														</div>
														<div className="tag-row">
															<span className="tag subtle">{item.total} {t('common.pills')} {t('common.total')}</span>
															{status && <span className={`tag ${status.className}`}>{t(status.label)}</span>}
														</div>
													</div>
													<div className="doses-col">
														{item.doses.map((dose) => {
															const isTaken = takenDoses.has(dose.id);
															return (
																<div key={dose.id} className={`dose-item past ${isTaken ? "taken" : ""}`}>
																	<span className="dose-time">{dose.timeStr}</span>
																	<span className="dose-usage">
																		{dose.usage} {dose.usage !== 1 ? t('common.pills') : t('common.pill')}
																		{med?.pillWeightMg && ` (${dose.usage * med.pillWeightMg} mg)`}
																	</span>
																	{isTaken ? (
																		<button className="dose-btn undo" onClick={() => undoDoseTaken(dose.id)} title={t('common.undo')}>↩</button>
																	) : (
																		<button className="dose-btn take" onClick={() => markDoseTaken(dose.id)} title={t('dose.markAsTaken')}>✓</button>
																	)}
																</div>
															);
														})}
													</div>
												</div>
											);
										})}
									</div>
								);
							})}
							{/* Current and future days */}
							{futureDays.map((day) => {
								// Check if all doses in this day are taken (auto-collapse)
								const allDoseIds = day.meds.flatMap((item) => item.doses.map((d) => d.id));
								const allDayTaken = allDoseIds.length > 0 && allDoseIds.every((id) => takenDoses.has(id));
								const takenCount = allDoseIds.filter((id) => takenDoses.has(id)).length;
								
								// Calculate stock status for this day
								const worstStatus = getDayStockStatus(day.meds);
								
								// Check if this is today
								const today = new Date();
								today.setHours(0, 0, 0, 0);
								const dayDate = new Date(day.date);
								dayDate.setHours(0, 0, 0, 0);
								const isToday = dayDate.getTime() === today.getTime();
								
								// Determine if day should be collapsed: only today is expanded by default
								const isAutoCollapsed = allDayTaken || !isToday;
								const isManuallyExpanded = manuallyExpandedDays.has(day.dateStr);
								const isManuallyCollapsed = manuallyCollapsedDays.has(day.dateStr);
								const isCollapsed = isAutoCollapsed ? !isManuallyExpanded : isManuallyCollapsed;
								
								return (
									<div key={day.dateStr} className={`day-block ${isCollapsed ? "collapsed" : ""} ${allDayTaken ? "all-taken" : ""} ${isToday ? "today" : ""} stock-${worstStatus}`}>
										<div 
											className="day-divider clickable" 
											onClick={() => toggleDayCollapse(day.dateStr, isAutoCollapsed)}
											title={isCollapsed ? t('common.expand') : t('common.collapse')}
										>
											<span className="day-collapse-icon">{isCollapsed ? "▶" : "▼"}</span>
											<span className="day-date">{day.dateStr}</span>
											<span className="day-summary">
												{allDayTaken ? (
													<span className="day-complete">✓ {t('dashboard.schedules.allTaken')}</span>
												) : (
													<span className="day-progress">{takenCount}/{allDoseIds.length}</span>
												)}
											</span>
										</div>
										{!isCollapsed && day.meds.map((item) => {
											const med = data.medications.find(m => m.name === item.medName);
											const medCoverage = coverageByMed[item.medName];
											const depletionTime = depletionByMed[item.medName];
											const willBeOutOfStock = typeof depletionTime === "number" && item.lastWhen > depletionTime;
											
											// Calculate status for this medication on this day
											let status: { className: string; label: string } | null = null;
											if (willBeOutOfStock) {
												status = { className: "danger", label: "status.outOfStock" };
											} else if (medCoverage) {
												const { daysLeft, medsLeft } = medCoverage;
												if (medsLeft <= 0 || daysLeft === 0) {
													status = { className: "danger", label: "status.outOfStock" };
												} else if (daysLeft !== null && daysLeft < lowStockDays) {
													status = { className: "warning", label: "status.lowStock" };
												} else {
													status = { className: "success", label: "status.normal" };
												}
											}
											
											const allTaken = item.doses.every((d) => takenDoses.has(d.id));
											return (
												<div key={`${day.dateStr}-${item.medName}`} className={`time-row ${allTaken ? "taken" : ""}`}>
													<div className="time-main">
														<div className="med-name">
															<span 
																className={med?.imageUrl ? 'clickable' : ''}
																onClick={() => med?.imageUrl && setLightboxImage({ url: med.imageUrl, name: med.name })}
															>
																<MedicationAvatar name={item.medName} imageUrl={med?.imageUrl} size="sm" />
															</span>
															<span className="med-name-text">{item.medName}</span>
															{med?.genericName && <span className="med-generic-inline">({med.genericName})</span>}
														</div>
														<div className="tag-row">
															<span className="tag subtle">{item.total} {t('common.pills')} {t('common.total')}</span>
															{status && <span className={`tag ${status.className}`}>{t(status.label)}</span>}
														</div>
													</div>
													<div className="doses-col">
														{item.doses.map((dose) => {
															const isTaken = takenDoses.has(dose.id);
															const isOverdue = dose.when < Date.now() && !isTaken;
															// Only disable doses on future DAYS, not later today
															const doseDate = new Date(dose.when);
															doseDate.setHours(0, 0, 0, 0);
															const todayMidnight = new Date();
															todayMidnight.setHours(0, 0, 0, 0);
															const isFutureDose = doseDate.getTime() > todayMidnight.getTime();
															return (
																<div key={dose.id} className={`dose-item ${isTaken ? "taken" : ""} ${isOverdue ? "overdue" : ""} ${isFutureDose ? "future" : ""}`}>
																	<span className="dose-time">{dose.timeStr}</span>
																	<span className="dose-usage">
																		{dose.usage} {dose.usage !== 1 ? t('common.pills') : t('common.pill')}
																		{med?.pillWeightMg && ` (${dose.usage * med.pillWeightMg} mg)`}
																	</span>
																	{isTaken ? (
																		<button className="dose-btn undo" onClick={() => undoDoseTaken(dose.id)} title={t('common.undo')}>↩</button>
																	) : (
																		<button className="dose-btn take" onClick={() => markDoseTaken(dose.id)} title={t('dose.markAsTaken')} disabled={isFutureDose}>✓</button>
																	)}
																</div>
															);
														})}
													</div>
												</div>
											);
										})}
									</div>
								);
							})}
						</>
					)}
				</div>

				<footer className="shared-schedule-footer">
					<p>{t('share.generatedBy')} MedAssist</p>
				</footer>
			</div>

			{/* Image Lightbox */}
			{lightboxImage && (
				<div className="lightbox-overlay" onClick={() => setLightboxImage(null)}>
					<button className="lightbox-close" onClick={() => setLightboxImage(null)}>×</button>
					<img 
						src={`/api/images/${lightboxImage.url}`} 
						alt={lightboxImage.name} 
						className="lightbox-image"
						onClick={(e) => e.stopPropagation()}
					/>
				</div>
			)}
		</div>
	);
}
