import { v4 as uuidv4 } from "uuid";
import { NodeRect } from "./node-rect";
import {
	useStateStore,
	ServiceNode,
	ServiceTypes,
	nodeLabel,
	BoundEnvVar,
	AppState,
	nodeIsConnectable,
	GatewayTCPNode,
	GatewayHttpsNode,
	AppNode,
	GithubNode,
} from "@/lib/state";
import { KeyboardEvent, FocusEvent, useCallback, useEffect, useMemo, useState } from "react";
import { z } from "zod";
import { DeepPartial, EventType, useForm, ControllerRenderProps, FieldPath } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { Form, FormControl, FormField, FormItem, FormMessage } from "./ui/form";
import { Input } from "./ui/input";
import { Button } from "./ui/button";
import { Handle, Position, useNodes } from "@xyflow/react";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./ui/select";
import { PencilIcon, XIcon } from "lucide-react";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./ui/tooltip";
import { Textarea } from "./ui/textarea";

export function NodeApp(node: ServiceNode) {
	const { id, selected } = node;
	const isConnectablePorts = useMemo(() => nodeIsConnectable(node, "ports"), [node]);
	const isConnectableRepository = useMemo(() => nodeIsConnectable(node, "repository"), [node]);
	return (
		<NodeRect id={id} selected={selected} type={node.type} state={node.data.state}>
			<div style={{ padding: "10px 20px" }}>
				{nodeLabel(node)}
				<Handle
					id="repository"
					type={"target"}
					position={Position.Left}
					isConnectableStart={isConnectableRepository}
					isConnectableEnd={isConnectableRepository}
					isConnectable={isConnectableRepository}
				/>
				<Handle
					id="ports"
					type={"source"}
					position={Position.Top}
					isConnectableStart={isConnectablePorts}
					isConnectableEnd={isConnectablePorts}
					isConnectable={isConnectablePorts}
				/>
				<Handle
					id="env_var"
					type={"target"}
					position={Position.Bottom}
					isConnectableStart={true}
					isConnectableEnd={true}
					isConnectable={true}
				/>
			</div>
		</NodeRect>
	);
}

const schema = z.object({
	name: z.string().min(1, "requried"),
	type: z.enum(ServiceTypes),
});

const portSchema = z.object({
	name: z.string().min(1, "required"),
	value: z.coerce.number().gt(0, "must be positive").lte(65535, "must be less than 65535"),
});

const sourceSchema = z.object({
	id: z.string().min(1, "required"),
	branch: z.string(),
	rootDir: z.string(),
});

