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 lots = [];
let showArchived = false;
let editingId = null;

function fmtDate(value) {
	return value ? new Date(value).toLocaleDateString() : "—";
}

/** Disables `button` for the duration of `run()` so a slow request can't be double-submitted. */
async function guarded(button, run) {
	if (!button || button.disabled) return;
	button.disabled = true;
	try {
		await run();
	} finally {
		button.disabled = false;
	}
}

function renderLots() {
	const body = document.getElementById("lots-body");
	const visible = showArchived ? lots : lots.filter((l) => !l.archived);
	if (!visible.length) {
		body.innerHTML = `<tr><td colspan="5" class="empty-state">No lots yet.</td></tr>`;
		return;
	}
	body.replaceChildren(
		...visible.map((lot) => {
			const tr = document.createElement("tr");
			if (lot.archived) tr.className = "archived";

			const lotCell = document.createElement("td");
			const strong = document.createElement("strong");
			strong.textContent = lot.origin;
			const sub = document.createElement("div");
			sub.className = "muted";
			sub.style.fontSize = "11.5px";
			sub.textContent = [lot.variety, lot.producer].filter(Boolean).join(" · ") || "—";
			lotCell.append(strong, sub);

			const processCell = document.createElement("td");
			processCell.textContent = lot.process || "—";

			const remainingCell = document.createElement("td");
			const pct = lot.initialWeightG > 0
				? Math.max(0, Math.min(100, (lot.remainingWeightG / lot.initialWeightG) * 100))
				: 0;
			const wrap = document.createElement("div");
			wrap.className = "lot-remaining";
			const bar = document.createElement("div");
			bar.className = "blend-total-bar";
			const fill = document.createElement("div");
			fill.className = "blend-total-fill";
			if (lot.remainingWeightG < 0) fill.classList.add("over");
			fill.style.width = `${lot.remainingWeightG < 0 ? 0 : pct}%`;
			bar.append(fill);
			const label = document.createElement("span");
			label.className = "blend-total-label";
			label.textContent = `${Math.round(lot.remainingWeightG)} g of ${Math.round(lot.initialWeightG)} g`;
			wrap.append(bar, label);
			remainingCell.append(wrap);

			const purchasedCell = document.createElement("td");
			purchasedCell.textContent = fmtDate(lot.purchaseDate);

			const actions = document.createElement("td");
			actions.className = "data-table-actions";

			const editBtn = document.createElement("button");
			editBtn.className = "ghost-btn small";
			editBtn.type = "button";
			editBtn.textContent = "Edit";
			editBtn.addEventListener("click", () => startEdit(lot));

			const archiveBtn = document.createElement("button");
			archiveBtn.className = "ghost-btn small";
			archiveBtn.type = "button";
			archiveBtn.textContent = lot.archived ? "Unarchive" : "Archive";
			archiveBtn.addEventListener("click", (event) =>
				guarded(event.currentTarget, async () => {
					try {
						await api(`/api/inventory/${lot.id}`, {
							method: "PUT",
							body: JSON.stringify({ archived: !lot.archived }),
						});
						showToast(lot.archived ? "Lot unarchived." : "Lot archived.");
						await loadLots();
					} catch (error) {
						showToast(error.message, "fail");
					}
				}),
			);

			const logBtn = document.createElement("button");
			logBtn.className = "ghost-btn small";
			logBtn.type = "button";
			logBtn.textContent = "Log";
			logBtn.addEventListener("click", () => toggleLog(lot, tr, logBtn));

			const deleteBtn = document.createElement("button");
			deleteBtn.className = "ghost-btn small";
			deleteBtn.type = "button";
			deleteBtn.textContent = "Delete";
			deleteBtn.addEventListener("click", (event) =>
				guarded(event.currentTarget, async () => {
					if (!confirm(`Delete the ${lot.origin} lot? This cannot be undone.`))
						return;
					try {
						await api(`/api/inventory/${lot.id}`, { method: "DELETE" });
						showToast("Lot deleted.");
						if (editingId === lot.id) cancelEdit();
						await loadLots();
					} catch (error) {
						showToast(error.message, "fail");
					}
				}),
			);

			actions.append(editBtn, archiveBtn, logBtn, deleteBtn);
			tr.append(lotCell, processCell, remainingCell, purchasedCell, actions);
			return tr;
		}),
	);
}

async function toggleLog(lot, row, button) {
	const existing = row.nextElementSibling;
	if (existing?.classList.contains("lot-log-row")) {
		existing.remove();
		return;
	}
	guarded(button, async () => {
		try {
			const { log } = await api(`/api/inventory/${lot.id}`);
			const tr = document.createElement("tr");
			tr.className = "lot-log-row";
			const td = document.createElement("td");
			td.colSpan = 5;
			if (!log.length) {
				td.className = "empty-state";
				td.textContent = "No consumption recorded yet.";
			} else {
				const ul = document.createElement("ul");
				ul.style.margin = "0";
				ul.style.paddingLeft = "18px";
				for (const entry of log) {
					const li = document.createElement("li");
					li.style.fontSize = "12.5px";
					li.textContent = `${Math.round(entry.weightG)} g — ${entry.planTitle || "manual"} — ${fmtDate(entry.createdAt)}`;
					ul.append(li);
				}
				td.append(ul);
			}
			tr.append(td);
			row.after(tr);
		} catch (error) {
			showToast(error.message, "fail");
		}
	});
}

