import { api, protectedFetch } from "./api.js?v=__ASSET_VERSION__";
import { initSideNav, loadNavUser } from "./nav.js?v=__ASSET_VERSION__";
import { showToast } from "./toast.js?v=__ASSET_VERSION__";

let roasters = [];
let selectedId = null;
let profile = null;

const fmtTime = (s) =>
	s == null
		? "—"
		: `${Math.floor(Math.round(s) / 60)}:${String(Math.round(s) % 60).padStart(2, "0")}`;

// Metric rows of the report: what the planner actually consumes from a machine's profile.
// `fmt` renders read-only values; overrides are edited in the raw unit (°C / seconds / ×).
const METRICS = [
	{ key: "chargeTempC", label: "Charge temp (curve fallback)", unit: "°C" },
	{ key: "turningPointS", label: "Turning point time (thermal lag)", unit: "s", fmt: fmtTime },
	{ key: "turningPointTempC", label: "Turning point temp", unit: "°C" },
	{ key: "yellowTempC", label: "Yellow temp (curve fallback)", unit: "°C" },
	{ key: "firstCrackTempC", label: "First crack temp (curve fallback)", unit: "°C" },
	{ key: "dropTempC", label: "Drop temp (curve fallback)", unit: "°C" },
	{ key: "paceFactor", label: "Pace factor (multiplies first-crack timing)", unit: "×" },
];

function renderRoasters() {
	const body = document.getElementById("roasters-body");
	if (!roasters.length) {
		body.innerHTML = `<tr><td colspan="4" class="empty-state">No roasters yet — add your machine below. Your first one becomes the default.</td></tr>`;
		return;
	}
	body.replaceChildren(
		...roasters.map((roaster) => {
			const tr = document.createElement("tr");
			tr.style.cursor = "pointer";
			if (roaster.id === selectedId) tr.style.background = "var(--surface-sunken)";

			const nameCell = document.createElement("td");
			const strong = document.createElement("strong");
			strong.textContent = roaster.name;
			nameCell.append(strong);
			if (roaster.model) {
				const sub = document.createElement("div");
				sub.className = "muted";
				sub.style.fontSize = "11.5px";
				sub.textContent = roaster.model;
				nameCell.append(sub);
			}

			const defaultCell = document.createElement("td");
			defaultCell.textContent = roaster.isDefault ? "✓ default" : "";

			const countCell = document.createElement("td");
			countCell.className = "num";
			countCell.textContent = roaster.roastCount ?? 0;

			const actions = document.createElement("td");
			actions.className = "data-table-actions";
			if (!roaster.isDefault) {
				const makeDefault = document.createElement("button");
				makeDefault.className = "ghost-btn small";
				makeDefault.type = "button";
				makeDefault.textContent = "Make default";
				makeDefault.addEventListener("click", async (event) => {
					event.stopPropagation();
					try {
						await api(`/api/roasters/${roaster.id}`, {
							method: "PUT",
							body: JSON.stringify({ isDefault: true }),
						});
						showToast(`${roaster.name} is now the default.`);
						await loadRoasters();
					} catch (error) {
						showToast(error.message, "fail");
					}
				});
				actions.append(makeDefault);
			}
			const deleteBtn = document.createElement("button");
			deleteBtn.className = "ghost-btn small";
			deleteBtn.type = "button";
			deleteBtn.textContent = "Delete";
			deleteBtn.addEventListener("click", async (event) => {
				event.stopPropagation();
				if (
					!confirm(
						`Delete "${roaster.name}"? Its logged roasts are kept but detach from it.`,
					)
				)
					return;
				try {
					await api(`/api/roasters/${roaster.id}`, { method: "DELETE" });
					showToast("Roaster deleted.");
					if (selectedId === roaster.id) selectedId = null;
					await loadRoasters();
				} catch (error) {
					showToast(error.message, "fail");
				}
			});
			actions.append(deleteBtn);

			tr.append(nameCell, defaultCell, countCell, actions);
			tr.addEventListener("click", () => selectRoaster(roaster.id));
			return tr;
		}),
	);
}

function overrideInputs() {
	return [...document.querySelectorAll("#report-rows input[data-key]")];
}

