/* biome-ignore-all lint/style/noNestedTernary: schedule timeline branches are intentionally explicit */
import { Archive, Bell } from "lucide-react";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { ConfirmModal, MedicationAvatar } from "../components";
import { useAuth } from "../components/Auth";
import { ScheduleUsageTag } from "../features/schedule/components";
import { formatScheduleDoseUsageLabel, formatScheduleTotalUsageLabel } from "../features/schedule/formatters";
import { useScheduleController } from "../hooks";
import type { Coverage, IntakeUnit } from "../types";
import { getMedDisplayName, isLiquidContainerPackageType, isTubePackageType } from "../types";
import { buildClearMissedPayload, isDoseDismissed } from "../utils/schedule";

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

// Helper function to get stock status based on thresholds
function getStockStatus(
	daysLeft: number | null,
	medsLeft: number,
	settings: { lowStockDays: number; normalStockDays: number; highStockDays: number; reminderDaysBefore: number },
	packageType?: string
) {
	if (isTubePackageType(packageType)) return { className: "success", label: "status.noSchedule" };
	// Only a real zero-or-below stock count is out of stock.
	if (medsLeft <= 0) return { className: "danger", label: "status.outOfStock" };
	// No schedule, but has stock = normal
	if (daysLeft === null) return { className: "success", label: "status.noSchedule" };
	if (isLiquidContainerPackageType(packageType)) {
		const lowDays = Math.max(1, Math.floor(settings.reminderDaysBefore));
		const criticalDays = Math.max(1, Math.ceil(lowDays / 2));
		if (daysLeft <= criticalDays) return { className: "danger", label: "status.criticalStock" };
		if (daysLeft <= lowDays) return { className: "warning", label: "status.lowStock" };
		return { className: "success", label: "status.normal" };
	}
	// Critical: at or below reminder threshold = danger (red)
	if (daysLeft <= settings.reminderDaysBefore) return { className: "danger", label: "status.criticalStock" };
	// Low: below low stock threshold = warning (yellow)
	if (daysLeft < settings.lowStockDays) return { className: "warning", label: "status.lowStock" };
	// High stock
	if (daysLeft >= settings.highStockDays) return { className: "high", label: "status.highStock" };
	// Normal stock
	return { className: "success", label: "status.normal" };
}

// Helper function to get worst stock status for a day
function getDayStockStatus(
	dayMeds: Array<{ medName: string }>,
	coverageByMed: Record<string, Coverage>,
	settings: { lowStockDays: number; normalStockDays: number; highStockDays: number; reminderDaysBefore: number },
	meds: Array<{ name: string; genericName?: string | null; packageType?: string }>
): string {
	let worstLevel = 3; // 3=success, 2=warning, 1=danger
	for (const item of dayMeds) {
		const cov = coverageByMed[item.medName];
		if (!cov) continue;
		const med = meds.find((m) => getMedDisplayName(m) === item.medName);
		const status = getStockStatus(cov.daysLeft, cov.medsLeft, settings, med?.packageType);
		if (status.className === "danger") worstLevel = Math.min(worstLevel, 1);
		else if (status.className === "warning") worstLevel = Math.min(worstLevel, 2);
	}
	return worstLevel === 1 ? "danger" : worstLevel === 2 ? "warning" : "success";
}

// Helper to get dose ID (with or without person)
function getDoseId(baseId: string, person: string | null): string {
	return person ? `${baseId}-${person}` : baseId;
}

