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]);
	console.log("asd", projectId);
	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>
		</>
	);
}
