"use client";
import EditableText from "@/components/editable-text";
import { LocalEditor } from "@/components/editor";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Dialog, DialogTrigger, DialogContent } from "@/components/ui/dialog";
import useApiMutation, { useApi } from "@/hooks/use-api";
import sluggify from "@/lib/sluggify";
import { Blog, Category, NewBlog } from "@/types/types";
import { useEffect, useMemo, useState } from "react";
import { DialogTitle } from "@radix-ui/react-dialog";
import { useToast } from "@/hooks/use-toast";
import {
	ActionButton,
	ActionButtonDefault,
	ActionButtonError,
	ActionButtonLoading,
	ActionButtonSuccess,
} from "@/components/action-button";
import ComboBox from "@/components/ui/combobox";

export type BlogState = Partial<Blog> & {
	[K in keyof Required<Blog>]?: Blog[K] | null; // Allows null for resetting or un-setting fields
};

export default function BlogEditor({ blog }: { blog?: Blog }) {
	const { toast } = useToast();

	const setItem = (b: BlogState) =>
		blog
			? localStorage.setItem(`draft_${blog.blogID}`, JSON.stringify(b))
			: localStorage.setItem("draft", JSON.stringify(b));

	const [draft, setDraft] = useState<BlogState>(() => {
		if (blog) {
			setItem(blog);
			return blog;
		}

		const d = {
			slug: "",
			content: "",
			title: "",
			category: "",
			image: "/placeholder.svg",
		};

		try {
			const _draft = localStorage.getItem("draft");
			if (_draft) {
				const draft: BlogState = JSON.parse(_draft);
				return draft;
			}
		} catch (e) {}

		return d;
	});

	const handleChange =
		(field: keyof BlogState) =>
		(e: React.ChangeEvent<HTMLInputElement> | string) => {
			const value = typeof e === "string" ? e : e.target.value;
			setDraft((prev) => {
				const n: typeof prev = {
					...prev,
					[field]: value,
				};
				setItem(n);
				return n;
			});
		};

	const { data } = useApi<Category[]>(
		"/blogs/categories",
		undefined,
		false,
		false,
	);

	const [categories, setCategories] = useState<string[]>(
		draft.category ? [draft.category] : [],
	);

	useEffect(() => {
		if (data) setCategories(data.map((c) => c.category) ?? []);
	}, [data]);

	const slug = useMemo(() => {
		const slug = draft.title ? sluggify(draft.title) : "";
		handleChange("slug")(slug);
		return slug;
	}, [draft.title]);

	const newBlog = useApiMutation<undefined, NewBlog>(
		"/blogs/new",
		{},
		"POST",
		true,
		false,
	);

	const updateBlog = useApiMutation(
		`/blogs/${blog?.blogID}/update`,
		{},
		"PATCH",
		true,
		false,
	);

	const handleNewBlog = async () => {
		try {
			if (!draft.content) return;
			if (!draft.title || draft.title.length < 1) return;
			const res = await newBlog.trigger({
				title: draft.title,
				summary: draft.summary,
				image: draft.image,
				slug,
				content: draft.content,
				category: draft.category,
			});
			if (!res) {
				toast({ title: "Aucune réponse du serveur." });
				return;
			}
			if (res.status === "Error") {
				toast({
					title: "Erreur.",
					content: "Une erreur est survenue.",
				});
			}
			if (res.data) console.log(res.data);
			return res;
		} catch (error: any) {
			toast({
				title: "Erreur.",
				content: "Une erreur est survenue.",
			});
		}
	};

	const handleUpdateBlog = async () => {
		try {
			if (!draft.content) return;
			if (!draft.title || draft.title.length < 1) return;
			const res = await updateBlog.trigger({
				title: draft.title,
				summary: draft.summary,
				image: draft.image,
				slug,
				content: draft.content,
				category: draft.category,
			});
			if (!res) {
				toast({ title: "Aucune réponse du serveur." });
				return;
			}
			if (res.status === "Error") {
				toast({
					title: "Erreur.",
					content: "Une erreur est survenue.",
				});
			}
			if (res.data) console.log(res.data);
			return res;
		} catch (error: any) {
			toast({
				title: "Erreur.",
				content: "Une erreur est survenue.",
			});
		}
	};

	return (
		<section className="m-10 flex flex-col gap-4">
			<div className="flex flex-col gap-4">
				<EditableText onChange={handleChange("title")}>
					<h1>
						{draft.title && draft.title.length > 0
							? draft.title
							: "Un titre doit-être fourni"}
					</h1>
				</EditableText>
				<p className="italic">{slug}</p>
				<Dialog>
					<DialogTrigger>
						<img
							src={draft.image}
							alt="Blog cover"
							className="w-full h-60 object-cover cursor-pointer rounded-lg"
						/>
					</DialogTrigger>
					<DialogTitle></DialogTitle>
					<DialogContent>
						<Input
							type="text"
							placeholder="Enter image URL"
							value={draft.image}
							onChange={handleChange("image")}
						/>
					</DialogContent>
				</Dialog>
				<div className="flex gap-4">
					<Input
						type="text"
						placeholder="Enter a summary"
						value={draft.summary}
						onChange={handleChange("summary")}
					/>
					<ComboBox
						value={draft.category ?? ""}
						onValueChange={handleChange("category")}
						key={categories.join(",")}
						elements={categories}
						trigger={(value) => (
							<Button>
								{value ?? "Selectionner une catégorie"}
							</Button>
						)}
						onSubmit={(value) => {
							setCategories((prev) => {
								if (prev.includes(value)) return prev;
								return [...prev, value];
							});
							handleChange("category")(value);
						}}
					>
						{(Item, element) => (
							<Item value={element} key={element} label={element}>
								{element}
							</Item>
						)}
					</ComboBox>
				</div>
			</div>
			<div className="flex">
				<div className="flex-1">
					<LocalEditor
						onChange={handleChange("content")}
						content={draft.content ?? ""}
						onTitleChange={handleChange("title")}
					/>
				</div>
			</div>

			<ActionButton
				isLoading={newBlog.isMutating || updateBlog.isMutating}
				isSuccess={newBlog.isSuccess || updateBlog.isSuccess}
				error={newBlog.error || updateBlog.error}
				onClick={blog ? handleUpdateBlog : handleNewBlog}
			>
				<ActionButtonDefault>
					{blog ? "Modifier" : "Publier"}
				</ActionButtonDefault>
				<ActionButtonSuccess />
				<ActionButtonError />
				<ActionButtonLoading />
			</ActionButton>
		</section>
	);
}
