import { Readable } from "stream";
import { Document } from "mongoose";
import { IStory, Story } from "~/models/stories";
import { FormStory } from "~/lib/client/types/form/story";
import storyQuerier from "~/lib/server/dbHelpers/storyQuerier";
import isLoggedIn from "~/lib/server/middlewareButNotReally/isLoggedIn";
import { canModify } from "~/lib/server/middlewareButNotReally/storyPrivileges";
import {
	bodyHandler,
	getBucket,
	modelFormChapter,
	replaceOrUploadContent,
} from "~/lib/server/storyHelpers";
import { countWords } from "~/lib/functions";
import { messages } from "~/lib/server/constants";

export default eventHandler(async (ev) => {
	let os:
		| (Document<unknown, {}, IStory> &
				IStory &
				Required<{
					_id: number;
				}>)
		| null = await storyQuerier(ev);
	isLoggedIn(ev);
	if (!canModify(ev, os)) {
		throw createError({
			statusCode: 403,
			message: messages[403],
		});
	}
	const body: FormStory = await readBody<FormStory>(ev);
	const update: Partial<IStory> = {
		title: body.title,
		completed: body.completed,
		chapters: [],
	};
	for (const oc of os.chapters) {
		let filename = `/stories/${oc.id}.txt`;
		const bucket = getBucket();
		const curs = bucket.find({ filename }).limit(1);
		for await (const d of curs) {
			await bucket.delete(d._id);
		}
	}
	for (const c of body.chapters) {
		let idx = os.chapters.findIndex((k) => k.id === c.id);
		const cont = await bodyHandler(c);
		if (idx === -1) {
			update.chapters!.push({
				...modelFormChapter(c),
				posted: new Date(Date.now()),
			});
		} else {
			update.chapters!.push({
				...modelFormChapter(c),
				id: os.chapters[idx].id,
				posted: os.chapters[idx].posted,
			});
			replaceOrUploadContent(os.chapters![idx].id, cont);
		}
		update.chapters![update.chapters!.length - 1].words = countWords(cont);
	}
	os = await Story.findOneAndUpdate(
		{
			_id: os._id,
		},
		update,
		{ new: true },
	);
	if (!os) {
		throw createError({
			statusCode: 500,
			message: "Something went wrong.",
		});
	}
	return {
		success: true,
		data: os.toObject(),
	};
});
