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

const fmtDate = (v) => (v ? new Date(v).toLocaleDateString() : "—");

async function guarded(button, run) {
	if (!button || button.disabled) return;
	button.disabled = true;
	try {
		await run();
	} finally {
		button.disabled = false;
	}
}

function renderBeans() {
	const body = document.getElementById("beans-body");
	const visible = showArchived ? beans : beans.filter((b) => !b.archived);
	if (!visible.length) {
		body.innerHTML = `<tr><td colspan="6" class="empty-state">No beans yet. Add a bag below — paste the roaster's product URL to prefill the details.</td></tr>`;
		return;
	}
	body.replaceChildren(
		...visible.map((bean) => {
			const tr = document.createElement("tr");
			if (bean.archived) tr.className = "archived";

			const beanCell = document.createElement("td");
			const strong = document.createElement("strong");
			strong.textContent = bean.name;
			const sub = document.createElement("div");
			sub.className = "muted";
			sub.style.fontSize = "11.5px";
			sub.textContent =
				[bean.roaster, bean.roastLevel].filter(Boolean).join(" · ") || "—";
			beanCell.append(strong, sub);

			const originCell = document.createElement("td");
			originCell.textContent =
				[bean.origin, bean.process].filter(Boolean).join(" · ") || "—";

			const roastedCell = document.createElement("td");
			roastedCell.textContent = fmtDate(bean.roastDate);

			const remainingCell = document.createElement("td");
			if (bean.initialWeightG == null) remainingCell.textContent = "—";
			else {
				const pct = bean.initialWeightG > 0
					? Math.max(0, Math.min(100, (bean.remainingWeightG / bean.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 (bean.remainingWeightG < 0) fill.classList.add("over");
				fill.style.width = `${bean.remainingWeightG < 0 ? 0 : pct}%`;
				bar.append(fill);
				const label = document.createElement("span");
				label.className = "blend-total-label";
				label.textContent = `${Math.round(bean.remainingWeightG)} g of ${Math.round(bean.initialWeightG)} g`;
				wrap.append(bar, label);
				remainingCell.append(wrap);
			}

			const brewsCell = document.createElement("td");
			brewsCell.className = "num";
			const brewsLink = document.createElement("a");
			brewsLink.href = `/brews?bean=${encodeURIComponent(bean.id)}`;
			brewsLink.textContent = String(bean.brewCount ?? 0);
			brewsCell.append(brewsLink);

			const actions = document.createElement("td");
			actions.className = "data-table-actions";
			const brewBtn = document.createElement("a");
			brewBtn.className = "ghost-btn small";
			brewBtn.href = `/brews?new=1&bean=${encodeURIComponent(bean.id)}`;
			brewBtn.textContent = "Brew";
			const editBtn = document.createElement("button");
			editBtn.className = "ghost-btn small";
			editBtn.type = "button";
			editBtn.textContent = "Edit";
			editBtn.addEventListener("click", () => startEdit(bean));
			const archiveBtn = document.createElement("button");
			archiveBtn.className = "ghost-btn small";
			archiveBtn.type = "button";
			archiveBtn.textContent = bean.archived ? "Unarchive" : "Archive";
			archiveBtn.addEventListener("click", (event) =>
				guarded(event.currentTarget, async () => {
					try {
						await api(`/api/beans/${bean.id}`, {
							method: "PUT",
							body: JSON.stringify({ archived: !bean.archived }),
						});
						showToast(bean.archived ? "Bean unarchived." : "Bean archived.");
						await loadBeans();
					} catch (error) {
						showToast(error.message, "fail");
					}
				}),
			);
			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 "${bean.name}"? Its logged brews are kept but lose the bean link.`,
						)
					)
						return;
					try {
						await api(`/api/beans/${bean.id}`, { method: "DELETE" });
						showToast("Bean deleted.");
						if (editingId === bean.id) cancelEdit();
						await loadBeans();
					} catch (error) {
						showToast(error.message, "fail");
					}
				}),
			);
			actions.append(brewBtn, editBtn, archiveBtn, deleteBtn);

			tr.append(beanCell, originCell, roastedCell, remainingCell, brewsCell, actions);
			return tr;
		}),
	);
}

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

function startEdit(bean) {
	editingId = bean.id;
	const form = document.getElementById("bean-form");
	form.name.value = bean.name;
	form.roaster.value = bean.roaster;
	form.origin.value = bean.origin;
	form.process.value = bean.process;
	form.variety.value = bean.variety;
	form.roastLevel.value = bean.roastLevel;
	form.roastDate.value = bean.roastDate ? bean.roastDate.slice(0, 10) : "";
	form.initialWeightG.value = bean.initialWeightG ?? "";
	form.tastingNotes.value = bean.tastingNotes;
	form.url.value = bean.url;
	form.notes.value = bean.notes;
	document.getElementById("bean-form-title").textContent = "Edit bean";
	document.getElementById("bean-form-submit").textContent = "Save changes";
	document.getElementById("bean-form-cancel").classList.remove("hidden");
	document.getElementById("bean-form-card").scrollIntoView({ behavior: "smooth" });
}

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

// The LLM prefill endpoint returns raw `extracted` page facts — map them straight into the
// bean form (only overwriting fields the page actually stated).
function wirePrefill() {
	const button = document.getElementById("bean-prefill-btn");
	const note = document.getElementById("bean-prefill-note");
	button.addEventListener("click", () =>
		guarded(button, async () => {
			const url = document.getElementById("bean-prefill-url").value.trim();
			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("bean-form");
				const setIf = (field, value) => {
					if (value) form[field].value = value;
				};
				setIf("name", x.coffeeName);
				setIf("roaster", x.producer);
				setIf("origin", x.origin);
				setIf("process", x.process);
				setIf("variety", x.cultivar);
				setIf("roastLevel", x.roastLevel);
				if (Array.isArray(x.tastingNotes) && x.tastingNotes.length)
					form.tastingNotes.value = x.tastingNotes.join(", ");
				form.url.value = url;
				const filled = ["coffeeName", "producer", "origin", "process", "cultivar", "roastLevel"]
					.filter((k) => x[k]).length + (x.tastingNotes?.length ? 1 : 0);
				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("bean-form-cancel").addEventListener("click", cancelEdit);
document.getElementById("show-archived").addEventListener("change", (event) => {
	showArchived = event.target.checked;
	renderBeans();
});
document.getElementById("bean-form").addEventListener("submit", (event) => {
	event.preventDefault();
	const form = event.target;
	const data = Object.fromEntries(new FormData(form));
	guarded(document.getElementById("bean-form-submit"), async () => {
		try {
			const payload = {
				name: data.name,
				roaster: data.roaster,
				origin: data.origin,
				process: data.process,
				variety: data.variety,
				roastLevel: data.roastLevel,
				roastDate: data.roastDate || null,
				initialWeightG: data.initialWeightG === "" ? null : Number(data.initialWeightG),
				tastingNotes: data.tastingNotes,
				url: data.url,
				notes: data.notes,
			};
			if (editingId) {
				await api(`/api/beans/${editingId}`, {
					method: "PUT",
					body: JSON.stringify(payload),
				});
				showToast("Bean updated.");
			} else {
				await api("/api/beans", { method: "POST", body: JSON.stringify(payload) });
				showToast("Bean added.");
			}
			cancelEdit();
			await loadBeans();
		} catch (error) {
			showToast(error.message, "fail");
		}
	});
});

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;
	wirePrefill();
	await loadBeans();
}

init();
