import { useEffect } from "react";
import { createFileRoute } from "@tanstack/react-router";
import { create } from "zustand";
import clsx from "clsx";
import { Button } from "~/components/button";
import type { LinkBookmark } from "~/bookmark";

const testBookmarks: LinkBookmark[] = [
	{
		kind: "link",
		id: "1",
		title: "Running a Docker container as a non-root user",
		url: "https://test.website.com/article/123",
	},
	{
		kind: "link",
		id: "2",
		title: "Running a Docker container as a non-root user",
		url: "https://test.website.com/article/123",
	},
];

const LAYOUT_MODE = {
	popup: "popup",
	sideBySide: "side-by-side",
} as const;
type LayoutMode = (typeof LAYOUT_MODE)[keyof typeof LAYOUT_MODE];

interface BookmarkPageState {
	bookmarks: LinkBookmark[];
	selectedBookmarkIndex: number;
	isBookmarkItemExpanded: boolean;
	isBookmarkPreviewOpened: boolean;
	layoutMode: LayoutMode;

	setBookmarkItemExpanded: (isExpanded: boolean) => void;
	setBookmarkPreviewOpened: (isOpened: boolean) => void;
	setLayoutMode: (mode: LayoutMode) => void;
	selectBookmarkAt: (index: number) => void;
}

const useBookmarkPageStore = create<BookmarkPageState>()((set, get) => ({
	bookmarks: testBookmarks,
	selectedBookmarkIndex: 0,
	isBookmarkItemExpanded: false,
	isBookmarkPreviewOpened: false,
	layoutMode: LAYOUT_MODE.popup,

	setBookmarkItemExpanded(isExpanded: boolean) {
		set({ isBookmarkItemExpanded: isExpanded });
	},

	setBookmarkPreviewOpened(isOpened: boolean) {
		set({ isBookmarkPreviewOpened: isOpened });
	},

	setLayoutMode(mode: LayoutMode) {
		set({ layoutMode: mode });
	},

	selectBookmarkAt(index: number) {
		const bookmarks = get().bookmarks;
		if (index >= 0 && index < bookmarks.length) {
			set({ selectedBookmarkIndex: index });
		}
	},
}));

function Page() {
	const setLayoutMode = useBookmarkPageStore((state) => state.setLayoutMode);

	useEffect(() => {
		function onKeyDown(event: KeyboardEvent) {
			const state = useBookmarkPageStore.getState();

			switch (event.key) {
				case "ArrowDown":
					state.selectBookmarkAt(state.selectedBookmarkIndex + 1);
					break;
				case "ArrowUp":
					state.selectBookmarkAt(state.selectedBookmarkIndex - 1);
					break;
				case "ArrowLeft":
					state.setBookmarkItemExpanded(false);
					break;
				case "ArrowRight":
					state.setBookmarkItemExpanded(true);
					break;
				default:
					break;
			}
		}

		window.addEventListener("keydown", onKeyDown);

		return () => {
			window.removeEventListener("keydown", onKeyDown);
		};
	}, [useBookmarkPageStore]);

	useEffect(() => {
		function mediaQueryListener(this: MediaQueryList) {
			if (this.matches) {
				setLayoutMode(LAYOUT_MODE.sideBySide);
			} else {
				setLayoutMode(LAYOUT_MODE.popup);
			}
		}

		const q = window.matchMedia("(width >= 64rem)");
		q.addEventListener("change", mediaQueryListener);

		mediaQueryListener.call(q);

		return () => {
			q.removeEventListener("change", mediaQueryListener);
		};
	}, []);

	return (
		<div className="flex justify-center h-full">
			<Main>
				<div className="flex flex-col md:flex-row justify-center py-16 lg:py-32 ">
					<header className="mb-4 md:mb-0 md:mr-16 text-start">
						<h1 className="font-bold text-start">
							<span className="invisible md:hidden">&gt;&nbsp;</span>
							YOUR BOOKMARKS
						</h1>
					</header>
					<div className="flex flex-col container max-w-2xl -mt-2">
						{testBookmarks.map((bookmark, i) => (
							<BookmarkListItem
								key={bookmark.id}
								index={i}
								bookmark={bookmark}
							/>
						))}
					</div>
				</div>
				<BookmarkPreview />
			</Main>
		</div>
	);
}

function Main({ children }: React.PropsWithChildren) {
	const isPreviewOpened = useBookmarkPageStore(
		(state) => state.isBookmarkPreviewOpened,
	);
	const layoutMode = useBookmarkPageStore((state) => state.layoutMode);

	return (
		<main
			className={clsx(
				"px-4 lg:px-8 2xl:px-0 grid flex justify-center relative w-full",
				isPreviewOpened && layoutMode === LAYOUT_MODE.sideBySide
					? "grid-cols-2"
					: "grid-cols-1",
			)}
		>
			{children}
		</main>
	);
}

