import { v4 as uuidv4 } from "uuid";
import { NodeRect } from "./node-rect";
import {
	useStateStore,
	ServiceNode,
	ServiceTypes,
	nodeLabel,
	BoundEnvVar,
	AppState,
	nodeIsConnectable,
	GatewayTCPNode,
	GatewayHttpsNode,
	AppNode,
	GithubNode,
	useEnv,
} 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 { 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";
import { Input } from "./ui/input";
import { Checkbox } from "./ui/checkbox";
import { Label } from "./ui/label";

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(),
});

const devSchema = z.object({
	enabled: z.boolean(),
});

const exposeSchema = z.object({
	network: z.string().min(1, "reqired"),
	subdomain: z.string().min(1, "required"),
});

export function NodeAppDetails({ id, data, disabled }: ServiceNode & { disabled?: boolean }) {
	const store = useStateStore();
	const nodes = useNodes<AppNode>();
	const env = useEnv();
	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]);
	const devForm = useForm<z.infer<typeof devSchema>>({
		resolver: zodResolver(devSchema),
		mode: "onChange",
		defaultValues: {
			enabled: data.dev ? data.dev.enabled : false,
		},
	});
	useEffect(() => {
		const sub = devForm.watch((value, { name }) => {
			if (name === "enabled") {
				if (value.enabled) {
					const csGateway: Omit<GatewayHttpsNode, "position"> = {
						id: uuidv4(),
						type: "gateway-https",
						data: {
							readonly: true,
							https: {
								serviceId: id,
								portId: `${id}-code-server`,
							},
							network: data.dev?.expose?.network,
							subdomain: data.dev?.expose?.subdomain,
							label: "",
							envVars: [],
							ports: [],
						},
					};
					const sshGateway: Omit<GatewayTCPNode, "position"> = {
						id: uuidv4(),
						type: "gateway-tcp",
						data: {
							readonly: true,
							exposed: [
								{
									serviceId: id,
									portId: `${id}-ssh`,
								},
							],
							network: data.dev?.expose?.network,
							subdomain: data.dev?.expose?.subdomain,
							label: "",
							envVars: [],
							ports: [],
						},
					};
					store.addNode(csGateway);
					store.addNode(sshGateway);
					store.updateNodeData<"app">(id, {
						dev: {
							enabled: true,
							expose: data.dev?.expose,
							codeServerNodeId: csGateway.id,
							sshNodeId: sshGateway.id,
						},
						ports: (data.ports || []).concat(
							{
								id: `${id}-code-server`,
								name: "code-server",
								value: 9090,
							},
							{
								id: `${id}-ssh`,
								name: "ssh",
								value: 22,
							},
						),
					});
					let edges = store.edges.concat([
						{
							id: uuidv4(),
							source: id,
							sourceHandle: "ports",
							target: csGateway.id,
							targetHandle: "https",
						},
						{
							id: uuidv4(),
							source: id,
							sourceHandle: "ports",
							target: sshGateway.id,
							targetHandle: "tcp",
						},
					]);
					if (data.dev?.expose?.network !== undefined) {
						edges = edges.concat([
							{
								id: uuidv4(),
								source: csGateway.id,
								sourceHandle: "subdomain",
								target: data.dev.expose.network,
								targetHandle: "subdomain",
							},
							{
								id: uuidv4(),
								source: sshGateway.id,
								sourceHandle: "subdomain",
								target: data.dev.expose.network,
								targetHandle: "subdomain",
							},
						]);
					}
					store.setEdges(edges);
				} else {
					const { dev } = data;
					if (dev?.enabled) {
						store.setNodes(
							store.nodes.filter((n) => n.id !== dev.codeServerNodeId && n.id !== dev.sshNodeId),
						);
						store.setEdges(
							store.edges.filter((e) => e.target !== dev.codeServerNodeId && e.target !== dev.sshNodeId),
						);
					}
					store.updateNodeData<"app">(id, {
						dev: {
							enabled: false,
							expose: dev?.expose,
						},
						ports: (data.ports || []).filter((p) => p.name !== "code-server" && p.name !== "ssh"),
					});
				}
			}
		});
		return () => sub.unsubscribe();
	}, [id, data, devForm, store]);
	const exposeForm = useForm<z.infer<typeof exposeSchema>>({
		resolver: zodResolver(exposeSchema),
		mode: "onChange",
		defaultValues: {
			network: data.dev?.expose?.network,
			subdomain: data.dev?.expose?.subdomain,
		},
	});
	useEffect(() => {
		const sub = exposeForm.watch(
			(
				value: DeepPartial<z.infer<typeof exposeSchema>>,
				{ name }: { name?: keyof z.infer<typeof exposeSchema> | undefined; type?: EventType | undefined },
			) => {
				const { dev } = data;
				if (!dev?.enabled) {
					return;
				}
				if (name === "network") {
					let edges = store.edges;
					if (dev.enabled && dev.expose?.network !== undefined) {
						edges = edges.filter((e) => {
							if (
								(e.source === dev.codeServerNodeId || e.source === dev.sshNodeId) &&
								e.sourceHandle === "subdomain" &&
								e.target === dev.expose?.network &&
								e.targetHandle === "subdomain"
							) {
								return false;
							} else {
								return true;
							}
						});
					}
					if (value.network !== undefined) {
						edges = edges.concat(
							{
								id: uuidv4(),
								source: dev.codeServerNodeId,
								sourceHandle: "subdomain",
								target: value.network,
								targetHandle: "subdomain",
							},
							{
								id: uuidv4(),
								source: dev.sshNodeId,
								sourceHandle: "subdomain",
								target: value.network,
								targetHandle: "subdomain",
							},
						);
					}
					store.setEdges(edges);
					store.updateNodeData<"app">(id, {
						dev: {
							...dev,
							expose: {
								network: value.network,
								subdomain: dev.expose?.subdomain,
							},
						},
					});
					store.updateNodeData<"gateway-https">(dev.codeServerNodeId, { network: value.network });
					store.updateNodeData<"gateway-tcp">(dev.sshNodeId, { network: value.network });
				} else if (name === "subdomain") {
					store.updateNodeData<"app">(id, {
						dev: {
							...dev,
							expose: {
								network: dev.expose?.network,
								subdomain: value.subdomain,
							},
						},
					});
					store.updateNodeData<"gateway-https">(dev.codeServerNodeId, { subdomain: value.subdomain });
					store.updateNodeData<"gateway-tcp">(dev.sshNodeId, { subdomain: value.subdomain });
				}
			},
		);
		return () => sub.unsubscribe();
	}, [id, data, exposeForm, store]);
	return (
		<>
			<Form {...exposeForm}>
				<form className="space-y-2">
					<FormField
						control={form.control}
						name="name"
						render={({ field }) => (
							<FormItem>
								<FormControl>
									<Input
										placeholder="name"
										className="lowercase"
										{...field}
										ref={focus(field, "name")}
										disabled={disabled}
									/>
								</FormControl>
								<FormMessage />
							</FormItem>
						)}
					/>
					<FormField
						control={form.control}
						name="type"
						render={({ field }) => (
							<FormItem>
								<Select
									onValueChange={field.onChange}
									defaultValue={field.value}
									{...typeProps}
									disabled={disabled}
								>
									<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} disabled={disabled}>
									<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="lowercase" {...field} disabled={disabled} />
								</FormControl>
								<FormMessage />
							</FormItem>
						)}
					/>
					<FormField
						control={sourceForm.control}
						name="rootDir"
						render={({ field }) => (
							<FormItem>
								<FormControl>
									<Input placeholder="/" {...field} disabled={disabled} />
								</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)}
								className="w-4 h-4"
								disabled={disabled}
							>
								<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="lowercase" {...field} disabled={disabled} />
								</FormControl>
								<FormMessage />
							</FormItem>
						)}
					/>
					<FormField
						control={portForm.control}
						name="value"
						render={({ field }) => (
							<FormItem>
								<FormControl>
									<Input placeholder="value" {...field} disabled={disabled} />
								</FormControl>
								<FormMessage />
							</FormItem>
						)}
					/>
					<Button type="submit" disabled={disabled}>
						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="uppercase"
											defaultValue={value}
											onKeyUp={saveAliasOnEnter(v)}
											onBlur={saveAliasOnBlur(v)}
											autoFocus={true}
											disabled={disabled}
										/>
									</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"} className="w-4 h-4">
														<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}
				disabled={disabled}
			/>
			Dev
			<Form {...devForm}>
				<form className="space-y-2">
					<FormField
						control={devForm.control}
						name="enabled"
						render={({ field }) => (
							<FormItem>
								<div className="flex flex-row gap-1 items-center">
									<Checkbox
										id="devEnabled"
										onCheckedChange={field.onChange}
										checked={field.value}
										disabled={disabled}
									/>
									<Label htmlFor="devEnabled">Enabled</Label>
								</div>
								<FormMessage />
							</FormItem>
						)}
					/>
				</form>
			</Form>
			{data.dev && data.dev.enabled && (
				<Form {...exposeForm}>
					<form className="space-y-2">
						<FormField
							control={exposeForm.control}
							name="network"
							render={({ field }) => (
								<FormItem>
									<Select
										onValueChange={field.onChange}
										defaultValue={field.value}
										disabled={disabled}
									>
										<FormControl>
											<SelectTrigger>
												<SelectValue placeholder="Network" />
											</SelectTrigger>
										</FormControl>
										<SelectContent>
											{env.networks.map((n) => (
												<SelectItem
													key={n.name}
													value={n.domain}
												>{`${n.name} - ${n.domain}`}</SelectItem>
											))}
										</SelectContent>
									</Select>
									<FormMessage />
								</FormItem>
							)}
						/>
						<FormField
							control={exposeForm.control}
							name="subdomain"
							render={({ field }) => (
								<FormItem>
									<FormControl>
										<Input placeholder="subdomain" {...field} disabled={disabled} />
									</FormControl>
									<FormMessage />
								</FormItem>
							)}
						/>
					</form>
				</Form>
			)}
		</>
	);
}
