import { v4 as uuidv4 } from "uuid";
import { NodeRect } from "./node-rect";
import { useStateStore, nodeLabel, AppState, nodeIsConnectable, useEnv, useGithubRepositories } from "@/lib/state";
import { ServiceNode, ServiceTypes } from "config";
import { KeyboardEvent, FocusEvent, useCallback, useEffect, useMemo, useState } from "react";
import { z } from "zod";
import { useForm, EventType, DeepPartial } 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 { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./ui/tooltip";
import { Textarea } from "./ui/textarea";
import { Input } from "./ui/input";
import { Switch } from "./ui/switch";
import { Label } from "./ui/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./ui/tabs";
import { Code, Container, Network, Pencil, Variable } from "lucide-react";
import { Badge } from "./ui/badge";
import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from "./ui/accordion";
import { Name } from "./node-name";
import { NodeDetailsProps } from "@/lib/types";

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 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({ node, disabled, showName = true, isOverview = false }: NodeDetailsProps<ServiceNode>) {
	const { data } = node;
	return (
		<>
			{showName ? <Name node={node} disabled={disabled} /> : null}
			<Tabs defaultValue="runtime">
				<TabsList className="w-full flex flex-row justify-between">
					<TabsTrigger value="runtime">
						{isOverview ? (
							<div className="flex flex-row gap-1 items-center">
								<Container /> Runtime
							</div>
						) : (
							<TooltipProvider>
								<Tooltip>
									<TooltipTrigger>
										<Container />
									</TooltipTrigger>
									<TooltipContent>Runtime</TooltipContent>
								</Tooltip>
							</TooltipProvider>
						)}
					</TabsTrigger>
					<TabsTrigger value="ports">
						{isOverview ? (
							<div className="flex flex-row gap-1 items-center">
								<Network /> Ports
								<Badge className="rounded-full">{data.ports?.length ?? 0}</Badge>
							</div>
						) : (
							<TooltipProvider>
								<Tooltip>
									<TooltipTrigger className="flex flex-row gap-1 items-center">
										<Network />
									</TooltipTrigger>
									<TooltipContent>
										Ports{" "}
										<Badge variant="secondary" className="rounded-full">
											{data.ports?.length ?? 0}
										</Badge>
									</TooltipContent>
								</Tooltip>
							</TooltipProvider>
						)}
					</TabsTrigger>
					<TabsTrigger value="vars">
						{isOverview ? (
							<div className="flex flex-row gap-1 items-center">
								<Variable /> Variables
								<Badge className="rounded-full">{data.envVars?.length ?? 0}</Badge>
							</div>
						) : (
							<TooltipProvider>
								<Tooltip>
									<TooltipTrigger className="flex flex-row gap-1 items-center">
										<Variable />
									</TooltipTrigger>
									<TooltipContent>
										Variables{" "}
										<Badge variant="secondary" className="rounded-full">
											{data.envVars?.length ?? 0}
										</Badge>
									</TooltipContent>
								</Tooltip>
							</TooltipProvider>
						)}
					</TabsTrigger>
					<TabsTrigger value="dev">
						{isOverview ? (
							<div className="flex flex-row gap-1 items-center">
								<Code /> Dev
							</div>
						) : (
							<TooltipProvider>
								<Tooltip>
									<TooltipTrigger className="flex flex-row gap-1 items-center">
										<Code />
									</TooltipTrigger>
									<TooltipContent>Dev</TooltipContent>
								</Tooltip>
							</TooltipProvider>
						)}
					</TabsTrigger>
				</TabsList>
				<TabsContent value="runtime">
					<Runtime node={node} disabled={disabled} />
				</TabsContent>
				<TabsContent value="ports">
					<Ports node={node} disabled={disabled} />
				</TabsContent>
				<TabsContent value="vars">
					<EnvVars node={node} disabled={disabled} />
				</TabsContent>
				<TabsContent value="dev">
					<Dev node={node} disabled={disabled} />
				</TabsContent>
			</Tabs>
		</>
	);
}

function Runtime({ node, disabled }: { node: ServiceNode; disabled?: boolean }): React.ReactNode {
	const { id, data } = node;
	const store = useStateStore();
	const form = useForm<z.infer<typeof schema>>({
		resolver: zodResolver(schema),
		mode: "onChange",
		defaultValues: {
			name: data.label,
			type: data.type,
		},
	});
	useEffect(() => {
		const sub = form.watch(
			(
				value: DeepPartial<z.infer<typeof schema>>,
				{ name, type }: { name?: keyof z.infer<typeof schema> | undefined; type?: EventType | undefined },
			) => {
				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 [typeProps, setTypeProps] = useState({});
	useEffect(() => {
		if (data.activeField === "type") {
			setTypeProps({
				open: true,
				onOpenChange: () => store.updateNodeData(id, { activeField: undefined }),
			});
		} else {
			setTypeProps({});
		}
	}, [id, data, store, setTypeProps]);
	const setPreBuildCommands = useCallback(
		(e: React.ChangeEvent<HTMLTextAreaElement>) => {
			store.updateNodeData<"app">(id, {
				preBuildCommands: e.currentTarget.value,
			});
		},
		[id, store],
	);
	return (
		<>
			<SourceRepo node={node} disabled={disabled} />
			<Form {...form}>
				<form className="space-y-2">
					<Label>Container Image</Label>
					<FormField
						control={form.control}
						name="type"
						render={({ field }) => (
							<FormItem>
								<Select
									onValueChange={field.onChange}
									value={field.value || ""}
									{...typeProps}
									disabled={disabled}
								>
									<FormControl>
										<SelectTrigger>
											<SelectValue />
										</SelectTrigger>
									</FormControl>
									<SelectContent>
										{ServiceTypes.map((t) => (
											<SelectItem key={t} value={t}>
												{t}
											</SelectItem>
										))}
									</SelectContent>
								</Select>
								<FormMessage />
							</FormItem>
						)}
					/>
				</form>
			</Form>
			<Label>Pre-Build Commands</Label>
			<Textarea
				placeholder="new line separated list of commands to run before running the service"
				value={data.preBuildCommands}
				onChange={setPreBuildCommands}
				disabled={disabled}
			/>
		</>
	);
}

function Ports({ node, disabled }: { node: ServiceNode; disabled?: boolean }): React.ReactNode {
	const { id, data } = node;
	const store = useStateStore();
	const [name, setName] = useState("");
	const [value, setValue] = useState("");
	const onSubmit = useCallback(() => {
		const portId = uuidv4();
		store.updateNodeData<"app">(id, {
			ports: (data.ports || []).concat({
				id: portId,
				name: name.toUpperCase(),
				value: Number(value),
			}),
			envVars: (data.envVars || []).concat({
				id: uuidv4(),
				source: null,
				portId,
				name: `DODO_PORT_${name.toUpperCase()}`,
			}),
		});
		setName("");
		setValue("");
	}, [id, data, store, name, value, setName, setValue]);
	const removePort = useCallback(
		(portId: string) => {
			// TODO(gio): this is ugly
			const tcpRemoved = new Set<string>();
			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],
	);
	return (
		<div className="flex flex-col gap-1">
			<div className="grid grid-cols-[1fr_1fr_auto] gap-1">
				{data &&
					data.ports &&
					data.ports.map((p) => (
						<>
							<div className="flex items-center px-3">{p.name.toUpperCase()}</div>
							<div className="flex items-center px-3">{p.value}</div>
							<div className="flex items-center">
								<Button
									variant="destructive"
									className="w-full"
									onClick={() => removePort(p.id)}
									disabled={disabled}
								>
									Remove
								</Button>
							</div>
						</>
					))}
				<div>
					<Input
						placeholder="name"
						className="uppercase w-0 min-w-full"
						disabled={disabled}
						value={name}
						onChange={(e) => setName(e.target.value)}
					/>
				</div>
				<div>
					<Input
						placeholder="0"
						className="w-0 min-w-full"
						disabled={disabled}
						value={value}
						onChange={(e) => setValue(e.target.value)}
					/>
				</div>
				<div>
					<Button type="submit" className="w-full" disabled={disabled} onClick={onSubmit}>
						Add
					</Button>
				</div>
			</div>
		</div>
	);
}

function EnvVars({ node, disabled }: { node: ServiceNode; disabled?: boolean }): React.ReactNode {
	const { id, data } = node;
	const store = useStateStore();
	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(),
						};
					}
					if ("alias" in o) {
						const { alias: _, ...rest } = o;
						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],
	);
	return (
		<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 className="w-full">
											<div className="w-full flex flex-row items-center gap-1 cursor-text">
												<Pencil className="w-4 h-4" />
												<div className="uppercase">{value}</div>
											</div>
										</TooltipTrigger>
										<TooltipContent>{v.name}</TooltipContent>
									</Tooltip>
								</TooltipProvider>
							</li>
						);
					}
				})}
		</ul>
	);
}