export function SchedulePage() {
	const { t } = useTranslation();
	const { user } = useAuth();
	const {
		meds,
		settings,
		scheduleDays,
		setScheduleDays,
		showPastDays,
		setShowPastDays,
		pastDays,
		futureDays,
		takenDoses,
		isDoseTakenAutomatically,
		dismissedDoses,
		markDoseTaken,
		skippedDoses,
		markDoseSkipped,
		undoDoseTaken,
		undoDoseSkipped,
		coverageByMed,
		depletionByMed,
		manuallyExpandedDays,
		toggleDayCollapse,
		openUserFilter,
		missedPastDoseIds,
		loadMeds,
	} = useScheduleController();
	const [showClearMissedConfirm, setShowClearMissedConfirm] = useState(false);
	const [clearingMissed, setClearingMissed] = useState(false);
	const [showObsoleteConfirm, setShowObsoleteConfirm] = useState(false);
	const [obsoleteCandidate, setObsoleteCandidate] = useState<{ id: number; name: string } | null>(null);

	const isDoseTakenForDisplay = (doseId: string) => takenDoses.has(doseId);

	const shouldHideNoScheduleStatusForTube = (
		med: (typeof meds)[number] | undefined,
		status: { className: string; label: string } | null
	) => isTubePackageType(med?.packageType) && status?.label === "status.noSchedule";

	const clearMissedDoses = async (missedCount: number) => {
		const payload = buildClearMissedPayload(pastDays, meds, takenDoses, dismissedDoses);
		if (payload.medicationIds.length === 0 || !payload.until) {
			setShowClearMissedConfirm(false);
			return;
		}

		setClearingMissed(true);
		try {
			const res = await fetch("/api/medications/dismiss-until", {
				method: "POST",
				credentials: "include",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify(payload),
			});
			if (!res.ok) {
				throw new Error(`HTTP ${res.status}`);
			}
			await loadMeds();
			setShowClearMissedConfirm(false);
			alert(t("dashboard.schedules.clearMissedSuccess", { count: missedCount }));
		} catch {
			alert(t("common.saveFailed"));
		} finally {
			setClearingMissed(false);
		}
	};

	const requestMarkObsolete = (med: { id: number; name: string }) => {
		setObsoleteCandidate(med);
		setShowObsoleteConfirm(true);
	};

	const handleConfirmMarkObsolete = async () => {
		if (!obsoleteCandidate) return;
		try {
			const res = await fetch(`/api/medications/${obsoleteCandidate.id}/obsolete`, {
				method: "POST",
				credentials: "include",
			});
			if (!res.ok) throw new Error(`HTTP ${res.status}`);
			await loadMeds();
			setShowObsoleteConfirm(false);
			setObsoleteCandidate(null);
		} catch {
			alert(t("common.saveFailed"));
		}
	};

	const handleCancelMarkObsolete = () => {
		setShowObsoleteConfirm(false);
		setObsoleteCandidate(null);
	};

	const formatDoseUsageLabel = (
		med: (typeof meds)[number] | undefined,
		usage: number,
		intakeUnit?: IntakeUnit | null
	) => formatScheduleDoseUsageLabel(med, usage, t, intakeUnit);

	const formatTotalUsageLabel = (
		med: (typeof meds)[number] | undefined,
		total: number,
		doses?: Array<{ usage: number; intakeUnit?: IntakeUnit | null }>
	) => formatScheduleTotalUsageLabel(med, total, t, doses);

	const renderDoseActionButtons = (options: {
		doseId: string;
		isTaken: boolean;
		isSkipped: boolean;
		isAutomaticallyTaken: boolean;
		isEmpty: boolean;
	}) => {
		const takeButton = options.isTaken ? (
			<button className="dose-btn undo take" onClick={() => undoDoseTaken(options.doseId)} title={t("common.undo")}>
				{options.isAutomaticallyTaken && (
					<span className="info-tooltip" data-tooltip={t("tooltips.automaticTaken")}>
						🤖
					</span>
				)}
				<span className="dose-btn-label">{t("common.undo")}</span>
				<span aria-hidden="true">↩</span>
			</button>
		) : (
			<button
				className={`dose-btn take${options.isEmpty ? " out-of-stock" : ""}`}
				onClick={() => markDoseTaken(options.doseId)}
				disabled={options.isEmpty || options.isSkipped}
				title={options.isEmpty ? t("common.outOfStockTakeBlocked") : t("dose.markAsTaken")}
			>
				<span className="dose-btn-label">{t("dose.take")}</span>
				<span aria-hidden="true">{options.isEmpty ? "⊘" : "✓"}</span>
			</button>
		);

		const skipButton = options.isSkipped ? (
			<button className="dose-btn undo skip" onClick={() => undoDoseSkipped(options.doseId)} title={t("common.undo")}>
				<span className="dose-btn-label">{t("common.undo")}</span>
				<span aria-hidden="true">↩</span>
			</button>
		) : (
			<button
				className="dose-btn skip"
				onClick={() => markDoseSkipped(options.doseId)}
				title={t("dose.markAsSkipped")}
				disabled={options.isTaken}
			>
				<span className="dose-btn-label">{t("dose.skip")}</span>
			</button>
		);

		return (
			<>
				{takeButton}
				{skipButton}
			</>
		);
	};

	return (
		<section className="grid">
			<article className="card schedule-full">
				<div className="card-head">
					<h2>{t("dashboard.schedules.title")}</h2>
					<select
						className="select-field 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 (when expanded) — rendered above toggle */}
					{showPastDays &&
						pastDays.map((day) => {
							// Get ALL dose IDs for this day (for total count and yellow styling)
							const allDoseIds = day.meds.flatMap((item) =>
								item.doses.flatMap((d) => {
									const takenByArray = Array.isArray(d.takenBy) ? d.takenBy : [];
									return takenByArray.length > 0 ? takenByArray.map((p) => `${d.id}-${p}`) : [d.id];
								})
							);

							// Really taken = all doses marked as taken by human (for green "All taken")
							const allReallyTaken = allDoseIds.length > 0 && allDoseIds.every((id) => isDoseTakenForDisplay(id));
							const takenCount = allDoseIds.filter((id) => isDoseTakenForDisplay(id)).length;

							// Count missed doses that are NOT dismissed (for warning icon)
							const missedNotDismissedCount = day.meds.reduce((count, item) => {
								const med = meds.find((m) => getMedDisplayName(m) === item.medName);
								const dismissedUntilDate = med?.dismissedUntil ?? undefined;
								return (
									count +
									item.doses.reduce((doseCount, d) => {
										if (isDoseDismissed(d.id, dismissedUntilDate)) return doseCount;
										const takenByArray = Array.isArray(d.takenBy) ? d.takenBy : [];
										const ids = takenByArray.length > 0 ? takenByArray.map((p) => `${d.id}-${p}`) : [d.id];
										return doseCount + ids.filter((id) => !isDoseTakenForDisplay(id) && !dismissedDoses.has(id)).length;
									}, 0)
								);
							}, 0);
							const hasRealMissed = missedNotDismissedCount > 0;

							const isManuallyExpanded = manuallyExpandedDays.has(day.dateStr);
							const isCollapsed = !isManuallyExpanded;
							const _worstStatus = getDayStockStatus(day.meds, coverageByMed, settings, meds);

							return (
								<div
									key={day.dateStr}
									className={`day-block past ${isCollapsed ? "collapsed" : ""} ${allReallyTaken ? "all-taken" : allDoseIds.length > 0 ? "past-missed" : ""}`}
								>
									<div
										className="day-divider clickable"
										onClick={() => toggleDayCollapse(day.dateStr, true)}
										onKeyDown={(e) => {
											if (e.key === "Enter" || e.key === " ") 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">
											{allReallyTaken ? (
												<span className="day-complete">✓ {t("dashboard.schedules.allTaken")}</span>
											) : (
												<>
													{hasRealMissed && (
														<span
															className="day-warning"
															title={t("dashboard.schedules.missedDoses", { count: missedNotDismissedCount })}
														>
															⚠️
														</span>
													)}
													<span className="day-progress">
														{takenCount}/{allDoseIds.length}
													</span>
												</>
											)}
										</span>
									</div>
									{!isCollapsed &&
										day.meds.map((item) => {
											const med = meds.find((m) => getMedDisplayName(m) === item.medName);
											const medCov = coverageByMed[item.medName];
											const isEmpty = medCov ? medCov.medsLeft <= 0 : false;
											const rawStatus = medCov
												? getStockStatus(medCov.daysLeft, medCov.medsLeft, settings, med?.packageType)
												: null;
											const visibleStatus = shouldHideNoScheduleStatusForTube(med, rawStatus) ? null : rawStatus;
											const isLowStock = !isEmpty && visibleStatus?.className === "warning";
											const rowClasses = ["time-row"];
											if (isEmpty) rowClasses.push("med-empty");
											else if (isLowStock) rowClasses.push("med-low");
											return (
												<div key={`${day.dateStr}-${item.medName}`} className={rowClasses.join(" ")}>
													<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>
														</div>
														<div className="tag-row">
															<ScheduleUsageTag>{formatTotalUsageLabel(med, item.total, item.doses)}</ScheduleUsageTag>
														</div>
													</div>
													<div className="doses-col">
														{item.doses.map((dose) => {
															// If no takenBy, show single checkbox; otherwise show one per person
															const people = (dose.takenBy || []).length > 0 ? dose.takenBy : [null];
															const allTaken = people.every((person) =>
																isDoseTakenForDisplay(getDoseId(dose.id, person))
															);
															const doseClasses = ["dose-item", "past"];
															if (allTaken) doseClasses.push("all-taken");
															if (isEmpty) doseClasses.push("med-empty");
															else if (isLowStock) doseClasses.push("med-low");
															return (
																<div key={dose.id} className={doseClasses.join(" ")}>
																	<span className="dose-time">{dose.timeStr}</span>
																	<span className="dose-usage">
																		<span className="dose-usage-main">
																			{formatDoseUsageLabel(med, dose.usage, dose.intakeUnit)}
																		</span>
																		{med?.pillWeightMg && (
																			<span className="dose-usage-weight">{`${dose.usage * med.pillWeightMg} ${med.doseUnit ?? "mg"}`}</span>
																		)}
																	</span>{" "}
																	{dose.intakeRemindersEnabled && (
																		<span
																			className="reminder-icon info-tooltip"
																			data-tooltip={t("tooltips.intakeReminders")}
																		>
																			<Bell size={14} aria-hidden="true" />
																		</span>
																	)}{" "}
																	<div className="dose-checks">
																		{people.map((person) => {
																			const doseId = getDoseId(dose.id, person);
																			const isTaken = isDoseTakenForDisplay(doseId);
																			const isSkipped = skippedDoses.has(doseId);
																			const isAutomaticallyTaken =
																				isTaken && isDoseTakenAutomatically(doseId) && dose.when <= Date.now();
																			const personClasses = ["dose-person"];
																			if (isTaken) personClasses.push("taken");
																			if (isSkipped) personClasses.push("skipped");
																			return (
																				<div key={doseId} className={personClasses.join(" ")}>
																					{person && (
																						<span
																							className="person-name clickable"
																							onClick={() => openUserFilter(person)}
																							onKeyDown={(e) => {
																								if (e.key === "Enter" || e.key === " ") openUserFilter(person);
																							}}
																						>
																							{person}
																						</span>
																					)}
																					{renderDoseActionButtons({
																						doseId,
																						isTaken,
																						isSkipped,
																						isAutomaticallyTaken,
																						isEmpty,
																					})}
																				</div>
																			);
																		})}
																	</div>
																</div>
															);
														})}
													</div>
												</div>
											);
										})}
								</div>
							);
						})}
					{/* Past days toggle */}
					{pastDays.length > 0 &&
						(() => {
							const missedCount = missedPastDoseIds.length;
							return (
								<div className="past-days-header">
									<div
										className={`past-days-toggle ${showPastDays ? "expanded" : ""} ${missedCount > 0 ? "has-missed" : ""}`}
										onClick={() => {
											const wasCollapsed = !showPastDays;
											setShowPastDays(!showPastDays);
											if (wasCollapsed) {
												setTimeout(() => {
													document
														.querySelector(".day-block.today")
														?.scrollIntoView({ behavior: "smooth", block: "center" });
												}, 50);
											}
										}}
										onKeyDown={(e) => {
											if (e.key === "Enter" || e.key === " ") {
												const wasCollapsed = !showPastDays;
												setShowPastDays(!showPastDays);
												if (wasCollapsed) {
													setTimeout(() => {
														document
															.querySelector(".day-block.today")
															?.scrollIntoView({ behavior: "smooth", block: "center" });
													}, 50);
												}
											}
										}}
									>
										<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>
										{missedCount > 0 && (
											<span
												className="past-days-warning"
												title={t("dashboard.schedules.missedDoses", { count: missedCount })}
											>
												⚠️ {missedCount}
											</span>
										)}
									</div>
									{missedCount > 0 && (
										<button type="button" className="clear-missed-btn" onClick={() => setShowClearMissedConfirm(true)}>
											{t("dashboard.schedules.clearMissed")}
										</button>
									)}
								</div>
							);
						})()}
					{showClearMissedConfirm && (
						<ConfirmModal
							title={t("dashboard.schedules.clearMissedConfirmTitle")}
							message={t("dashboard.schedules.clearMissedConfirmMessage", {
								count: missedPastDoseIds.length,
							})}
							confirmLabel={t("dashboard.schedules.clearMissedConfirm")}
							cancelLabel={t("dashboard.schedules.clearMissedCancel")}
							onConfirm={() => void clearMissedDoses(missedPastDoseIds.length)}
							onCancel={() => {
								if (!clearingMissed) setShowClearMissedConfirm(false);
							}}
							isLoading={clearingMissed}
							confirmVariant="warning"
						/>
					)}
					{showObsoleteConfirm && obsoleteCandidate && (
						<ConfirmModal
							title={t("medications.obsoleteModal.title")}
							message={t("medications.obsoleteModal.message", { name: obsoleteCandidate.name })}
							confirmLabel={t("medications.list.markObsolete")}
							cancelLabel={t("common.cancel")}
							onConfirm={() => void handleConfirmMarkObsolete()}
							onCancel={handleCancelMarkObsolete}
							confirmVariant="warning"
						/>
					)}
					{/* 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 isEmpty = medCoverage ? medCoverage.medsLeft <= 0 : false;
									const med = meds.find((m) => getMedDisplayName(m) === 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, med?.packageType)
											: null;
									const visibleStatus = shouldHideNoScheduleStatusForTube(med, status) ? null : status;
									const isLowStock = !isEmpty && visibleStatus?.className === "warning";
									const rowClasses = ["time-row"];
									if (isEmpty) rowClasses.push("med-empty");
									else if (isLowStock) rowClasses.push("med-low");
									return (
										<div key={`${day.dateStr}-${item.medName}`} className={rowClasses.join(" ")}>
											<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>
												</div>
												<div className="tag-row">
													<ScheduleUsageTag>{formatTotalUsageLabel(med, item.total, item.doses)}</ScheduleUsageTag>
													{visibleStatus && (
														<span className={`tag ${visibleStatus.className}`}>{t(visibleStatus.label)}</span>
													)}
												</div>
												{isEmpty && med && !med.isObsolete && (
													<div className="timeline-obsolete-row">
														<button
															type="button"
															className="timeline-obsolete-btn btn-obsolete"
															onClick={() => requestMarkObsolete({ id: med.id, name: getMedDisplayName(med) })}
														>
															<Archive size={16} aria-hidden="true" />
															<span>{t("medications.list.markObsolete")}</span>
														</button>
													</div>
												)}
											</div>
											<div className="doses-col">
												{item.doses.map((dose) => {
													const people = (dose.takenBy || []).length > 0 ? dose.takenBy : [null];
													const now = Date.now();
													const dayStart = new Date(day.date).setHours(0, 0, 0, 0);
													const isPastDay = dayStart < new Date().setHours(0, 0, 0, 0);
													const allTaken = people.every((person) => isDoseTakenForDisplay(getDoseId(dose.id, person)));
													const doseClasses = ["dose-item"];
													if (allTaken) doseClasses.push("all-taken");
													if (isEmpty) doseClasses.push("med-empty");
													else if (isLowStock) doseClasses.push("med-low");
													return (
														<div key={dose.id} className={doseClasses.join(" ")}>
															<span className="dose-time">{dose.timeStr}</span>
															<span className="dose-usage">
																<span className="dose-usage-main">
																	{formatDoseUsageLabel(med, dose.usage, dose.intakeUnit)}
																</span>
																{med?.pillWeightMg && (
																	<span className="dose-usage-weight">{`${dose.usage * med.pillWeightMg} ${med.doseUnit ?? "mg"}`}</span>
																)}
															</span>
															{dose.intakeRemindersEnabled && (
																<span
																	className="reminder-icon info-tooltip"
																	data-tooltip={t("tooltips.intakeReminders")}
																>
																	<Bell size={14} aria-hidden="true" />
																</span>
															)}
															<div className="dose-checks">
																{people.map((person) => {
																	const doseId = getDoseId(dose.id, person);
																	const isTaken = isDoseTakenForDisplay(doseId);
																	const isSkipped = skippedDoses.has(doseId);
																	const isAutomaticallyTaken =
																		isTaken && isDoseTakenAutomatically(doseId) && dose.when <= now;
																	const isOverdue = !isTaken && !isSkipped && !isEmpty && dose.when < now && !isPastDay;
																	const personClasses = ["dose-person"];
																	if (isTaken) personClasses.push("taken");
																	if (isSkipped) personClasses.push("skipped");
																	if (isOverdue) personClasses.push("overdue");
																	return (
																		<div key={doseId} className={personClasses.join(" ")}>
																			{person && (
																				<span
																					className="person-name clickable"
																					onClick={() => openUserFilter(person)}
																					onKeyDown={(e) => {
																						if (e.key === "Enter" || e.key === " ") openUserFilter(person);
																					}}
																				>
																					{person}
																				</span>
																			)}
																			{renderDoseActionButtons({
																				doseId,
																				isTaken,
																				isSkipped,
																				isAutomaticallyTaken,
																				isEmpty,
																			})}
																		</div>
																	);
																})}
															</div>
														</div>
													);
												})}
											</div>
										</div>
									);
								})}
							</div>
						);
					})}
				</div>
			</article>
		</section>
	);
}