export function NodeAppDetails({ id, data }: ServiceNode) {
	const store = useStateStore();
	const nodes = useNodes<AppNode>();
	const form = useForm<z.infer<typeof schema>>({
		resolver: zodResolver(schema),
		mode: "onChange",
		defaultValues: {
			name: data.label,
			type: data.type,
		},
	});
	const portForm = useForm<z.infer<typeof portSchema>>({
		resolver: zodResolver(portSchema),
		mode: "onSubmit",
		defaultValues: {
			name: "",
			value: 0,
		},
	});
	const onSubmit = useCallback(
		(values: z.infer<typeof portSchema>) => {
			const portId = uuidv4();
			store.updateNodeData<"app">(id, {
				ports: (data.ports || []).concat({
					id: portId,
					name: values.name.toLowerCase(),
					value: values.value,
				}),
				envVars: (data.envVars || []).concat({
					id: uuidv4(),
					source: null,
					portId,
					name: `DODO_PORT_${values.name.toUpperCase()}`,
				}),
			});
			portForm.reset();
		},
		[id, data, portForm, store],
	);
	useEffect(() => {
		const sub = form.watch(
			(
				value: DeepPartial<z.infer<typeof schema>>,
				{ name, type }: { name?: keyof z.infer<typeof schema> | undefined; type?: EventType | undefined },
			) => {
				console.log({ name, type });
				if (type !== "change") {
					return;
				}
				switch (name) {
					case "name":
						if (!value.name) {
							break;
						}
						store.updateNodeData<"app">(id, {
							label: value.name,
						});
						break;
					case "type":
						if (!value.type) {
							break;
						}
						store.updateNodeData<"app">(id, {
							type: value.type,
						});
						break;
				}
			},
		);
		return () => sub.unsubscribe();
	}, [id, form, store]);
	const focus = useCallback(
		(field: ControllerRenderProps<z.infer<typeof schema>, FieldPath<z.infer<typeof schema>>>, name: string) => {
			return (e: HTMLElement | null) => {
				field.ref(e);
				if (e != null && name === data.activeField) {
					console.log(e);
					e.focus();
					store.updateNodeData(id, {
						activeField: undefined,
					});
				}
			};
		},
		[id, data, store],
	);
	const [typeProps, setTypeProps] = useState({});
	useEffect(() => {
		if (data.activeField === "type") {
			setTypeProps({
				open: true,
				onOpenChange: () => store.updateNodeData(id, { activeField: undefined }),
			});
		} else {
			setTypeProps({});
		}
	}, [id, data, store, setTypeProps]);
	const editAlias = useCallback(
		(e: BoundEnvVar) => {
			return () => {
				store.updateNodeData(id, {
					...data,
					envVars: data.envVars!.map((o) => {
						if (o.id !== e.id) {
							return o;
						} else
							return {
								...o,
								isEditting: true,
							};
					}),
				});
			};
		},
		[id, data, store],
	);
	const saveAlias = useCallback(
		(e: BoundEnvVar, value: string, store: AppState) => {
			store.updateNodeData(id, {
				...data,
				envVars: data.envVars!.map((o) => {
					if (o.id !== e.id) {
						return o;
					}
					if (value) {
						return {
							...o,
							isEditting: false,
							alias: value.toUpperCase(),
						};
					}
					console.log(o);
					if ("alias" in o) {
						const { alias: _, ...rest } = o;
						console.log(rest);
						return {
							...rest,
							isEditting: false,
						};
					}
					return {
						...o,
						isEditting: false,
					};
				}),
			});
		},
		[id, data],
	);
	const saveAliasOnEnter = useCallback(
		(e: BoundEnvVar) => {
			return (event: KeyboardEvent<HTMLInputElement>) => {
				if (event.key === "Enter") {
					event.preventDefault();
					saveAlias(e, event.currentTarget.value, store);
				}
			};
		},
		[store, saveAlias],
	);
	const saveAliasOnBlur = useCallback(
		(e: BoundEnvVar) => {
			return (event: FocusEvent<HTMLInputElement>) => {
				saveAlias(e, event.currentTarget.value, store);
			};
		},
		[store, saveAlias],
	);
	const removePort = useCallback(
		(portId: string) => {
			// TODO(gio): this is ugly
			const tcpRemoved = new Set<string>();
			console.log(store.edges);
			store.setEdges(
				store.edges.filter((e) => {
					if (e.source !== id || e.sourceHandle !== "ports") {
						return true;
					}
					const tn = store.nodes.find((n) => n.id == e.target)!;
					if (e.targetHandle === "https") {
						const t = tn as GatewayHttpsNode;
						if (t.data.https?.serviceId === id && t.data.https.portId === portId) {
							return false;
						}
					}
					if (e.targetHandle === "tcp") {
						const t = tn as GatewayTCPNode;
						if (tcpRemoved.has(t.id)) {
							return true;
						}
						if (t.data.exposed.find((e) => e.serviceId === id && e.portId === portId)) {
							tcpRemoved.add(t.id);
							return false;
						}
					}
					if (e.targetHandle === "env_var") {
						if (
							tn &&
							(tn.data.envVars || []).find(
								(ev) => ev.source === id && "portId" in ev && ev.portId === portId,
							)
						) {
							return false;
						}
					}
					return true;
				}),
			);
			store.nodes
				.filter(
					(n) =>
						n.type === "gateway-https" &&
						n.data.https &&
						n.data.https.serviceId === id &&
						n.data.https.portId === portId,
				)
				.forEach((n) => {
					store.updateNodeData<"gateway-https">(n.id, {
						https: undefined,
					});
				});
			store.nodes
				.filter((n) => n.type === "gateway-tcp")
				.forEach((n) => {
					const filtered = n.data.exposed.filter((e) => {
						if (e.serviceId === id && e.portId === portId) {
							return false;
						} else {
							return true;
						}
					});
					if (filtered.length != n.data.exposed.length) {
						store.updateNodeData<"gateway-tcp">(n.id, {
							exposed: filtered,
						});
					}
				});
			store.nodes
				.filter((n) => n.type === "app" && n.data.envVars)
				.forEach((n) => {
					store.updateNodeData<"app">(n.id, {
						envVars: n.data.envVars.filter((ev) => {
							if (ev.source === id && "portId" in ev && ev.portId === portId) {
								return false;
							}
							return true;
						}),
					});
				});
			store.updateNodeData<"app">(id, {
				ports: (data.ports || []).filter((p) => p.id !== portId),
				envVars: (data.envVars || []).filter(
					(ev) => !(ev.source === null && "portId" in ev && ev.portId === portId),
				),
			});
		},
		[id, data, store],
	);
	const setPreBuildCommands = useCallback(
		(e: React.ChangeEvent<HTMLTextAreaElement>) => {
			store.updateNodeData<"app">(id, {
				preBuildCommands: e.currentTarget.value,
			});
		},
		[id, store],
	);

	const sourceForm = useForm<z.infer<typeof sourceSchema>>({
		resolver: zodResolver(sourceSchema),
		mode: "onChange",
		defaultValues: {
			id: data?.repository?.id,
			branch: data.repository && "branch" in data.repository ? data.repository.branch : undefined,
			rootDir: data.repository && "rootDir" in data.repository ? data.repository.rootDir : undefined,
		},
	});
	useEffect(() => {
		const sub = sourceForm.watch(
			(
				value: DeepPartial<z.infer<typeof sourceSchema>>,
				{ name }: { name?: keyof z.infer<typeof sourceSchema> | undefined; type?: EventType | undefined },
			) => {
				console.log(value);
				if (name === "id") {
					let edges = store.edges;
					if (data?.repository?.id !== undefined) {
						edges = edges.filter((e) => {
							if (e.target === id && e.targetHandle === "repository" && e.source === data.repository.id) {
								return false;
							} else {
								return true;
							}
						});
					}
					if (value.id !== undefined) {
						edges = edges.concat({
							id: uuidv4(),
							source: value.id,
							sourceHandle: "repository",
							target: id,
							targetHandle: "repository",
						});
					}
					store.setEdges(edges);
					store.updateNodeData<"app">(id, {
						repository: {
							id: value.id,
						},
					});
				} else if (name === "branch") {
					store.updateNodeData<"app">(id, {
						repository: {
							...data?.repository,
							branch: value.branch,
						},
					});
				} else if (name === "rootDir") {
					store.updateNodeData<"app">(id, {
						repository: {
							...data?.repository,
							rootDir: value.rootDir,
						},
					});
				}
			},
		);
		return () => sub.unsubscribe();
	}, [id, data, sourceForm, store]);

	return (
		<>
			<Form {...form}>
				<form>
					<FormField
						control={form.control}
						name="name"
						render={({ field }) => (
							<FormItem>
								<FormControl>
									<Input
										placeholder="name"
										className="border border-black"
										{...field}
										ref={focus(field, "name")}
									/>
								</FormControl>
								<FormMessage />
							</FormItem>
						)}
					/>
					<FormField
						control={form.control}
						name="type"
						render={({ field }) => (
							<FormItem>
								<Select onValueChange={field.onChange} defaultValue={field.value} {...typeProps}>
									<FormControl>
										<SelectTrigger>
											<SelectValue placeholder="Runtime" />
										</SelectTrigger>
									</FormControl>
									<SelectContent>
										{ServiceTypes.map((t) => (
											<SelectItem key={t} value={t}>
												{t}
											</SelectItem>
										))}
									</SelectContent>
								</Select>
								<FormMessage />
							</FormItem>
						)}
					/>
				</form>
			</Form>
			Source
			<Form {...sourceForm}>
				<form className="space-y-2">
					<FormField
						control={sourceForm.control}
						name="id"
						render={({ field }) => (
							<FormItem>
								<Select onValueChange={field.onChange} defaultValue={field.value}>
									<FormControl>
										<SelectTrigger>
											<SelectValue placeholder="Repository" />
										</SelectTrigger>
									</FormControl>
									<SelectContent>
										{(
											nodes.filter(
												(n) => n.type === "github" && n.data.repository?.id !== undefined,
											) as GithubNode[]
										).map((n) => (
											<SelectItem
												key={n.id}
												value={n.id}
											>{`${n.data.repository?.fullName}`}</SelectItem>
										))}
									</SelectContent>
								</Select>
								<FormMessage />
							</FormItem>
						)}
					/>
					<FormField
						control={sourceForm.control}
						name="branch"
						render={({ field }) => (
							<FormItem>
								<FormControl>
									<Input placeholder="master" className="border border-black" {...field} />
								</FormControl>
								<FormMessage />
							</FormItem>
						)}
					/>
					<FormField
						control={sourceForm.control}
						name="rootDir"
						render={({ field }) => (
							<FormItem>
								<FormControl>
									<Input placeholder="/" className="border border-black" {...field} />
								</FormControl>
								<FormMessage />
							</FormItem>
						)}
					/>
				</form>
			</Form>
			Ports
			<ul>
				{data &&
					data.ports &&
					data.ports.map((p) => (
						<li key={p.id} className="flex flex-row items-center gap-1">
							<Button size={"icon"} variant={"ghost"} onClick={() => removePort(p.id)}>
								<XIcon />
							</Button>
							<div>
								{p.name} - {p.value}
							</div>
						</li>
					))}
			</ul>
			<Form {...portForm}>
				<form className="flex flex-row space-x-1" onSubmit={portForm.handleSubmit(onSubmit)}>
					<FormField
						control={portForm.control}
						name="name"
						render={({ field }) => (
							<FormItem>
								<FormControl>
									<Input placeholder="name" className="border border-black" {...field} />
								</FormControl>
								<FormMessage />
							</FormItem>
						)}
					/>
					<FormField
						control={portForm.control}
						name="value"
						render={({ field }) => (
							<FormItem>
								<FormControl>
									<Input placeholder="value" className="border border-black" {...field} />
								</FormControl>
								<FormMessage />
							</FormItem>
						)}
					/>
					<Button type="submit">Add Port</Button>
				</form>
			</Form>
			Env Vars
			<ul>
				{data &&
					data.envVars &&
					data.envVars.map((v) => {
						if ("name" in v) {
							const value = "alias" in v ? v.alias : v.name;
							if (v.isEditting) {
								return (
									<li key={v.id}>
										<Input
											type="text"
											className="border border-black"
											defaultValue={value}
											onKeyUp={saveAliasOnEnter(v)}
											onBlur={saveAliasOnBlur(v)}
											autoFocus={true}
										/>
									</li>
								);
							}
							return (
								<li key={v.id} onClick={editAlias(v)}>
									<TooltipProvider>
										<Tooltip>
											<TooltipTrigger>
												<div className="flex flex-row items-center gap-1">
													<Button size={"icon"} variant={"ghost"}>
														<PencilIcon />
													</Button>
													<div>{value}</div>
												</div>
											</TooltipTrigger>
											<TooltipContent>{v.name}</TooltipContent>
										</Tooltip>
									</TooltipProvider>
								</li>
							);
						}
					})}
			</ul>
			Pre-Build Commands
			<Textarea
				placeholder="new line separated list of commands to run before running the service"
				value={data.preBuildCommands}
				onChange={setPreBuildCommands}
			/>
		</>
	);
}