async function loadLots() {
	try {
		const body = await api("/api/inventory");
		lots = body.lots;
		renderLots();
	} catch (error) {
		document.getElementById("lots-body").innerHTML =
			`<tr><td colspan="5" class="empty-state">Could not load lots.</td></tr>`;
	}
}

function startEdit(lot) {
	editingId = lot.id;
	const form = document.getElementById("lot-form");
	form.id.value = lot.id;
	form.origin.value = lot.origin;
	form.variety.value = lot.variety;
	form.process.value = lot.process;
	form.producer.value = lot.producer;
	form.purchaseDate.value = lot.purchaseDate ? lot.purchaseDate.slice(0, 10) : "";
	form.initialWeightG.value = lot.initialWeightG;
	form.costTotal.value = lot.costTotal ?? "";
	form.moisturePct.value = lot.moisturePct ?? "";
	form.densityGL.value = lot.densityGL ?? "";
	form.notes.value = lot.notes;
	document.getElementById("lot-form-title").textContent = "Edit lot";
	document.getElementById("lot-form-submit").textContent = "Save changes";
	document.getElementById("lot-form-cancel").classList.remove("hidden");
	const note = document.getElementById("lot-remaining-note");
	note.classList.remove("hidden");
	note.textContent = `Remaining: ${Math.round(lot.remainingWeightG)} g — remaining weight is only changed by roasts drawing from the lot. Correct the initial weight and the remaining shifts with it.`;
	document.getElementById("lot-form-card").scrollIntoView({ behavior: "smooth" });
}

function cancelEdit() {
	editingId = null;
	const form = document.getElementById("lot-form");
	form.reset();
	form.id.value = "";
	document.getElementById("lot-form-title").textContent = "Add a lot";
	document.getElementById("lot-form-submit").textContent = "Add lot";
	document.getElementById("lot-form-cancel").classList.add("hidden");
	document.getElementById("lot-remaining-note").classList.add("hidden");
}

document.getElementById("lot-form-cancel").addEventListener("click", cancelEdit);
document.getElementById("show-archived").addEventListener("change", (event) => {
	showArchived = event.target.checked;
	renderLots();
});
document.getElementById("lot-form").addEventListener("submit", (event) => {
	event.preventDefault();
	const form = event.target;
	const data = Object.fromEntries(new FormData(form));
	const submitBtn = document.getElementById("lot-form-submit");
	guarded(submitBtn, async () => {
		try {
			const payload = {
				origin: data.origin,
				variety: data.variety,
				process: data.process,
				producer: data.producer,
				purchaseDate: data.purchaseDate || null,
				initialWeightG: Number(data.initialWeightG),
				costTotal: data.costTotal === "" ? null : Number(data.costTotal),
				moisturePct: data.moisturePct === "" ? null : Number(data.moisturePct),
				densityGL: data.densityGL === "" ? null : Number(data.densityGL),
				notes: data.notes,
			};
			if (editingId) {
				await api(`/api/inventory/${editingId}`, {
					method: "PUT",
					body: JSON.stringify(payload),
				});
				showToast("Lot updated.");
			} else {
				await api("/api/inventory", { method: "POST", body: JSON.stringify(payload) });
				showToast("Lot added.");
			}
			cancelEdit();
			await loadLots();
		} catch (error) {
			showToast(error.message, "fail");
		}
	});
});

// The LLM prefill endpoint returns raw `extracted` page facts — map the green-relevant ones
// into the lot form (only overwriting what the page actually stated).
document.getElementById("lot-prefill-btn").addEventListener("click", (event) =>
	guarded(event.currentTarget, async () => {
		const url = document.getElementById("lot-prefill-url").value.trim();
		const note = document.getElementById("lot-prefill-note");
		if (!url) return;
		note.classList.remove("hidden");
		note.textContent = "Reading the page with the LLM…";
		try {
			const body = await api("/api/prefill", {
				method: "POST",
				body: JSON.stringify({ url }),
			});
			const x = body.extracted ?? {};
			const form = document.getElementById("lot-form");
			if (x.origin) form.origin.value = x.origin;
			if (x.cultivar) form.variety.value = x.cultivar;
			if (x.process) form.process.value = x.process;
			if (x.producer) form.producer.value = x.producer;
			if (x.moisturePct) form.moisturePct.value = x.moisturePct;
			const filled = ["origin", "cultivar", "process", "producer", "moisturePct"]
				.filter((k) => x[k]).length;
			note.textContent = filled
				? `Prefilled ${filled} field${filled === 1 ? "" : "s"} — check them, then save.`
				: "The page didn't state anything usable — fill the form by hand.";
		} catch (error) {
			note.textContent = `Prefill failed: ${error.message}`;
		}
	}),
);

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

init();
