import { v4 as uuidv4 } from "uuid";
import { NodeRect } from "./node-rect";
import {
	useStateStore,
	ServiceNode,
	ServiceTypes,
	nodeLabel,
	BoundEnvVar,
	AppState,
	nodeIsConnectable,
	GatewayTCPNode,
	GatewayHttpsNode,
	AppNode,
} 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, "can not be negative"),
});

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,
					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?.sshURL}`}</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}>
							<Button size={"icon"} variant={"ghost"} onClick={() => removePort(p.id)}>
								<XIcon />
							</Button>{" "}
							{p.name} - {p.value}
						</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>
												<Button size={"icon"} variant={"ghost"}>
													<PencilIcon />
												</Button>
												{value}
											</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}
			/>
		</>
	);
}