function renderReport() {
	const card = document.getElementById("report-card");
	if (!selectedId || !profile) {
		card.classList.add("hidden");
		return;
	}
	card.classList.remove("hidden");
	const roaster = roasters.find((r) => r.id === selectedId);
	document.getElementById("report-title").textContent =
		`Analysis — ${roaster?.name ?? ""}`;
	document.getElementById("report-count").textContent =
		`${profile.n} roast${profile.n === 1 ? "" : "s"} analyzed`;
	document.getElementById("report-empty").hidden = profile.n > 0;

	const rows = document.getElementById("report-rows");
	rows.replaceChildren(
		...METRICS.map((metric) => {
			const tr = document.createElement("tr");
			const label = document.createElement("td");
			label.textContent = metric.label;

			const learnedCell = document.createElement("td");
			const learnedValue =
				metric.key === "paceFactor" ? null : profile.learnedMedians?.[metric.key];
			learnedCell.textContent =
				learnedValue == null
					? metric.key === "paceFactor"
						? "learned from plan logs"
						: "—"
					: `${metric.fmt ? metric.fmt(learnedValue) : learnedValue} ${metric.fmt ? "" : metric.unit}`.trim();

			const overrideCell = document.createElement("td");
			const input = document.createElement("input");
			input.className = "field-input sm";
			input.type = "number";
			input.step = "any";
			input.style.maxWidth = "110px";
			input.dataset.key = metric.key;
			input.placeholder = metric.unit;
			const overrideValue = profile.overrides?.[metric.key];
			if (overrideValue != null) input.value = overrideValue;
			overrideCell.append(input);

			const appliedCell = document.createElement("td");
			const applied =
				overrideValue ??
				(metric.key === "paceFactor" ? null : profile.learnedMedians?.[metric.key]);
			appliedCell.textContent =
				applied == null
					? metric.key === "paceFactor"
						? "plan-log pace"
						: "reference default"
					: `${metric.fmt ? metric.fmt(applied) : applied} ${metric.fmt ? "" : metric.unit}${overrideValue != null ? " (your tweak)" : " (learned)"}`.trim();

			tr.append(label, learnedCell, overrideCell, appliedCell);
			return tr;
		}),
	);

	const ror = profile.rorCPerMin ?? {};
	document.getElementById("report-ror").textContent =
		profile.n > 0
			? `Typical rate of rise on this machine — drying ${ror.drying ?? "—"} °C/min, Maillard ${ror.maillard ?? "—"} °C/min, development ${ror.development ?? "—"} °C/min.`
			: "";

	const adjustments = document.getElementById("report-adjustments");
	adjustments.replaceChildren();
	const list = document.createElement("ul");
	list.style.paddingLeft = "18px";
	list.style.fontSize = "13px";
	const items = [];
	if (profile.n > 0)
		items.push(
			"Blank milestone temps on the planner's curve use this machine's learned medians instead of the reference machine.",
			`New plans assume the turning point around ${fmtTime(profile.medians?.turningPointS)} — this machine's measured thermal lag.`,
		);
	if (profile.paceFactorOverride != null)
		items.push(
			`First-crack timing is multiplied by your pace tweak ×${profile.paceFactorOverride} instead of the plan-log learned pace.`,
		);
	items.push(
		"Roast reviews compare each new roast against this machine's own typical behavior, not a generic one.",
	);
	if (!(roaster?.isDefault ?? false))
		items.push(
			"Note: the planner uses the DEFAULT machine's profile — make this one default to plan with it.",
		);
	for (const text of items) {
		const li = document.createElement("li");
		li.textContent = text;
		list.append(li);
	}
	adjustments.append(list);
}

async function selectRoaster(id) {
	selectedId = id;
	try {
		profile = (await api(`/api/roaster-profile?roaster=${encodeURIComponent(id)}`)).profile;
	} catch (error) {
		showToast(error.message, "fail");
		profile = null;
	}
	renderRoasters();
	renderReport();
}

async function saveOverrides(clear = false) {
	if (!selectedId) return;
	const overrides = {};
	if (!clear)
		for (const input of overrideInputs()) {
			if (input.value === "") continue;
			const value = Number(input.value);
			if (!Number.isFinite(value)) {
				showToast(`"${input.value}" is not a number.`, "fail");
				return;
			}
			overrides[input.dataset.key] = value;
		}
	try {
		await api(`/api/roasters/${selectedId}`, {
			method: "PUT",
			body: JSON.stringify({ overrides }),
		});
		showToast(clear ? "Tweaks cleared — using learned values." : "Tweaks saved.");
		await loadRoasters();
		await selectRoaster(selectedId);
	} catch (error) {
		showToast(error.message, "fail");
	}
}

async function loadRoasters() {
	try {
		roasters = (await api("/api/roasters")).roasters;
		renderRoasters();
	} catch {
		document.getElementById("roasters-body").innerHTML =
			`<tr><td colspan="4" class="empty-state">Could not load roasters.</td></tr>`;
	}
}

document.getElementById("roaster-form").addEventListener("submit", async (event) => {
	event.preventDefault();
	const form = event.target;
	try {
		const created = await api("/api/roasters", {
			method: "POST",
			body: JSON.stringify({ name: form.name.value, model: form.model.value }),
		});
		form.reset();
		showToast("Roaster added.");
		await loadRoasters();
		await selectRoaster(created.roaster.id);
	} catch (error) {
		showToast(error.message, "fail");
	}
});
document.getElementById("save-overrides").addEventListener("click", () => saveOverrides(false));
document.getElementById("clear-overrides").addEventListener("click", () => saveOverrides(true));
document.getElementById("btn-logout").addEventListener("click", async () => {
	await protectedFetch("/api/auth/logout", { method: "POST" });
	location.assign("/");
});

async function init() {
	initSideNav();
	const user = await loadNavUser();
	if (!user) return;
	await loadRoasters();
	const preferred = roasters.find((r) => r.isDefault) ?? roasters[0];
	if (preferred) await selectRoaster(preferred.id);
}

init();