function Dev({ node, disabled }: { node: ServiceNode; disabled?: boolean }): React.ReactNode {
	const { id, data } = node;
	const env = useEnv();
	const store = useStateStore();
	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 {...devForm}>
				<form className="space-y-2">
					<FormField
						control={devForm.control}
						name="enabled"
						render={({ field }) => (
							<FormItem>
								<div className="flex flex-row gap-1 items-center">
									<Switch
										id="devEnabled"
										onCheckedChange={field.onChange}
										checked={field.value}
										disabled={disabled}
									/>
									<Label htmlFor="devEnabled">Dev VM</Label>
								</div>
								<FormMessage />
							</FormItem>
						)}
					/>
				</form>
			</Form>
			{data.dev && data.dev.enabled && (
				<Form {...exposeForm}>
					<form className="space-y-2">
						<Label>Network</Label>
						<FormField
							control={exposeForm.control}
							name="network"
							render={({ field }) => (
								<FormItem>
									<Select
										onValueChange={field.onChange}
										value={field.value || ""}
										disabled={disabled}
									>
										<FormControl>
											<SelectTrigger>
												<SelectValue />
											</SelectTrigger>
										</FormControl>
										<SelectContent>
											{env.networks.map((n) => (
												<SelectItem
													key={n.name}
													value={n.domain}
												>{`${n.name} - ${n.domain}`}</SelectItem>
											))}
										</SelectContent>
									</Select>
									<FormMessage />
								</FormItem>
							)}
						/>
						<Label>Subdomain</Label>
						<FormField
							control={exposeForm.control}
							name="subdomain"
							render={({ field }) => (
								<FormItem>
									<FormControl>
										<Input {...field} disabled={disabled} />
									</FormControl>
									<FormMessage />
								</FormItem>
							)}
						/>
					</form>
				</Form>
			)}
		</>
	);
}

