import { Category, defaultCategories } from "./categories";
import { CreateValidators, Validator } from "./config";
import { GitHubService, GitHubServiceImpl, GitHubRepository } from "./github";
import type { Edge, OnConnect, OnEdgesChange, OnNodesChange, Viewport as ReactFlowViewport } from "@xyflow/react";
import {
	addEdge,
	applyEdgeChanges,
	applyNodeChanges,
	Connection,
	EdgeChange,
	useNodes,
	XYPosition,
} from "@xyflow/react";
import type { DeepPartial } from "react-hook-form";
import { v4 as uuidv4 } from "uuid";
import { create } from "zustand";
import { AppNode, Env, NodeType, VolumeNode, GatewayTCPData, envSchema, AgentAccess } from "config";

export function nodeLabel(n: AppNode): string {
	try {
		switch (n.type) {
			case "network":
				return n.data.domain;
			case "app":
				return n.data.label || "Service";
			case "github":
				return n.data.repository?.fullName || "Github";
			case "gateway-https": {
				if (n.data && n.data.subdomain) {
					return `${n.data.subdomain}`;
				} else {
					return "HTTPS Gateway";
				}
			}
			case "gateway-tcp": {
				if (n.data && n.data.subdomain) {
					return `${n.data.subdomain}`;
				} else {
					return "TCP Gateway";
				}
			}
			case "mongodb":
				return n.data.label || "MongoDB";
			case "postgresql":
				return n.data.label || "PostgreSQL";
			case "volume":
				return n.data.label || "Volume";
			case undefined:
				throw new Error(`nodeLabel: Node type is undefined. Node ID: ${n.id}, Data: ${JSON.stringify(n.data)}`);
		}
	} catch (e) {
		console.error("opaa", e);
	} finally {
		console.log("done");
	}
	return "Unknown Node";
}

export function nodeLabelFull(n: AppNode): string {
	if (n.type === "gateway-https") {
		return `https://${n.data.subdomain}.${n.data.network}`;
	} else {
		return nodeLabel(n);
	}
}

export function nodeIsConnectable(n: AppNode, handle: string): boolean {
	switch (n.type) {
		case "network":
			return true;
		case "app":
			if (handle === "ports") {
				return n.data !== undefined && n.data.ports !== undefined && n.data.ports.length > 0;
			} else if (handle === "repository") {
				if (!n.data || !n.data.repository || !n.data.repository.id) {
					return true;
				}
				return false;
			}
			return false;
		case "github":
			if (n.data.repository?.id !== undefined) {
				return true;
			}
			return false;
		case "gateway-https":
			if (handle === "subdomain") {
				return n.data.network === undefined;
			}
			return n.data === undefined || n.data.https === undefined;
		case "gateway-tcp":
			if (handle === "subdomain") {
				return n.data.network === undefined;
			}
			return true;
		case "mongodb":
			return true;
		case "postgresql":
			return true;
		case "volume":
			if (n.data === undefined || n.data.type === undefined) {
				return false;
			}
			if (n.data.type === "ReadWriteOnce" || n.data.type === "ReadWriteOncePod") {
				return n.data.attachedTo === undefined || n.data.attachedTo.length === 0;
			}
			return true;
		case undefined:
			throw new Error(
				`nodeIsConnectable: Node type is undefined. Node ID: ${n.id}, Handle: ${handle}, Data: ${JSON.stringify(n.data)}`,
			);
	}
}

export function nodeEnvVarNamePort(n: AppNode, portName: string): string {
	return `DODO_SERVICE_${n.data.label.toUpperCase()}_ADDRESS_${portName.toUpperCase()}`;
}

