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 } 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("MUST NOT REACH!");
		}
	} 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("MUST NOT REACH!");
	}
}

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 = {
	managerAddr: undefined,
	deployKeyPublic: undefined,
	instanceId: undefined,
	networks: [],
	integrations: {
		github: 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;
	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 githubServiceSelector = (state: AppState) => state.githubService;
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 useGithubService(): GitHubService | null {
	return useStateStore(githubServiceSelector);
}

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[]) => {
		set({
			nodes,
			messages: v(nodes),
		});
	};

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

	const restoreSaved = async () => {
		const { projectId } = get();
		const resp = await fetch(`/api/project/${projectId}/saved/${get().mode === "deploy" ? "deploy" : "draft"}`, {
			method: "GET",
		});
		const inst = await resp.json();
		setN(inst.state.nodes);
		set({ edges: inst.state.edges });
		injectNetworkNodes();
		if (
			get().zoom.x !== inst.state.viewport.x ||
			get().zoom.y !== inst.state.viewport.y ||
			get().zoom.zoom !== inst.state.viewport.zoom
		) {
			set({ zoom: inst.state.viewport });
		}
	};

	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("MUST NOT REACH!");
				}
				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 === "volume") {
			if (tn.type === "postgresql" || tn.type === "mongodb") {
				updateNodeData(c.target, {
					volumeId: 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 });
		}
	};

	return {
		projectId: undefined,
		mode: "edit",
		projects: [],
		nodes: [],
		edges: [],
		categories: defaultCategories,
		messages: v([]),
		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,
		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) => {
			set({ mode });
		},
		setProject: async (projectId) => {
			const currentProjectId = get().projectId;
			if (projectId === currentProjectId) {
				return;
			}
			stopRefreshEnvInterval();
			set({
				projectId,
				githubRepositories: [],
				githubRepositoriesLoading: false,
				githubRepositoriesError: null,
			});
			if (projectId) {
				await get().refreshEnv();
				if (get().env.instanceId) {
					set({ mode: "deploy" });
				} else {
					set({ mode: "edit" });
				}
				restoreSaved();
				startRefreshEnvInterval();
			} else {
				set({
					nodes: [],
					edges: [],
					env: defaultEnv,
					githubService: null,
					githubRepositories: [],
					githubRepositoriesLoading: false,
					githubRepositoriesError: null,
				});
			}
		},
		fetchGithubRepositories: fetchGithubRepositories,
	};
});