function BookmarkPreview() {
	const isVisible = useBookmarkPageStore(
		(state) => state.isBookmarkPreviewOpened,
	);
	const layoutMode = useBookmarkPageStore((state) => state.layoutMode);

	if (!isVisible) {
		return null;
	}

	return (
		<div
			className={clsx(
				"h-screen flex justify-center items-center border-l border-stone-700 dark:border-stone-300 flex dark:bg-stone-900",
				{
					"absolute inset-0 border-l-0": layoutMode === LAYOUT_MODE.popup,
				},
			)}
		>
			<p>Content here</p>
		</div>
	);
}

function BookmarkListItem({
	bookmark,
	index,
}: { bookmark: LinkBookmark; index: number }) {
	const url = new URL(bookmark.url);
	const selectedBookmark = useBookmarkPageStore(
		(state) => state.bookmarks[state.selectedBookmarkIndex],
	);
	const isSelected = selectedBookmark.id === bookmark.id;
	const isBookmarkItemExpanded = useBookmarkPageStore(
		(state) => state.isBookmarkItemExpanded,
	);
	const setBookmarkItemExpanded = useBookmarkPageStore(
		(state) => state.setBookmarkItemExpanded,
	);
	const selectBookmarkAt = useBookmarkPageStore(
		(state) => state.selectBookmarkAt,
	);
	const setBookmarkPreviewOpened = useBookmarkPageStore(
		(state) => state.setBookmarkPreviewOpened,
	);

	function expandOrOpenPreview() {
		setBookmarkItemExpanded(true);
		if (useBookmarkPageStore.getState().layoutMode === LAYOUT_MODE.sideBySide) {
			console.log(useBookmarkPageStore.getState().layoutMode);
			setBookmarkPreviewOpened(true);
		}
	}

	return (
		<div
			className={clsx("group flex flex-row justify-start py-2", {
				"bg-teal-600 text-stone-100": isBookmarkItemExpanded && isSelected,
				"text-teal-600": isSelected && !isBookmarkItemExpanded,
			})}
			onMouseEnter={() => {
				if (!isBookmarkItemExpanded) {
					selectBookmarkAt(index);
				}
			}}
		>
			<button
				disabled={!isSelected}
				className={clsx(
					"select-none flex items-start font-bold hover:bg-teal-600 hover:text-stone-100",
					{
						invisible: !isSelected,
					},
				)}
				onClick={() => {
					setBookmarkItemExpanded(!isBookmarkItemExpanded);
					setBookmarkPreviewOpened(false);
				}}
			>
				<span className="sr-only">Options for this bookmark</span>
				<span>&nbsp;</span>
				<span className={isBookmarkItemExpanded ? "rotate-90" : ""}>&gt;</span>
				<span>&nbsp;</span>
			</button>
			<div className="flex flex-col w-full">
				<button className="text-start font-bold" onClick={expandOrOpenPreview}>
					{bookmark.title}
				</button>
				<p className="opacity-80 text-sm">{url.host}</p>
				{isBookmarkItemExpanded && isSelected ? (
					<div className="flex flex-col space-y-1 md:flex-row md:space-y-0 md:space-x-2 items-end justify-between pt-2">
						<p className="text-sm">
							#dev #devops #devops #devops #devops #devops #devops
						</p>
						<div className="flex space-x-2">
							<OpenBookmarkPreviewButton />
							<Button className="text-sm">
								<span className="underline">E</span>dit
							</Button>
							<Button className="text-sm">
								<span className="underline">D</span>elete
							</Button>
							<span className="-ml-2">&nbsp;</span>
						</div>
					</div>
				) : null}
			</div>
		</div>
	);
}

function OpenBookmarkPreviewButton() {
	const isBookmarkPreviewOpened = useBookmarkPageStore(
		(state) => state.isBookmarkPreviewOpened,
	);
	const setBookmarkPreviewOpened = useBookmarkPageStore(
		(state) => state.setBookmarkPreviewOpened,
	);
	const setBookmarkItemExpanded = useBookmarkPageStore(
		(state) => state.setBookmarkItemExpanded,
	);

	useEffect(() => {
		function onKeyDown(event: KeyboardEvent) {
			if (isBookmarkPreviewOpened && event.key === "c") {
				closePreview();
			} else if (!isBookmarkPreviewOpened && event.key === "o") {
				openPreview();
			}
		}

		window.addEventListener("keydown", onKeyDown);

		return () => {
			window.removeEventListener("keydown", onKeyDown);
		};
	}, [isBookmarkPreviewOpened]);

	function closePreview() {
		setBookmarkPreviewOpened(false);
		setBookmarkItemExpanded(false);
	}

	function openPreview() {
		setBookmarkPreviewOpened(true);
	}

	return (
		<Button
			className="text-sm"
			onClick={() => {
				if (isBookmarkPreviewOpened) {
					closePreview();
				} else {
					openPreview();
				}
			}}
		>
			{isBookmarkPreviewOpened ? (
				<>
					<span className="underline">C</span>lose
				</>
			) : (
				<>
					<span className="underline">O</span>pen
				</>
			)}
		</Button>
	);
}

export const Route = createFileRoute("/$username/bookmarks")({
	component: Page,
});
