import { ChangeEvent, useCallback, useEffect, useState } from "react";
import { Project, useProjectId, useStateStore } from "./lib/state";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./components/ui/select";
import { Input } from "./components/ui/input";
import { Button } from "./components/ui/button";
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "./components/ui/dialog";
import { useToast } from "@/hooks/use-toast";
import { Separator } from "./components/ui/separator";
import { Plus } from "lucide-react";
import { z } from "zod";
import { cn } from "./lib/utils";

const createNewSchema = z.object({
	id: z.string().min(1),
});

export function ProjectSelect({ className }: { className?: string }) {
	const { toast } = useToast();
	const store = useStateStore();
	const [projects, setProjects] = useState<Project[]>([]);
	const projectId = useProjectId();
	// Track the selected project ID locally to ensure UI consistency
	const [selectedId, setSelectedId] = useState<string | undefined>(projectId);

	// Keep local state in sync with global state
	useEffect(() => {
		setSelectedId(projectId);
	}, [projectId]);

	const refreshProjects = useCallback(
		async (id?: string) => {
			console.log("refreshProjects", id);
			try {
				const resp = await fetch("/api/project");
				const projectList = await resp.json();
				const sortedProjects = [...projectList].sort((a, b) =>
					a.name.localeCompare(b.name, undefined, { sensitivity: "base" }),
				);
				setProjects(sortedProjects);
				if (id && !sortedProjects.some((p) => p.id === id)) {
					throw new Error("MUST NOT REACH!");
				}
				if (id == null) {
					id = sortedProjects[0].id;
				}
				if (id !== selectedId) {
					setSelectedId(id);
					store.setProject(id);
				}
			} catch (e) {
				console.log(e);
			}
		},
		[selectedId, store, setProjects, setSelectedId],
	);

	useEffect(() => {
		refreshProjects();
	}, [refreshProjects]);

	const [createNewOpen, setCreateNewOpen] = useState(false);
	const onSelect = useCallback(
		(projectId: string) => {
			if (projectId === "create-new") {
				setCreateNewOpen(true);
			} else {
				setSelectedId(projectId);
				store.setProject(projectId);
			}
		},
		[store, setSelectedId],
	);

	const [name, setName] = useState<string | undefined>(undefined);
	const updateName = useCallback(
		(e: ChangeEvent<HTMLInputElement>) => {
			setName(e.target.value);
		},
		[setName],
	);

	const createNew = useCallback(() => {
		if (!name) {
			toast({
				variant: "destructive",
				title: "Name is required",
			});
			return;
		}
		fetch("/api/project", {
			method: "POST",
			headers: {
				"Content-Type": "application/json",
			},
			body: JSON.stringify({
				name: name,
			}),
		})
			.then(async (resp) => {
				if (!resp.ok) {
					return false;
				}
				const result = createNewSchema.safeParse(await resp.json());
				if (!result.success) {
					toast({
						variant: "destructive",
						title: `Failed to create project: ${name}`,
					});
					return;
				}
				const { id } = result.data;
				await refreshProjects(id);
				setCreateNewOpen(false);
				setName(undefined); // Clear the input for next time
				toast({
					title: `Created project: ${name}`,
				});
			})
			.catch((e) => {
				console.log(e);
				toast({
					variant: "destructive",
					title: `Failed to create project: ${name}`,
				});
			});
	}, [name, setCreateNewOpen, toast, refreshProjects]);

	return (
		<>
			<Select onValueChange={onSelect} value={selectedId}>
				<SelectTrigger
					className={cn("!border-none", "!shadow-none", "!focus:ring-0", "!focus:ring-offset-0", className)}
				>
					<SelectValue placeholder="Choose Project" />
				</SelectTrigger>
				<SelectContent>
					{projects.map((p) => (
						<SelectItem key={p.id} value={p.id}>
							{p.name}
						</SelectItem>
					))}
					<Separator />
					<SelectItem value={"create-new"}>
						<div className="flex flex-row items-center gap-1">
							<Plus />
							<div>New project</div>
						</div>
					</SelectItem>
				</SelectContent>
			</Select>
			<Dialog open={createNewOpen} onOpenChange={setCreateNewOpen}>
				<DialogContent>
					<DialogHeader>
						<DialogTitle>New project</DialogTitle>
					</DialogHeader>
					<Input
						type="text"
						placeholder="Name"
						onChange={updateName}
						value={name || ""}
						onKeyDown={(e) => {
							if (e.key === "Enter") {
								createNew();
							}
						}}
					/>
					<DialogFooter>
						<Button onClick={createNew}>Create</Button>
					</DialogFooter>
				</DialogContent>
			</Dialog>
		</>
	);
}
