export const buildInventoryTimeline = (
	weeklyDemand: Array<{
		MaterialHumanReadableId: string;
		WeekStart: string;
		WeeklyDemand: number;
	}>,
	opening: Record<string, number>,
	weeklyPurchases?: Array<{
		MaterialHumanReadableId: string;
		WeekStart: string;
		WeeklyPurchase: number;
	}>,
) => {
	// group weekly demand by material
	const groupedDemand: Record<
		string,
		Array<{ WeekStart: string; Demand: number }>
	> = {};
	for (const d of weeklyDemand) {
		const mat = d.MaterialHumanReadableId;
		groupedDemand[mat] ??= [];
		groupedDemand[mat].push({
			WeekStart: d.WeekStart,
			Demand: Number(d.WeeklyDemand),
		});
	}

	// group weekly purchases by material
	const groupedPurchases: Record<
		string,
		Array<{ WeekStart: string; Purchase: number }>
	> = {};
	if (weeklyPurchases) {
		for (const p of weeklyPurchases) {
			const mat = p.MaterialHumanReadableId;
			groupedPurchases[mat] ??= [];
			groupedPurchases[mat].push({
				WeekStart: p.WeekStart,
				Purchase: Number(p.WeeklyPurchase),
			});
		}
	}

	// sort both chronologically
	for (const mat of Object.keys(groupedDemand)) {
		groupedDemand[mat].sort(
			(a, b) =>
				new Date(a.WeekStart).getTime() - new Date(b.WeekStart).getTime(),
		);
	}
	for (const mat of Object.keys(groupedPurchases)) {
		groupedPurchases[mat].sort(
			(a, b) =>
				new Date(a.WeekStart).getTime() - new Date(b.WeekStart).getTime(),
		);
	}

	const result: Array<{
		MaterialHumanReadableId: string;
		WeekStart: string;
		OpeningInventory: number;
		Purchases: number;
		Consumption: number;
		ClosingInventory: number;
	}> = [];

	for (const [mat, weeks] of Object.entries(groupedDemand)) {
		let inv = opening[mat] ?? 0;
		const purchasesForMaterial = groupedPurchases[mat] ?? [];

		for (const week of weeks) {
			const demand = Number(week.Demand);
			const purchase =
				purchasesForMaterial.find((p) => p.WeekStart === week.WeekStart)
					?.Purchase ?? 0;

			const openingInv = inv;
			const adjustedInv = openingInv + purchase;
			const closingInv = adjustedInv - demand;

			result.push({
				MaterialHumanReadableId: mat,
				WeekStart: week.WeekStart,
				OpeningInventory: Number(openingInv.toFixed(2)),
				Purchases: Number(purchase.toFixed(2)),
				Consumption: Number(demand.toFixed(2)),
				ClosingInventory: Number(closingInv.toFixed(2)),
			});

			inv = closingInv;
		}
	}

	return result;
};