function SourceRepo({ node, disabled }: { node: ServiceNode; disabled?: boolean }): React.ReactNode {
	const { id, data } = node;
	const store = useStateStore();
	const nodes = useNodes<AppNode>();
	const repo = useMemo(() => {
		return nodes
			.filter((n): n is GithubNode => n.type === "github")
			.find((n) => n.id === data.repository?.repoNodeId);
	}, [nodes, data.repository?.repoNodeId]);
	const repos = useGithubRepositories();
	const sourceForm = useForm<z.infer<typeof sourceSchema>>({
		resolver: zodResolver(sourceSchema),
		mode: "onChange",
		defaultValues: {
			id: data?.repository?.id?.toString(),
			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 },
			) => {
				if (name === "id") {
					const newRepoId = value.id ? parseInt(value.id, 10) : undefined;
					if (!newRepoId) return;

					const oldGithubNodeId = data.repository?.repoNodeId;
					const selectedRepo = repos.find((r) => r.id === newRepoId);

					if (!selectedRepo) return;

					// If a node for the selected repo already exists, connect to it.
					const existingNodeForSelectedRepo = nodes
						.filter((n): n is GithubNode => n.type === "github")
						.find((n) => n.data.repository?.id === selectedRepo.id);

					if (existingNodeForSelectedRepo) {
						let { nodes, edges } = store;
						if (oldGithubNodeId) {
							edges = edges.filter(
								(e) =>
									!(
										e.target === id &&
										e.source === oldGithubNodeId &&
										e.targetHandle === "repository"
									),
							);
						}
						edges = edges.concat({
							id: uuidv4(),
							source: existingNodeForSelectedRepo.id,
							sourceHandle: "repository",
							target: id,
							targetHandle: "repository",
						});
						nodes = nodes.map((n) => {
							if (n.id !== id) {
								return n;
							} else {
								const sn = n as ServiceNode;
								return {
									...sn,
									data: {
										...sn.data,
										repository: {
											...sn.data.repository,
											id: newRepoId,
											repoNodeId: existingNodeForSelectedRepo.id,
										},
									},
								};
							}
						});
						if (oldGithubNodeId && oldGithubNodeId !== existingNodeForSelectedRepo.id) {
							const isOldNodeStillUsed = edges.some(
								(e) => e.source === oldGithubNodeId && e.sourceHandle === "repository",
							);
							if (!isOldNodeStillUsed) {
								nodes = nodes.filter((n) => n.id !== oldGithubNodeId);
							}
						}
						store.setNodes(nodes);
						store.setEdges(edges);
						return;
					}

					// No node for selected repo, decide whether to update old node or create a new one.
					if (oldGithubNodeId) {
						const isOldNodeShared =
							store.edges.filter(
								(e) =>
									e.source === oldGithubNodeId && e.target !== id && e.sourceHandle === "repository",
							).length > 0;

						if (!isOldNodeShared) {
							// Update old node
							store.updateNodeData<"github">(oldGithubNodeId, {
								repository: {
									id: selectedRepo.id,
									sshURL: selectedRepo.ssh_url,
									fullName: selectedRepo.full_name,
								},
								label: selectedRepo.full_name,
							});
							store.updateNodeData<"app">(id, {
								repository: {
									...data.repository,
									id: newRepoId,
								},
							});
						} else {
							// Create new node because old one is shared
							const newGithubNodeId = uuidv4();
							store.addNode({
								id: newGithubNodeId,
								type: "github",
								data: {
									repository: {
										id: selectedRepo.id,
										sshURL: selectedRepo.ssh_url,
										fullName: selectedRepo.full_name,
									},
									label: selectedRepo.full_name,
									envVars: [],
									ports: [],
								},
							});

							let edges = store.edges;
							// remove old edge
							edges = edges.filter(
								(e) =>
									!(
										e.target === id &&
										e.source === oldGithubNodeId &&
										e.targetHandle === "repository"
									),
							);
							// add new edge
							edges = edges.concat({
								id: uuidv4(),
								source: newGithubNodeId,
								sourceHandle: "repository",
								target: id,
								targetHandle: "repository",
							});
							store.setEdges(edges);
							store.updateNodeData<"app">(id, {
								repository: {
									...data.repository,
									id: newRepoId,
									repoNodeId: newGithubNodeId,
								},
							});
						}
					} else {
						// No old github node, so create a new one
						const newGithubNodeId = uuidv4();
						store.addNode({
							id: newGithubNodeId,
							type: "github",
							data: {
								repository: {
									id: selectedRepo.id,
									sshURL: selectedRepo.ssh_url,
									fullName: selectedRepo.full_name,
								},
								label: selectedRepo.full_name,
								envVars: [],
								ports: [],
							},
						});
						store.setEdges(
							store.edges.concat({
								id: uuidv4(),
								source: newGithubNodeId,
								sourceHandle: "repository",
								target: id,
								targetHandle: "repository",
							}),
						);
						store.updateNodeData<"app">(id, {
							repository: {
								...data.repository,
								id: newRepoId,
								repoNodeId: newGithubNodeId,
							},
						});
					}
				} 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, nodes, repos]);
	const [isExpanded, setIsExpanded] = useState(false);
	// useEffect(() => {
	// 	if (data.repository === undefined) {
	// 		setIsExpanded(true);
	// 	}
	// }, [data.repository, setIsExpanded]);
	console.log(data.repository, isExpanded, repo);
	return (
		<Accordion type="single" collapsible>
			<AccordionItem value="repository" className="border-none">
				<AccordionTrigger onClick={() => setIsExpanded(!isExpanded)}>
					Source {!isExpanded && repo !== undefined && repo.data.repository?.fullName}
				</AccordionTrigger>
				<AccordionContent className="px-1">
					<Form {...sourceForm}>
						<form className="space-y-2">
							<Label>Repository</Label>
							<FormField
								control={sourceForm.control}
								name="id"
								render={({ field }) => (
									<FormItem>
										<Select onValueChange={field.onChange} value={field.value} disabled={disabled}>
											<FormControl>
												<SelectTrigger>
													<SelectValue />
												</SelectTrigger>
											</FormControl>
											<SelectContent>
												{repos.map((r) => (
													<SelectItem
														key={r.id}
														value={r.id.toString()}
													>{`${r.full_name}`}</SelectItem>
												))}
											</SelectContent>
										</Select>
										<FormMessage />
									</FormItem>
								)}
							/>
							<Label>Branch</Label>
							<FormField
								control={sourceForm.control}
								name="branch"
								render={({ field }) => (
									<FormItem>
										<FormControl>
											<Input
												placeholder="master"
												className="lowercase"
												{...field}
												disabled={disabled}
											/>
										</FormControl>
										<FormMessage />
									</FormItem>
								)}
							/>
							<Label>Root Directory</Label>
							<FormField
								control={sourceForm.control}
								name="rootDir"
								render={({ field }) => (
									<FormItem>
										<FormControl>
											<Input placeholder="/" {...field} disabled={disabled} />
										</FormControl>
										<FormMessage />
									</FormItem>
								)}
							/>
						</form>
					</Form>
				</AccordionContent>
			</AccordionItem>
		</Accordion>
	);
}
