import { ChangeEvent, useCallback, useEffect, useState } from "react";
import { Project, useProjectId, useSetProject } 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 [projects, setProjects] = useState<Project[] | null>(null);
	const projectId = useProjectId();
	const setProject = useSetProject();
	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" }),
				);
				console.log(projectId, id, sortedProjects);
				setProjects(sortedProjects);
				if (id && !sortedProjects.some((p) => p.id === id)) {
					throw new Error("MUST NOT REACH!");
				}
				if (id == null) {
					if (projectId == null) {
						id = sortedProjects[0].id;
					} else {
						id = projectId;
					}
				}
				setProject(id);
			} catch (e) {
				console.log(e);
			}
		},
		[projectId, setProject, setProjects],
	);
	useEffect(() => {
		if (projects == null) {
			refreshProjects();
		}
	}, [refreshProjects, projects]);
	const [createNewOpen, setCreateNewOpen] = useState(false);
	const onSelect = useCallback(
		(id: string) => {
			if (id === "create-new") {
				setCreateNewOpen(true);
			} else {
				setProject(id);
			}
		},
		[setProject],
	);

	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={projectId}>
				<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>
					))}
					{(projects || []).length > 0 && <Separator />}
					<SelectItem key="create-new" 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>
		</>
	);
}