export function nodeEnvVarNames(n: AppNode): string[] {
	switch (n.type) {
		case "app":
			return [
				`DODO_SERVICE_${n.data.label.toUpperCase()}_ADDRESS`,
				...(n.data.ports || []).map((p) => nodeEnvVarNamePort(n, p.name)),
			];
		case "github":
			return [];
		case "gateway-https":
			return [];
		case "gateway-tcp":
			return [];
		case "mongodb":
			return [`DODO_MONGODB_${n.data.label.toUpperCase()}_URL`];
		case "postgresql":
			return [`DODO_POSTGRESQL_${n.data.label.toUpperCase()}_URL`];
		case "volume":
			return [`DODO_VOLUME_${n.data.label.toUpperCase()}_PATH`];
		case undefined:
			throw new Error("MUST NOT REACH");
		default:
			throw new Error("MUST NOT REACH");
	}
}

export type MessageType = "INFO" | "WARNING" | "FATAL";

export type Message = {
	id: string;
	type: MessageType;
	nodeId?: string;
	message: string;
	onHighlight?: (state: AppState) => void;
	onLooseHighlight?: (state: AppState) => void;
	onClick?: (state: AppState) => void;
};

const defaultEnv: Env = {
	deployKeyPublic: undefined,
	instanceId: undefined,
	networks: [],
	integrations: {
		github: false,
		gemini: false,
		anthropic: false,
	},
	services: [],
	user: {
		id: "",
		username: "",
	},
	access: [],
};

export type Project = {
	id: string;
	name: string;
};

export type IntegrationsConfig = {
	github: boolean;
};

type NodeUpdate<T extends NodeType> = DeepPartial<Extract<AppNode, { type: T }>>;
type NodeDataUpdate<T extends NodeType> = DeepPartial<Extract<AppNode, { type: T }>["data"]>;

type Viewport = {
	transformX: number;
	transformY: number;
	transformZoom: number;
	width: number;
	height: number;
};

let refreshEnvIntervalId: number | null = null;

export type AppState = {
	projectId: string | undefined;
	mode: "edit" | "deploy";
	projects: Project[];
	nodes: AppNode[];
	edges: Edge[];
	zoom: ReactFlowViewport;
	categories: Category[];
	messages: Message[];
	env: Env;
	viewport: Viewport;
	setViewport: (viewport: Viewport) => void;
	githubService: GitHubService | null;
	githubRepositories: GitHubRepository[];
	githubRepositoriesLoading: boolean;
	githubRepositoriesError: string | null;
	stateEventSource: EventSource | null;
	setHighlightCategory: (name: string, active: boolean) => void;
	onNodesChange: OnNodesChange<AppNode>;
	onEdgesChange: OnEdgesChange;
	onConnect: OnConnect;
	addNode: (node: Omit<AppNode, "position">) => void;
	setNodes: (nodes: AppNode[]) => void;
	setEdges: (edges: Edge[]) => void;
	setProject: (projectId: string | undefined) => Promise<void>;
	setMode: (mode: "edit" | "deploy") => void;
	updateNode: <T extends NodeType>(id: string, node: NodeUpdate<T>) => void;
	updateNodeData: <T extends NodeType>(id: string, data: NodeDataUpdate<T>) => void;
	replaceEdge: (c: Connection, id?: string) => void;
	refreshEnv: () => Promise<void>;
	fetchGithubRepositories: () => Promise<void>;
};

const projectIdSelector = (state: AppState) => state.projectId;
const categoriesSelector = (state: AppState) => state.categories;
const messagesSelector = (state: AppState) => state.messages;
const envSelector = (state: AppState) => state.env;
const zoomSelector = (state: AppState) => state.zoom;
const githubRepositoriesSelector = (state: AppState) => state.githubRepositories;
const githubRepositoriesLoadingSelector = (state: AppState) => state.githubRepositoriesLoading;
const githubRepositoriesErrorSelector = (state: AppState) => state.githubRepositoriesError;

export function useZoom(): ReactFlowViewport {
	return useStateStore(zoomSelector);
}

export function useProjectId(): string | undefined {
	return useStateStore(projectIdSelector);
}

export function useSetProject(): (projectId: string | undefined) => void {
	return useStateStore((state) => state.setProject);
}

export function useCategories(): Category[] {
	return useStateStore(categoriesSelector);
}

