<script lang="ts">
	import type { ReadingLogEntry } from "@utils/ReadingLog";
	import { Edit, Trash, Plus } from "lucide-svelte";
	import { ReadingLogEntryEditModal } from "@ui/modals";
	import type BookTrackerPlugin from "@src/main";

	const ALL_TIME = "ALL_TIME";

	interface Props {
		plugin: BookTrackerPlugin;
	}

	let { plugin }: Props = $props();

	function bookUri(book: string) {
		const v = encodeURIComponent(plugin.app.vault.getName());
		const f = encodeURIComponent(book + ".md");
		return `obsidian://open?vault=${v}&file=${f}`;
	}

	let entries = $state(
		plugin.readingLog.getEntries().map((entry, id) => ({
			...entry,
			id,
		})),
	);

	function reload() {
		entries = plugin.readingLog.getEntries().map((entry, id) => ({
			...entry,
			id,
		}));
	}

	const years = $derived([
		...new Set(entries.map((entry) => entry.createdAt.year())),
	]);

	// @ts-expect-error Moment is provided by Obsidian
	let selectedYear = $state(moment().year().toString());
	const filterYear = $derived(
		selectedYear === ALL_TIME ? ALL_TIME : parseInt(selectedYear, 10),
	);

	// @ts-expect-error Moment is provided by Obsidian
	let selectedMonth = $state(moment().format("MM"));
	const filterMonth = $derived(
		selectedMonth === "" ? undefined : parseInt(selectedMonth, 10),
	);

	const filteredEntries = $derived.by(() => {
		if (filterYear === ALL_TIME) {
			return entries;
		}

		// @ts-expect-error Moment is provided by Obsidian
		let startDate = moment().year(filterYear).startOf("year");

		// @ts-expect-error Moment is provided by Obsidian
		let endDate = moment().year(filterYear).endOf("year");

		if (filterMonth !== undefined) {
			startDate = startDate.month(filterMonth - 1).startOf("month");
			endDate = endDate.month(filterMonth - 1).endOf("month");
		}

		return entries.filter((entry) => {
			return (
				entry.createdAt.isSameOrAfter(startDate) &&
				entry.createdAt.isSameOrBefore(endDate)
			);
		});
	});

	function createEntry() {
		const modal = new ReadingLogEntryEditModal(plugin, async (entry) => {
			modal.close();
			await plugin.readingLog.addRawEntry(entry);
			reload();
		});
		modal.open();
	}

	function editEntry(i: number, entry: ReadingLogEntry) {
		const modal = new ReadingLogEntryEditModal(
			plugin,
			async (entry) => {
				modal.close();
				await plugin.readingLog.updateEntry(i, entry);
				reload();
			},
			entry,
		);
		modal.open();
	}

	async function deleteEntry(i: number) {
		await plugin.readingLog.spliceEntry(i);
		reload();
	}
</script>

<div class="obt-reading-log-viewer">
	<div class="controls">
		<div class="left">
			<select class="year-filter" bind:value={selectedYear}>
				{#each years as year}
					<option value={year.toString()}>{year}</option>
				{/each}
				<option class="all-time" value={ALL_TIME}>All Time</option>
			</select>
			<select class="month-filter" bind:value={selectedMonth}>
				<option value="">Select Month</option>
				<option value="01">January</option>
				<option value="02">February</option>
				<option value="03">March</option>
				<option value="04">April</option>
				<option value="05">May</option>
				<option value="06">June</option>
				<option value="07">July</option>
				<option value="08">August</option>
				<option value="09">September</option>
				<option value="10">October</option>
				<option value="11">November</option>
				<option value="12">December</option>
			</select>
		</div>
		<div class="right">
			<button onclick={createEntry} class="create-entry" type="button">
				<Plus />
				Create
			</button>
		</div>
	</div>

	<table>
		<thead>
			<tr>
				<th class="date">Date</th>
				<th class="book">Book</th>
				<th class="pages-read">Pages Read</th>
				<th class="percent-complete">Percent Complete</th>
				<th class="actions">Actions</th>
			</tr>
		</thead>
		<tbody>
			{#each filteredEntries as entry}
				<tr>
					<td class="date">{entry.createdAt.format("YYYY-MM-DD")}</td>
					<td class="book"
						><a href={bookUri(entry.book)}>{entry.book}</a></td
					>
					<td class="pages-read">{entry.pagesRead}</td>
					<td class="percent-complete">
						{Math.round(
							(entry.pagesReadTotal /
								(entry.pagesReadTotal + entry.pagesRemaining)) *
								100,
						)}%
					</td>
					<td class="actions">
						<button onclick={() => editEntry(entry.id, entry)}>
							<Edit />
							<span>Edit</span>
						</button>
						<button onclick={() => deleteEntry(entry.id)}>
							<Trash />
							<span>Delete</span>
						</button>
					</td>
				</tr>
			{:else}
				<tr>
					<td colspan="5">No entries found</td>
				</tr>
			{/each}
		</tbody>
	</table>
</div>

<!-- svelte-ignore css_unused_selector -->
<style lang="scss">
	@use "../styles/utils";

	.obt-reading-log-viewer {
		.controls {
			display: grid;
			grid-template-columns: 1fr 1fr;
			align-items: center;

			.right {
				text-align: right;

				button.create-entry {
					display: inline-flex;
					gap: var(--size-2-2);
					align-items: center;

					:global(svg) {
						width: var(--icon-s);
						height: var(--icon-s);
					}
				}
			}
		}

		.year-filter:has(> option.all-time:checked) + .month-filter {
			display: none;
		}

		table {
			width: 100%;

			td.book {
				width: 100%;
			}

			th,
			td:not(.book) {
				white-space: nowrap;
			}

			td.pages-read,
			td.percent-complete {
				text-align: center;
			}

			td.actions span {
				@include utils.visually-hidden;
			}
		}
	}
</style>
