import { useEffect, useMemo, useState } from "react";
import { Routes, Route, useNavigate, useLocation, Navigate } from "react-router-dom";

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

type Medication = {
	id: number;
	name: string;
	genericName?: string | null;
	count: number;
	strips: number;
	stripSize: number;
	packCount?: number;
	stripsPerPack?: number;
	tabsPerStrip?: number;
	looseTablets?: number;
	slices: Slice[];
	imageUrl?: string | null;
	expiryDate?: string | null;
	notes?: string | null;
	updatedAt: string | number | null;
};

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

type FormSlice = { usage: string; every: string; start: string };

type FormState = {
	name: string;
	genericName: string;
	packCount: string;
	stripsPerPack: string;
	tabsPerStrip: string;
	looseTablets: string;
	expiryDate: string;
	notes: string;
	slices: FormSlice[];
};

const defaultSlice = (): FormSlice => ({ usage: "1", every: "1", start: toInputValue(new Date().toISOString()) });

const defaultForm = (): FormState => ({ name: "", genericName: "", packCount: "1", stripsPerPack: "1", tabsPerStrip: "1", looseTablets: "0", expiryDate: "", notes: "", slices: [defaultSlice()] });

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;
};

export default function App() {
	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 [form, setForm] = useState<FormState>(defaultForm());
	const [range, setRange] = useState<{ start: string; end: string }>({ start: toInputValue(todayIso()), end: toInputValue(plusDaysIso(3)) });

	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,
		// Shoutrrr/ntfy settings
		shoutrrrEnabled: false,
		shoutrrrUrl: "",
	});
	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 [selectedMed, setSelectedMed] = useState<Medication | null>(null);
	const [showImageLightbox, setShowImageLightbox] = useState(false);

	// Track taken doses (stored in localStorage)
	const [takenDoses, setTakenDoses] = useState<Set<string>>(() => {
		try {
			const stored = localStorage.getItem("takenDoses");
			if (stored) {
				const parsed = JSON.parse(stored);
				// Clean up old entries (older than 7 days)
				const weekAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
				const filtered = parsed.filter((item: { id: string; timestamp: number }) => item.timestamp > weekAgo);
				return new Set(filtered.map((item: { id: string }) => item.id));
			}
		} catch {}
		return new Set();
	});

	function markDoseTaken(doseId: string) {
		setTakenDoses((prev) => {
			const next = new Set(prev);
			next.add(doseId);
			// Persist with timestamp for cleanup
			const items = Array.from(next).map((id) => ({ id, timestamp: Date.now() }));
			localStorage.setItem("takenDoses", JSON.stringify(items));
			return next;
		});
	}

	function undoDoseTaken(doseId: string) {
		setTakenDoses((prev) => {
			const next = new Set(prev);
			next.delete(doseId);
			const items = Array.from(next).map((id) => ({ id, timestamp: Date.now() }));
			localStorage.setItem("takenDoses", JSON.stringify(items));
			return next;
		});
	}

	// Close modal on Escape key
	useEffect(() => {
		const handleEscape = (e: KeyboardEvent) => {
			if (e.key === "Escape") {
				if (showImageLightbox) {
					setShowImageLightbox(false);
				} else if (selectedMed) {
					setSelectedMed(null);
				}
			}
		};
		document.addEventListener("keydown", handleEscape);
		return () => document.removeEventListener("keydown", handleEscape);
	}, [selectedMed, showImageLightbox]);

	// 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), [meds]);
	const totalTablets = useMemo(() => deriveTotal(form), [form]);
	const coverage = useMemo(() => calculateCoverage(meds, schedule.events), [meds, schedule.events]);
	const depletionByMed = useMemo(() => Object.fromEntries(coverage.all.map((c) => [c.name, c.depletionTime])), [coverage.all]);
	const groupedSchedule = useMemo(() => {
		type DoseInfo = { id: string; timeStr: string; when: number; usage: number };
		const days = new Map<string, { dateStr: string; meds: Map<string, { medName: string; total: number; doses: DoseInfo[]; lastWhen: number }> }>();
		schedule.events.slice(0, 200).forEach((event) => {
			const day = days.get(event.dateStr) ?? { dateStr: event.dateStr, 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, meds: Array.from(d.meds.values()) }));
	}, [schedule.events]);

	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();
		setSettingsSaving(true);
		setTestEmailResult(null);
		
		const payload = {
			emailEnabled: settings.emailEnabled,
			notificationEmail: settings.notificationEmail,
			reminderDaysBefore: settings.reminderDaysBefore,
			repeatDailyReminders: settings.repeatDailyReminders,
			lowStockDays: settings.lowStockDays,
			normalStockDays: settings.normalStockDays,
			highStockDays: settings.highStockDays,
			shoutrrrEnabled: settings.shoutrrrEnabled,
			shoutrrrUrl: settings.shoutrrrUrl,
			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);

		setSettingsSaving(false);
		setSavedSettings(settings);
		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 setSliceValue(idx: number, field: keyof FormSlice, value: string) {
		setForm((prev) => {
			const next = [...prev.slices];
			next[idx] = { ...next[idx], [field]: value };
			return { ...prev, slices: next };
		});
	}

	function addSlice() {
		setForm((prev) => ({ ...prev, slices: [...prev.slices, defaultSlice()] }));
	}

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

	function startEdit(med: Medication) {
		setEditingId(med.id);
		setForm({
			name: med.name,
			genericName: med.genericName ?? "",
			packCount: String(med.packCount ?? 1),
			stripsPerPack: String(med.stripsPerPack ?? med.strips ?? 1),
			tabsPerStrip: String(med.tabsPerStrip ?? med.stripSize ?? 1),
			looseTablets: String(med.looseTablets ?? 0),
			expiryDate: med.expiryDate ? med.expiryDate.slice(0, 10) : "",
			notes: med.notes ?? "",
			slices: med.slices.map((s) => ({ usage: String(s.usage), every: String(s.every), start: toInputValue(s.start) })),
		});
	}

	function resetForm() {
		setEditingId(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,
			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),
			expiryDate: form.expiryDate || null,
			notes: form.notes.trim() || null,
			slices: form.slices.map((s) => ({ usage: Number(s.usage) || 0, every: Math.max(1, Number(s.every) || 1), start: toIsoString(s.start) })),
		};

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

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

		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);
	}

	function resetRange() {
		setRange({ start: toInputValue(todayIso()), end: toInputValue(plusDaysIso(3)) });
		setPlannerRows([]);
	}

	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"));
	}

	return (
		<main className="page">
			<header className="hero">
				<div>
					<p className="eyebrow">Medassist · Planner</p>
					<h1>Manage medication plans</h1>
				</div>
				<div className="header-actions">
					<div className="tabs">
						<button className={currentPath === "/dashboard" || currentPath === "/" ? "pill primary" : "pill"} onClick={() => navigate("/dashboard")}>Dashboard</button>
						<button className={currentPath === "/medications" ? "pill primary" : "pill"} onClick={() => navigate("/medications")}>Medications</button>
						<button className={currentPath === "/planner" ? "pill primary" : "pill"} onClick={() => navigate("/planner")}>Planner</button>
					</div>
					<button className={`icon-btn ${currentPath === "/settings" ? "active" : ""}`} onClick={() => navigate("/settings")} title="Settings">⚙️</button>
					<button className="icon-btn" onClick={toggleTheme} title={theme === "dark" ? "Switch to light mode" : "Switch to dark mode"}>
						{theme === "dark" ? "☀️" : "🌙"}
					</button>
				</div>
			</header>

			<Routes>
				<Route path="/" element={<Navigate to="/dashboard" replace />} />
				<Route path="/dashboard" element={
					<>
						{settings.emailEnabled && settings.notificationEmail && (
							<section className="email-status-bar">
								<span className="email-status-icon">📧</span>
								<span className="email-status-text">
									Automatic reminders active — {getReminderStatusText(settings.reminderDaysBefore, coverage.low, settings.lastAutoEmailSent)}
								</span>
								<span className="email-status-recipient">→ {settings.notificationEmail}</span>
							</section>
						)}
						<section className="grid">
							<article className="card">
								<div className="card-head">
									<h2>Reorder Reminder</h2>
									<span className="pill neutral">Stock watch</span>
								</div>
								{meds.length === 0 ? (
									<p className="muted">No medications configured yet.</p>
								) : coverage.low.length === 0 ? (
									<p className="success-text">All good, enough stock.</p>
								) : (
									<>
										<div className="table table-6">
											<div className="table-head">
												<span>Name</span>
												<span>Current pills</span>
												<span>Days left</span>
												<span>Status</span>
												<span>Runs out</span>
												<span>Auto-remind</span>
											</div>
											{coverage.low.map((row) => {
												const status = getStockStatus(row.daysLeft, row.medsLeft, settings);
												const med = meds.find(m => m.name === row.name);
												return (
													<div key={row.name} className="table-row clickable" onClick={() => med && setSelectedMed(med)}>
														<span data-label="Name" className="cell-with-avatar"><MedicationAvatar name={row.name} imageUrl={med?.imageUrl} />{row.name}{med?.notes && <span className="notes-icon" title="Has notes">📝</span>}</span>
														<span data-label="Pills" className={row.medsLeft <= 0 ? "danger-text" : ""}>{formatNumber(row.medsLeft)}</span>
														<span data-label="Days" className={status.className === "danger" ? "danger-text" : status.className === "warning" ? "warning-text" : ""}>{formatNumber(row.daysLeft)}</span>
														<span data-label="Status" className={`status-chip ${status.className}`}>{status.label}</span>
														<span data-label="Runs out">{row.depletionDate ?? "-"}</span>
														<span data-label="Auto-remind" className="next-reminder-date">{getNextReminderForMed(row, settings.reminderDaysBefore)}</span>
													</div>
												);
											})}
										</div>
										{settings.emailEnabled && settings.notificationEmail && (
											<div className="email-send-action">
												<button type="button" className="ghost" onClick={sendReminderEmail} disabled={sendingReminderEmail}>
													{sendingReminderEmail ? "Sending..." : "📧 Send Reminder Now"}
												</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>Medication Overview</h2>
									<span className="pill neutral">Stock</span>
								</div>
								<div className="table table-6">
									<div className="table-head">
										<span>Name</span>
										<span>Current pills</span>
										<span>Days left</span>
										<span>Runs out</span>
										<span>Expiry</span>
										<span>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);
										return (
											<div key={row.name} className="table-row clickable" onClick={() => med && setSelectedMed(med)}>
												<span data-label="Name" className="cell-with-avatar"><MedicationAvatar name={row.name} imageUrl={med?.imageUrl} />{row.name}{med?.notes && <span className="notes-icon" title="Has notes">📝</span>}</span>
												<span data-label="Pills" className={row.medsLeft <= 0 ? "danger-text" : ""}>{formatNumber(row.medsLeft)}</span>
												<span data-label="Days left" className={status.className === "danger" ? "danger-text" : status.className === "warning" ? "warning-text" : ""}>{formatNumber(row.daysLeft)}</span>
												<span data-label="Runs out">{row.depletionDate ?? "-"}</span>
												<span data-label="Expiry" className={expiryClass}>{med?.expiryDate ? new Date(med.expiryDate).toLocaleDateString([], { day: "2-digit", month: "short", year: "2-digit" }) : "-"}</span>
												<span data-label="Status" className={`status-chip ${status.className}`}>{status.label}</span>
											</div>
										);
									})}
								</div>
							</article>
						</section>

						<section className="grid">
							<article className="card">
								<div className="card-head">
									<h2>Upcoming Schedules</h2>
									<span className="pill neutral">Next 10 days</span>
								</div>
								<div className="timeline">
									{groupedSchedule.map((day) => (
										<div key={day.dateStr} className="day-block">
											<div className="day-divider">{day.dateStr}</div>
											{day.meds.map((item) => {
												const depletionTime = depletionByMed[item.medName];
												const outOfStock = typeof depletionTime === "number" && item.lastWhen > depletionTime;
												const med = meds.find(m => m.name === item.medName);
												const allTaken = item.doses.every((d) => takenDoses.has(d.id));
												const takenCount = item.doses.filter((d) => takenDoses.has(d.id)).length;
												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" />{item.medName}</div>
															<div className="tag-row">
																<span className="tag subtle">{item.total} pills total</span>
																<span className={`tag ${outOfStock ? "danger" : "success"}`}>
																	{outOfStock ? "⚠ No pills left" : "✓ Stock OK"}
																</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 ${isTaken ? "taken" : ""}`}>
																		<span className="dose-time">{dose.timeStr}</span>
																		<span className="dose-usage">{dose.usage} pill{dose.usage !== 1 ? "s" : ""}</span>
																		{isTaken ? (
																			<button className="dose-btn undo" onClick={() => undoDoseTaken(dose.id)} title="Undo">↩</button>
																		) : (
																			<button className="dose-btn take" onClick={() => markDoseTaken(dose.id)} title="Mark as taken">✓</button>
																		)}
																	</div>
																);
															})}
														</div>
													</div>
												);
											})}
										</div>
									))}
								</div>
							</article>
						</section>
					</>
				} />

				<Route path="/medications" element={
					<section className="grid">
						<article className="card meds">
							<div className="card-head">
								<h2>Medication list</h2>
								<span className="pill neutral">{loading ? "Loading..." : `${meds.length} entries`}</span>
							</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>Packs: <strong>{med.packCount ?? 1}</strong></span>
													<span>Blisters per pack: <strong>{med.stripsPerPack ?? med.strips ?? 1}</strong></span>
													<span>Pills per blister: <strong>{med.tabsPerStrip ?? med.stripSize}</strong></span>
													<span>Loose: <strong>{med.looseTablets ?? 0}</strong></span>
												</div>
												<div className="med-total">Total: {med.count} pills</div>
											</div>
											<div className="med-actions">
												<button className="ghost" onClick={() => startEdit(med)}>Edit</button>
												<button className="ghost danger" onClick={() => deleteMed(med.id)}>Delete</button>
											</div>
										</div>
										<div className="slice-list">
											{med.slices.map((s, idx) => (
												<div key={`${med.id}-${idx}`} className="slice-row-simple">
													{s.usage} {s.usage === 1 ? "pill" : "pills"} · every {s.every} {s.every === 1 ? "day" : "days"} · from {formatDateTime(s.start)}
												</div>
											))}
										</div>
									</div>
								))}
							</div>
						</article>

						<article className="card form">
							<div className="card-head">
								<h2>{editingId ? "Edit entry" : "New entry"}</h2>
								<span className="pill">Packs + loose pills</span>
							</div>
							<form className="form-grid" onSubmit={saveMedication}>
								<label>
									Commercial Name
									<input value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} placeholder="e.g. Ozempic" required />
								</label>
								<label>
									Generic Name
									<input value={form.genericName} onChange={(e) => setForm({ ...form, genericName: e.target.value })} placeholder="e.g. Semaglutide (optional)" />
								</label>
								<label>
									Packs
									<input type="number" min="0" value={form.packCount} onChange={(e) => handleValueChange("packCount", e.target.value)} />
								</label>
								<label>
									Blisters per pack
									<input type="number" min="1" value={form.stripsPerPack} onChange={(e) => handleValueChange("stripsPerPack", e.target.value)} />
								</label>
								<label>
									Pills per blister
									<input type="number" min="1" value={form.tabsPerStrip} onChange={(e) => handleValueChange("tabsPerStrip", e.target.value)} />
								</label>
								<label>
									Loose pills
									<input type="number" min="0" value={form.looseTablets} onChange={(e) => handleValueChange("looseTablets", e.target.value)} />
								</label>
								<label>
									Total (pills)
									<div className="static-value">{formatNumber(totalTablets)}</div>
								</label>
								<label>
									Expiry Date
									<input type="date" value={form.expiryDate} onChange={(e) => handleValueChange("expiryDate", e.target.value)} placeholder="optional" />
								</label>

								<label className="full">
									Notes
									<textarea 
										value={form.notes} 
										onChange={(e) => handleValueChange("notes", e.target.value)} 
										placeholder="e.g. Take with food, avoid alcohol... (optional)"
										rows={2}
										maxLength={500}
									/>
								</label>

								<div className="full slices">
									<div className="card-head">
										<h3>Intake schedule</h3>
										<button type="button" className="ghost" onClick={addSlice}>+ Intake</button>
									</div>
									{form.slices.map((s, idx) => (
										<div key={idx} className="slice-row">
											<div className="slice-inputs">
												<label>
													Usage (pills)
													<input type="number" min="0" step="0.1" value={s.usage} onChange={(e) => setSliceValue(idx, "usage", e.target.value)} />
												</label>
												<label>
													Every (days)
													<input type="number" min="1" value={s.every} onChange={(e) => setSliceValue(idx, "every", e.target.value)} />
												</label>
												<label>
													Start (date/time)
													<input type="datetime-local" step="60" value={s.start} onChange={(e) => setSliceValue(idx, "start", e.target.value)} />
												</label>
											</div>
											{form.slices.length > 1 && (
												<button type="button" className="ghost" onClick={() => removeSlice(idx)}>Remove</button>
											)}
										</div>
									))}
								</div>

								{editingId && (
									<div className="full image-upload-section">
										<label className="setting-label">Medication Image</label>
										{(() => {
											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)}>Remove Image</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}
												/>
											);
										})()}
									</div>
								)}

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

				<Route path="/planner" element={
					<section className="grid">
						<article className="card">
							<div className="card-head">
								<h2>Demand Calculator</h2>
								<span className="pill neutral">Plan your supply</span>
							</div>
							<form className="planner" onSubmit={runPlanner}>
								<label>
									From
									<input type="datetime-local" step="60" value={range.start} onChange={(e) => setRange({ ...range, start: e.target.value })} />
								</label>
								<label>
									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}>Reset</button>
									<button type="submit" disabled={plannerLoading}>{plannerLoading ? "Calculating..." : "Calculate"}</button>
								</div>
							</form>
							{plannerRows.length > 0 && (
								<>
									<div className="table">
										<div className="table-head">
											<span>Medication</span>
											<span>Usage</span>
											<span>Blisters needed</span>
											<span>Available</span>
											<span>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="Medication" className="cell-with-avatar"><MedicationAvatar name={row.medicationName} imageUrl={med?.imageUrl} />{row.medicationName}</span>
													<span data-label="Usage"><strong>{row.plannerUsage}</strong> pills</span>
													<span data-label="Blisters">{row.stripsNeeded} × {row.stripSize}</span>
													<span data-label="Available">{row.stripsAvailable} blisters</span>
													<span data-label="Status" className={row.enough ? "status-chip success" : "status-chip danger"}>{row.enough ? "✓ Enough" : "⚠ Out of Stock"}</span>
												</div>
											);
										})}
									</div>
									{settings.emailEnabled && settings.notificationEmail && (
										<div className="planner-email-action">
											<button type="button" className="ghost" onClick={sendPlannerEmail} disabled={sendingPlannerEmail}>
												{sendingPlannerEmail ? "Sending..." : "📧 Send via Email"}
											</button>
											{plannerEmailResult && (
												<span className={plannerEmailResult.success ? "success-text" : "danger-text"}>
													{plannerEmailResult.message}
												</span>
											)}
										</div>
									)}
								</>
							)}
						</article>
					</section>
				} />

				<Route path="/settings" element={
					<section className="grid">
						<article className="card">
							<div className="card-head">
								<h2>Automatic Reminders</h2>
								<span className="pill neutral">Daily check at 6:00 AM</span>
							</div>
							{settingsLoading ? (
								<p>Loading settings...</p>
							) : (
								<form className="settings-form" onSubmit={saveSettings}>
									<div className="setting-info-box">
										<p>🤖 <strong>How it works:</strong> The server checks daily at 6:00 AM. When a medication drops below the threshold, you get notified via <strong>all enabled channels</strong> below.</p>
										<div className="enabled-channels" style={{ marginTop: "0.5rem", display: "flex", gap: "0.5rem", flexWrap: "wrap" }}>
											<button
												type="button"
												className={`pill clickable ${settings.emailEnabled ? "success" : "neutral"}`}
												onClick={async () => {
													const newSettings = { ...settings, emailEnabled: !settings.emailEnabled };
													setSettings(newSettings);
													try {
														await fetch("/api/settings/notifications", {
															method: "PUT",
															headers: { "Content-Type": "application/json" },
															body: JSON.stringify(newSettings),
														});
													} catch (e) { console.error(e); }
												}}
												style={{ cursor: "pointer", border: "none" }}
											>
												📧 Email: {settings.emailEnabled ? "ON" : "OFF"}
											</button>
											<button
												type="button"
												className={`pill clickable ${settings.shoutrrrEnabled ? "success" : "neutral"}`}
												onClick={async () => {
													const newSettings = { ...settings, shoutrrrEnabled: !settings.shoutrrrEnabled };
													setSettings(newSettings);
													try {
														await fetch("/api/settings/notifications", {
															method: "PUT",
															headers: { "Content-Type": "application/json" },
															body: JSON.stringify(newSettings),
														});
													} catch (e) { console.error(e); }
												}}
												style={{ cursor: "pointer", border: "none" }}
											>
												🔔 Push: {settings.shoutrrrEnabled ? "ON" : "OFF"}
											</button>
										</div>
									</div>

									<div className="setting-section">
										<h3>⚙️ Reminder Settings</h3>
										<p className="setting-hint">These settings apply to both Email and Push notifications.</p>
										<div className="setting-group">
											<label>
												Reminder threshold (days)
												<input
													type="number"
													min="1"
													max="90"
													value={settings.reminderDaysBefore}
													onChange={(e) => setSettings({ ...settings, reminderDaysBefore: Number(e.target.value) || 7 })}
												/>
												<span className="input-hint">Send reminder when stock lasts less than this</span>
											</label>
										</div>
										<div className="setting-row">
											<div className="setting-info">
												<label className="setting-label">Repeat daily reminders</label>
												<p className="setting-desc">Send daily notifications while stock is low (otherwise only once per medication)</p>
											</div>
											<label className="toggle-switch small">
												<input
													type="checkbox"
													checked={settings.repeatDailyReminders}
													onChange={(e) => setSettings({ ...settings, repeatDailyReminders: e.target.checked })}
												/>
												<span className="toggle-slider"></span>
											</label>
										</div>
										<div className="setting-info-box">
											<p>⏰ <strong>Next automatic check:</strong> {settings.nextScheduledCheck ? new Date(settings.nextScheduledCheck).toLocaleString() : "—"}</p>
											{settings.lastAutoEmailSent && (
												<p style={{ marginTop: "0.5rem" }}>✓ Last notification sent: <strong>{new Date(settings.lastAutoEmailSent).toLocaleString()}</strong></p>
											)}
										</div>
									</div>

									<div className="setting-section">
										<h3>📧 Email Notifications</h3>
										<div className="setting-row">
											<div className="setting-info">
												<label className="setting-label">Enable Email Notifications</label>
												<p className="setting-desc">Receive reminders via email</p>
											</div>
											<label className="toggle-switch">
												<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">
														Email address
														<input
															type="email"
															value={settings.notificationEmail}
															onChange={(e) => setSettings({ ...settings, notificationEmail: e.target.value })}
															placeholder="your@email.com"
														/>
													</label>
												</div>
												<div className="smtp-readonly">
													<div className="smtp-field">
														<span className="smtp-label">SMTP Host</span>
														<span className="smtp-value">{settings.smtpHost || "—"}</span>
													</div>
													<div className="smtp-field">
														<span className="smtp-label">Port</span>
														<span className="smtp-value">{settings.smtpPort}</span>
													</div>
													<div className="smtp-field">
														<span className="smtp-label">From</span>
														<span className="smtp-value">{settings.smtpFrom || "—"}</span>
													</div>
													<div className="smtp-field">
														<span className="smtp-label">Status</span>
														<span className="smtp-value">{settings.hasSmtpPassword ? "✓ Configured" : "Not configured"}</span>
													</div>
												</div>
												<p className="setting-hint" style={{ marginTop: "0.5rem" }}>SMTP is configured via <code>.env</code> file</p>
												<div className="setting-actions">
													<button type="button" className="ghost" onClick={testEmail} disabled={testingEmail || !settings.notificationEmail}>
														{testingEmail ? "Sending..." : "Send Test Email"}
													</button>
													{testEmailResult && (
														<span className={testEmailResult.success ? "success-text" : "danger-text"}>
															{testEmailResult.message}
														</span>
													)}
												</div>
											</>
										)}
									</div>

									<div className="setting-section">
										<h3>🔔 Shoutrrr Push Notifications</h3>
										<p className="setting-hint">Send push notifications via Shoutrrr-compatible services (ntfy, Discord, Telegram, Slack, etc.). Uses the same reminder threshold.</p>
										
										<div className="setting-row">
											<div className="setting-info">
												<label className="setting-label">Enable Shoutrrr Notifications</label>
												<p className="setting-desc">Receive reminders via push notification services</p>
											</div>
											<label className="toggle-switch">
												<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">
														Notification URL
														<input
															type="url"
															value={settings.shoutrrrUrl}
															onChange={(e) => setSettings({ ...settings, shoutrrrUrl: e.target.value })}
															placeholder="https://ntfy.sh/your-topic"
															pattern="(https?|ntfy|discord|telegram|slack):\/\/.+"
														/>
														<span className="input-hint">
															Examples: <code>https://ntfy.sh/mytopic</code> · <code>ntfy://ntfy.sh/mytopic</code> · <code>discord://token@id</code>
														</span>
													</label>
												</div>
												<div className="setting-actions">
													<button type="button" className="ghost" onClick={testShoutrrr} disabled={testingShoutrrr || !settings.shoutrrrUrl}>
														{testingShoutrrr ? "Sending..." : "Send Test Notification"}
													</button>
													{testShoutrrrResult && (
														<span className={testShoutrrrResult.success ? "success-text" : "danger-text"}>
															{testShoutrrrResult.message}
														</span>
													)}
												</div>
											</>
										)}
									</div>

									<div className="setting-section">
										<h3>📊 Stock Thresholds</h3>
										<p className="setting-hint">Define stock level colors based on how many days of medication you have left.</p>
										<div className="setting-group">
											<label>
												Low Stock (days)
												<input
													type="number"
													min="1"
													max="365"
													value={settings.lowStockDays}
													onChange={(e) => setSettings({ ...settings, lowStockDays: Number(e.target.value) || 30 })}
												/>
												<span className="input-hint">⚠ Yellow below this</span>
											</label>
											<label>
												High Stock (days)
												<input
													type="number"
													min="1"
													max="730"
													value={settings.highStockDays}
													onChange={(e) => setSettings({ ...settings, highStockDays: Number(e.target.value) || 180 })}
												/>
												<span className="input-hint">★ Green with star above this</span>
											</label>
										</div>
									</div>

									<div className="form-footer">
										<button type="submit" disabled={settingsSaving || (!settingsChanged && settingsSaved)}>
											{settingsSaving ? "Saving..." : settingsSaved && !settingsChanged ? "Saved ✓" : "Save Settings"}
										</button>
									</div>
								</form>
							)}
						</article>
					</section>
				} />
			</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>}
							</div>
						</div>

						<div className="med-detail-body">
							<div className="med-detail-section">
								<h3>Stock Information</h3>
								<div className="med-detail-grid">
									<div className="med-detail-item">
										<span className="med-detail-label">Total Pills</span>
										<span className="med-detail-value">{formatNumber(selectedMed.count)}</span>
									</div>
									<div className="med-detail-item">
										<span className="med-detail-label">Packs</span>
										<span className="med-detail-value">{selectedMed.packCount ?? 0}</span>
									</div>
									<div className="med-detail-item">
										<span className="med-detail-label">Blisters/Pack</span>
										<span className="med-detail-value">{selectedMed.stripsPerPack ?? 0}</span>
									</div>
									<div className="med-detail-item">
										<span className="med-detail-label">Pills/Blister</span>
										<span className="med-detail-value">{selectedMed.tabsPerStrip ?? 1}</span>
									</div>
									<div className="med-detail-item">
										<span className="med-detail-label">Loose Pills</span>
										<span className="med-detail-value">{selectedMed.looseTablets ?? 0}</span>
									</div>
									<div className="med-detail-item">
										<span className="med-detail-label">Expiry Date</span>
										<span className={`med-detail-value ${selectedMed.expiryDate && new Date(selectedMed.expiryDate) < new Date() ? 'danger-text' : ''}`}>
											{selectedMed.expiryDate ? new Date(selectedMed.expiryDate).toLocaleDateString([], { day: "2-digit", month: "short", year: "numeric" }) : "—"}
										</span>
									</div>
								</div>
							</div>

							{selectedMed.slices.length > 0 && (
								<div className="med-detail-section">
									<h3>Intake Schedule</h3>
									<div className="med-detail-schedules">
										{selectedMed.slices.map((slice, idx) => (
											<div key={idx} className="med-schedule-item">
												<span className="med-schedule-usage">{slice.usage} pill{slice.usage !== 1 ? "s" : ""}</span>
												<span className="med-schedule-freq">every {slice.every} day{slice.every !== 1 ? "s" : ""}</span>
												<span className="med-schedule-time">at {new Date(slice.start).toLocaleTimeString([], { 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>Coverage Status</h3>
										<div className="med-detail-grid">
											<div className="med-detail-item">
												<span className="med-detail-label">Days Left</span>
												<span className="med-detail-value">{medCoverage.daysLeft !== null ? formatNumber(medCoverage.daysLeft) : "—"}</span>
											</div>
											<div className="med-detail-item">
												<span className="med-detail-label">Runs Out</span>
												<span className="med-detail-value">{medCoverage.depletionDate ?? "—"}</span>
											</div>
											<div className="med-detail-item full-width">
												<span className="med-detail-label">Status</span>
												<span className={`status-chip ${status.className}`}>{status.label}</span>
											</div>
										</div>
									</div>
								);
							})()}

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

						<div className="med-detail-footer">
							<button className="ghost" onClick={() => { setSelectedMed(null); setShowImageLightbox(false); navigate("/medications"); setEditingId(selectedMed.id); }}>
								Edit Medication
							</button>
						</div>
					</div>

					{/* Image Lightbox */}
					{showImageLightbox && selectedMed.imageUrl && (
						<div className="lightbox-overlay" onClick={() => setShowImageLightbox(false)}>
							<button className="lightbox-close" onClick={() => setShowImageLightbox(false)}>×</button>
							<img 
								src={`/api/images/${selectedMed.imageUrl}`} 
								alt={selectedMed.name} 
								className="lightbox-image"
								onClick={(e) => e.stopPropagation()}
							/>
						</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();
	const date = new Date(value);
	return Number.isNaN(date.getTime()) ? new Date().toISOString() : date.toISOString();
}

function toInputValue(value: string) {
	const date = new Date(value);
	if (Number.isNaN(date.getTime())) return new Date().toISOString().slice(0, 16);
	const iso = date.toISOString();
	return iso.slice(0, 16);
}

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

function buildSchedulePreview(meds: Medication[]) {
	const events: Array<{ id: string; medName: string; timeStr: string; dateStr: string; usage: number; when: number }> = [];
	const now = new Date();
	const end = new Date();
	end.setDate(end.getDate() + 10);

	meds.forEach((med) => {
		med.slices.forEach((slice, idx) => {
			const start = new Date(slice.start);
			if (Number.isNaN(start.getTime())) return;
			for (let d = new Date(start); d <= end; d.setDate(d.getDate() + slice.every)) {
				if (d < now) continue;
				const whenMs = d.getTime();
				events.push({
					id: `${med.id}-${idx}-${whenMs}`,
					medName: med.name,
					usage: slice.usage,
					when: whenMs,
					timeStr: d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }),
					dateStr: d.toLocaleDateString([], { 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, totalSlices: meds.reduce((acc, m) => acc + m.slices.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);
}

function getExpiryClass(expiryDate: string | null | undefined): 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 <= 30) return "warning-text"; // 1 month or less
	return "success-text"; // more than 1 month
}

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

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

		let consumed = 0;
		m.slices.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([], { 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([], { 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 <= 3));
	return { low, all: coverage };
}

function getReminderStatusText(reminderDaysBefore: number, lowStock: Coverage[], lastSent: string | null): 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([], { day: "2-digit", month: "short", hour: "2-digit", minute: "2-digit" });
	};

	if (medsNeedingReminder.length > 0) {
		// There are medications that need reminders
		if (lastSent) {
			return (
				<>
					<strong className="warning-text">⚠ {medsNeedingReminder.length} med{medsNeedingReminder.length > 1 ? "s" : ""} need reorder</strong>
					{" · "}Last email: {formatLastSent(lastSent)}
				</>
			);
		}
		return <strong className="warning-text">⚠ {medsNeedingReminder.length} med{medsNeedingReminder.length > 1 ? "s" : ""} need reorder — waiting for first check</strong>;
	}

	// 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">✓ All OK</span>
					{" · "}Next: <strong>{nextMed.name}</strong> in {daysUntilReminder} days
				</>
			);
		}
	}

	// No low stock medications at all
	if (lastSent) {
		return (
			<>
				<span className="success-text">✓ All stock OK</span>
				{" · "}Last email: {formatLastSent(lastSent)}
			</>
		);
	}
	return <span className="success-text">✓ All stock OK — no reminders needed</span>;
}

function getNextReminderForMed(med: Coverage, reminderDaysBefore: number): 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([], {
		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: "Out of Stock" };
	}
	
	// No schedule set (no daysLeft calculation possible)
	if (daysLeft === null) {
		return { level: "normal", className: "success", label: "No Schedule" };
	}
	
	// High stock: > highStockDays (e.g. > 180 days)
	if (daysLeft > thresholds.highStockDays) {
		return { level: "high", className: "high", label: "★ High Stock" };
	}
	
	// Normal stock: between lowStockDays and highStockDays
	if (daysLeft >= thresholds.lowStockDays) {
		return { level: "normal", className: "success", label: "Normal" };
	}
	
	// Low stock: < lowStockDays (e.g. < 30 days)
	return { level: "low", className: "warning", label: "Low Stock" };
}

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>;
}