export function useMessages(): Message[] {
	return useStateStore(messagesSelector);
}

export function useNodeMessages(id: string): Message[] {
	return useMessages().filter((m) => m.nodeId === id);
}

export function useNodeLabel(id: string): string {
	return nodeLabel(useNodes<AppNode>().find((n) => n.id === id)!);
}

export function useNodePortName(id: string, portId: string): string {
	return (useNodes<AppNode>().find((n) => n.id === id)!.data.ports || []).find((p) => p.id === portId)!.name;
}

export function useEnv(): Env {
	return useStateStore(envSelector);
}

export function useAgents(): AgentAccess[] {
	return useStateStore(envSelector).access.filter(
		(acc): acc is AgentAccess => acc.type === "https" && acc.agentName != null,
	);
}

export function useLeadAgent(): AgentAccess | undefined {
	const agents = useAgents();
	return agents.find((a) => a.agentName === "dodo") || agents[0];
}

export function useGithubService(): boolean {
	return useStateStore(envSelector).integrations.github;
}

export function useGeminiService(): boolean {
	return useStateStore(envSelector).integrations.gemini;
}

export function useAnthropicService(): boolean {
	return useStateStore(envSelector).integrations.anthropic;
}

export function useGithubRepositories(): GitHubRepository[] {
	return useStateStore(githubRepositoriesSelector);
}

export function useGithubRepositoriesLoading(): boolean {
	return useStateStore(githubRepositoriesLoadingSelector);
}

export function useGithubRepositoriesError(): string | null {
	return useStateStore(githubRepositoriesErrorSelector);
}

export function useFetchGithubRepositories(): () => Promise<void> {
	return useStateStore((state) => state.fetchGithubRepositories);
}

export function useMode(): "edit" | "deploy" {
	return useStateStore((state) => state.mode);
}

const v: Validator = CreateValidators();

function getRandomPosition({ width, height, transformX, transformY, transformZoom }: Viewport): XYPosition {
	const zoomMultiplier = 1 / transformZoom;
	const realWidth = width * zoomMultiplier;
	const realHeight = height * zoomMultiplier;
	const paddingMultiplier = 0.8;
	const ret = {
		x: -transformX * zoomMultiplier + Math.random() * realWidth * paddingMultiplier,
		y: -transformY * zoomMultiplier + Math.random() * realHeight * paddingMultiplier,
	};
	return ret;
}

