<script lang="ts">
	import { chart } from "@ui/directives/chart";
	import { ALL_TIME } from "@ui/stores/date-filter.svelte";
	import { getMetadataContext } from "@ui/stores/metadata.svelte";
	import { getReadingLogContext } from "@ui/stores/reading-log.svelte";
	import { getSettingsContext } from "@ui/stores/settings.svelte";
	import { Color } from "@utils/color";
	import type { ChartConfiguration } from "chart.js";

	const settingsStore = getSettingsContext();
	const store = getMetadataContext();
	const readingLog = getReadingLogContext();

	const isMonthly = $derived(
		store.filterYear !== ALL_TIME && store.filterMonth !== ALL_TIME,
	);

	const items = $derived(
		isMonthly
			? readingLog.entries.map((entry) => ({
					pageCount: entry.pagesRead,
					date: entry.createdAt,
				}))
			: store.metadata.map((f) => ({
					pageCount:
						f.frontmatter[settingsStore.settings.pageCountProperty],
					// @ts-expect-error Moment is provided by Obsidian
					date: moment(
						f.frontmatter[settingsStore.settings.endDateProperty],
					),
				})),
	);

	const config = $derived.by(() => {
		const books = new Map<number, number>();
		const pages = new Map<number, number>();
		for (const item of items) {
			let key: number;
			if (store.filterYear === ALL_TIME) {
				key = item.date.year();
			} else if (store.filterMonth === ALL_TIME) {
				key = item.date.month();
			} else {
				key = item.date.date();
			}

			const pageCount = pages.get(key) ?? 0;
			pages.set(key, pageCount + item.pageCount);

			const bookCount = books.get(key) ?? 0;
			books.set(key, bookCount + 1);
		}

		if (isMonthly && typeof store.filterMonth === "number") {
			// @ts-expect-error Moment is provided by Obsidian
			const daysInMonth = moment()
				.month(store.filterMonth - 1)
				.daysInMonth();

			for (let i = 1; i <= daysInMonth; i++) {
				if (!pages.has(i)) {
					books.set(i, 0);
					pages.set(i, 0);
				}
			}
		}

		const labels = Array.from(books.keys())
			.sort((a, b) => a - b)
			.map((key) =>
				store.filterYear === ALL_TIME || isMonthly
					? key
					: // @ts-expect-error Moment is provided by Obsidian
						moment().month(key).format("MMM"),
			);
		const sortedBooks = Array.from(books.entries())
			.sort((a, b) => a[0] - b[0])
			.map((b) => b[1]);
		const sortedPages = Array.from(pages.entries())
			.sort((a, b) => a[0] - b[0])
			.map((p) => p[1]);

		let datasets = [
			{
				label: "Pages",
				data: sortedPages,
				borderColor: Color.fromName("blue").hex,
				backgroundColor: Color.fromName("blue").alpha(0.5).rgba,
				yAxisID: isMonthly ? "y" : "y1",
			},
		];
		if (!isMonthly) {
			datasets.push({
				label: "Books",
				data: sortedBooks,
				borderColor: Color.fromName("red").hex,
				backgroundColor: Color.fromName("red").alpha(0.5).rgba,
				yAxisID: "y",
			});
		}

		return {
			type: "line",
			data: {
				labels,
				datasets,
			},
			options: {
				scales: {
					y: {
						type: "linear",
						display: true,
						position: "left",
						ticks: { beginAtZero: true },
					},
					y1: {
						type: "linear",
						display: !isMonthly,
						position: "right",
						grid: { drawOnChartArea: false },
					},
				},
			},
		} as ChartConfiguration;
	});
</script>

<canvas use:chart={config}></canvas>