export const useStateStore = create<AppState>((setOg, get): AppState => {
	const set = (state: Partial<AppState>) => {
		setOg(state);
	};
	const setN = (nodes: AppNode[]) => {
		const env = get().env;
		console.log("---env", env);
		set({
			nodes,
			messages: v(nodes, env),
		});
	};

	const startRefreshEnvInterval = () => {
		if (refreshEnvIntervalId) {
			clearInterval(refreshEnvIntervalId);
		}
		if (get().projectId && typeof document !== "undefined" && document.visibilityState === "visible") {
			console.log("Starting refreshEnv interval for project:", get().projectId);
			refreshEnvIntervalId = setInterval(async () => {
				if (get().projectId && typeof document !== "undefined" && document.visibilityState === "visible") {
					console.log("Interval: Calling refreshEnv for project:", get().projectId);
					await get().refreshEnv();
				} else if (refreshEnvIntervalId) {
					console.log(
						"Interval: Conditions not met (project removed or tab hidden), stopping interval from inside.",
					);
					clearInterval(refreshEnvIntervalId);
					refreshEnvIntervalId = null;
				}
			}, 5000) as unknown as number;
		} else {
			console.log(
				"Not starting refreshEnv interval. Project ID:",
				get().projectId,
				"Visibility:",
				typeof document !== "undefined" ? document.visibilityState : "SSR",
			);
		}
	};

	const stopRefreshEnvInterval = () => {
		if (refreshEnvIntervalId) {
			console.log("Stopping refreshEnv interval for project:", get().projectId);
			clearInterval(refreshEnvIntervalId);
			refreshEnvIntervalId = null;
		}
	};

	if (typeof document !== "undefined") {
		document.addEventListener("visibilitychange", () => {
			if (document.visibilityState === "visible") {
				console.log("Tab became visible, attempting to start refreshEnv interval.");
				startRefreshEnvInterval();
			} else {
				console.log("Tab became hidden, stopping refreshEnv interval.");
				stopRefreshEnvInterval();
			}
		});
	}

	const injectNetworkNodes = () => {
		const newNetworks = get().env.networks.filter(
			(x) => !get().nodes.some((n) => n.type === "network" && n.data.domain === x.domain),
		);
		newNetworks.forEach((n) => {
			get().addNode({
				id: n.domain,
				type: "network",
				connectable: true,
				data: {
					domain: n.domain,
					label: n.domain,
					envVars: [],
					ports: [],
					state: "success", // TODO(gio): monitor network health
				},
			});
			console.log("added network", n.domain);
		});
	};

	function updateNodeData<T extends NodeType>(id: string, data: NodeDataUpdate<T>): void {
		setN(
			get().nodes.map((n) => {
				if (n.id === id) {
					return {
						...n,
						data: {
							...n.data,
							...data,
						},
					} as Extract<AppNode, { type: T }>;
				}
				return n;
			}),
		);
	}

	function updateNode<T extends NodeType>(id: string, node: NodeUpdate<T>): void {
		setN(
			get().nodes.map((n) => {
				if (n.id === id) {
					return {
						...n,
						...node,
					} as Extract<AppNode, { type: T }>;
				}
				return n;
			}),
		);
	}

	function onConnect(c: Connection) {
		const { nodes, edges } = get();
		set({
			edges: addEdge(c, edges),
		});
		const sn = nodes.filter((n) => n.id === c.source)[0]!;
		const tn = nodes.filter((n) => n.id === c.target)[0]!;
		if (tn.type === "network") {
			if (sn.type === "gateway-https") {
				updateNodeData<"gateway-https">(sn.id, {
					network: tn.data.domain,
				});
			} else if (sn.type === "gateway-tcp") {
				updateNodeData<"gateway-tcp">(sn.id, {
					network: tn.data.domain,
				});
			}
		}
		if (tn.type === "app") {
			if (c.sourceHandle === "env_var" && c.targetHandle === "env_var") {
				const sourceEnvVars = nodeEnvVarNames(sn);
				if (sourceEnvVars.length === 0) {
					throw new Error(
						`onConnect (env_var): Source node ${sn.id} (type: ${sn.type}) has no env vars to connect from.`,
					);
				}
				const id = uuidv4();
				if (sourceEnvVars.length === 1) {
					updateNode<"app">(c.target, {
						...tn,
						data: {
							...tn.data,
							envVars: [
								...(tn.data.envVars || []),
								{
									id: id,
									source: c.source,
									name: sourceEnvVars[0],
									isEditting: false,
								},
							],
						},
					});
				} else {
					updateNode<"app">(c.target, {
						...tn,
						data: {
							...tn.data,
							envVars: [
								...(tn.data.envVars || []),
								{
									id: id,
									source: c.source,
								},
							],
						},
					});
				}
			}
			if (c.sourceHandle === "ports" && c.targetHandle === "env_var") {
				const sourcePorts = sn.data.ports || [];
				const id = uuidv4();
				if (sourcePorts.length === 1) {
					updateNode<"app">(c.target, {
						...tn,
						data: {
							...tn.data,
							envVars: [
								...(tn.data.envVars || []),
								{
									id: id,
									source: c.source,
									name: nodeEnvVarNamePort(sn, sourcePorts[0].name),
									portId: sourcePorts[0].id,
									isEditting: false,
								},
							],
						},
					});
				}
			}
			if (c.targetHandle === "repository") {
				const sourceNode = nodes.find((n) => n.id === c.source);
				if (sourceNode && sourceNode.type === "github" && sourceNode.data.repository) {
					updateNodeData<"app">(tn.id, {
						repository: {
							id: sourceNode.data.repository.id,
							repoNodeId: c.source,
						},
					});
				}
			}
		}
		if (c.sourceHandle === "volume") {
			updateNodeData<"volume">(c.source, {
				attachedTo: ((sn as VolumeNode).data.attachedTo || []).concat(c.source),
			});
		}
		if (c.targetHandle === "https") {
			if ((sn.data.ports || []).length === 1) {
				updateNodeData<"gateway-https">(c.target, {
					https: {
						serviceId: c.source,
						portId: sn.data.ports![0].id,
					},
				});
			} else {
				updateNodeData<"gateway-https">(c.target, {
					https: {
						serviceId: c.source,
						portId: "", // TODO(gio)
					},
				});
			}
		}
		if (c.targetHandle === "tcp") {
			const td = tn.data as GatewayTCPData;
			if ((sn.data.ports || []).length === 1) {
				updateNodeData<"gateway-tcp">(c.target, {
					exposed: (td.exposed || []).concat({
						serviceId: c.source,
						portId: sn.data.ports![0].id,
					}),
				});
			} else {
				updateNodeData<"gateway-tcp">(c.target, {
					selected: {
						serviceId: c.source,
						portId: undefined,
					},
				});
			}
		}
		if (sn.type === "app") {
			if (c.sourceHandle === "ports") {
				updateNodeData<"app">(sn.id, {
					isChoosingPortToConnect: true,
				});
			}
		}
	}

	const fetchGithubRepositories = async () => {
		const { githubService, projectId } = get();
		if (!githubService || !projectId) {
			set({
				githubRepositories: [],
				githubRepositoriesError: "GitHub service or Project ID not available.",
				githubRepositoriesLoading: false,
			});
			return;
		}

		set({ githubRepositoriesLoading: true, githubRepositoriesError: null });
		try {
			const repos = await githubService.getRepositories();
			set({ githubRepositories: repos, githubRepositoriesLoading: false });
		} catch (error) {
			console.error("Failed to fetch GitHub repositories in store:", error);
			const errorMessage = error instanceof Error ? error.message : "Unknown error fetching repositories";
			set({ githubRepositories: [], githubRepositoriesError: errorMessage, githubRepositoriesLoading: false });
		}
	};

	const disconnectFromStateStream = () => {
		const { stateEventSource } = get();
		if (stateEventSource) {
			stateEventSource.close();
			set({ stateEventSource: null });
		}
	};

	const connectToStateStream = (projectId: string, mode: "deploy" | "edit") => {
		disconnectFromStateStream();

		const eventSource = new EventSource(
			`/api/project/${projectId}/state/stream/${mode === "edit" ? "draft" : "deploy"}`,
		);
		set({ stateEventSource: eventSource });

		eventSource.onmessage = (event) => {
			const inst = JSON.parse(event.data);
			setN(inst.nodes);
			set({ edges: inst.edges });
			injectNetworkNodes();
			if (
				get().zoom.x !== inst.viewport.x ||
				get().zoom.y !== inst.viewport.y ||
				get().zoom.zoom !== inst.viewport.zoom
			) {
				set({ zoom: inst.viewport });
			}
		};

		eventSource.onerror = (err) => {
			console.error("EventSource failed:", err);
			eventSource.close();
			set({ stateEventSource: null });
		};
	};

	return {
		projectId: undefined,
		mode: "edit",
		projects: [],
		nodes: [],
		edges: [],
		categories: defaultCategories,
		messages: [],
		env: defaultEnv,
		viewport: {
			transformX: 0,
			transformY: 0,
			transformZoom: 1,
			width: 800,
			height: 600,
		},
		zoom: {
			x: 0,
			y: 0,
			zoom: 1,
		},
		githubService: null,
		githubRepositories: [],
		githubRepositoriesLoading: false,
		githubRepositoriesError: null,
		stateEventSource: null,
		setViewport: (viewport) => {
			const { viewport: vp } = get();
			if (
				viewport.transformX !== vp.transformX ||
				viewport.transformY !== vp.transformY ||
				viewport.transformZoom !== vp.transformZoom ||
				viewport.width !== vp.width ||
				viewport.height !== vp.height
			) {
				set({ viewport });
			}
		},
		setHighlightCategory: (name, active) => {
			set({
				categories: get().categories.map((c) => {
					if (c.title.toLowerCase() !== name.toLowerCase()) {
						return c;
					} else {
						return {
							...c,
							active,
						};
					}
				}),
			});
		},
		onNodesChange: (changes) => {
			const nodes = applyNodeChanges(changes, get().nodes);
			setN(nodes);
		},
		onEdgesChange: (changes) => {
			set({
				edges: applyEdgeChanges(changes, get().edges),
			});
		},
		addNode: (node) => {
			const { viewport, nodes } = get();
			setN(
				nodes.concat({
					...node,
					position: getRandomPosition(viewport),
				} as AppNode),
			);
		},
		setNodes: (nodes) => {
			setN(nodes);
		},
		setEdges: (edges) => {
			set({ edges });
		},
		replaceEdge: (c, id) => {
			let change: EdgeChange;
			if (id === undefined) {
				change = {
					type: "add",
					item: {
						id: uuidv4(),
						...c,
					},
				};
				onConnect(c);
			} else {
				change = {
					type: "replace",
					id,
					item: {
						id,
						...c,
					},
				};
			}
			set({
				edges: applyEdgeChanges([change], get().edges),
			});
		},
		updateNode,
		updateNodeData,
		onConnect,
		refreshEnv: async () => {
			const projectId = get().projectId;
			let env: Env = defaultEnv;
			try {
				if (projectId) {
					const response = await fetch(`/api/project/${projectId}/env`);
					if (response.ok) {
						const data = await response.json();
						const result = envSchema.safeParse(data);
						if (result.success) {
							env = result.data;
						} else {
							console.error("Invalid env data:", result.error);
						}
					}
				}
			} catch (error) {
				console.error("Failed to fetch integrations:", error);
			} finally {
				const oldEnv = get().env;
				const oldGithubIntegrationStatus = oldEnv.integrations.github;
				if (JSON.stringify(oldEnv) !== JSON.stringify(env)) {
					set({ env });
					injectNetworkNodes();
					let ghService = null;
					if (env.integrations.github) {
						ghService = new GitHubServiceImpl(projectId!);
					}
					if (get().githubService !== ghService || (ghService && !get().githubService)) {
						set({ githubService: ghService });
					}
					if (
						ghService &&
						(oldGithubIntegrationStatus !== env.integrations.github || !oldEnv.integrations.github)
					) {
						get().fetchGithubRepositories();
					}
					if (!env.integrations.github) {
						set({
							githubRepositories: [],
							githubRepositoriesError: null,
							githubRepositoriesLoading: false,
						});
					}
				}
			}
		},
		setMode: (mode) => {
			disconnectFromStateStream();
			set({ mode });
			const projectId = get().projectId;
			if (projectId) {
				connectToStateStream(projectId, mode);
			}
		},
		setProject: async (projectId) => {
			const currentProjectId = get().projectId;
			if (projectId === currentProjectId) {
				return;
			}
			stopRefreshEnvInterval();
			disconnectFromStateStream();
			set({
				projectId,
				githubRepositories: [],
				githubRepositoriesLoading: false,
				githubRepositoriesError: null,
			});
			if (projectId) {
				await get().refreshEnv();
				if (get().env.instanceId) {
					set({ mode: "deploy" });
				} else {
					set({ mode: "edit" });
				}
				const mode = get().mode;
				connectToStateStream(projectId, mode);
				startRefreshEnvInterval();
			} else {
				set({
					nodes: [],
					edges: [],
					env: defaultEnv,
					githubService: null,
					githubRepositories: [],
					githubRepositoriesLoading: false,
					githubRepositoriesError: null,
				});
			}
		},
		fetchGithubRepositories: fetchGithubRepositories,
	};
});
