import { AppNode, Env, Message, MessageType, NodeType, ServiceType, VolumeType } from "./state";

export type AuthDisabled = {
	enabled: false;
};

export type AuthEnabled = {
	enabled: true;
	groups: string[];
	noAuthPathPatterns: string[];
};

export type Auth = AuthDisabled | AuthEnabled;

export type Ingress = {
	network: string;
	subdomain: string;
	port: { name: string } | { value: string };
	auth: Auth;
};

export type Domain = {
	network: string;
	subdomain: string;
};

export type PortValue =
	| {
			name: string;
	  }
	| {
			value: number;
	  };

export type PortDomain = Domain & {
	port: PortValue;
};

export type Service = {
	type: ServiceType;
	name: string;
	source: {
		repository: string;
		branch: string;
		rootDir: string;
	};
	ports?: {
		name: string;
		value: number;
		protocol: "TCP" | "UDP";
	}[];
	env?: {
		name: string;
		alias?: string;
	}[];
	ingress?: Ingress[];
	expose?: PortDomain[];
	volume?: string[];
	preBuildCommands?: { bin: string }[];
	dev?: {
		enabled: boolean;
		username?: string;
		ssh?: Domain;
		codeServer?: Domain;
	};
};

export type Volume = {
	name: string;
	accessMode: VolumeType;
	size: string;
};

export type PostgreSQL = {
	name: string;
	size: string;
	expose?: Domain[];
};

export type MongoDB = {
	name: string;
	size: string;
	expose?: Domain[];
};

export type Config = {
	input: {
		appId: string;
		managerAddr: string;
	};
	service?: Service[];
	volume?: Volume[];
	postgresql?: PostgreSQL[];
	mongodb?: MongoDB[];
};

export function generateDodoConfig(appId: string | undefined, nodes: AppNode[], env: Env): Config | null {
	try {
		if (appId == null || env.managerAddr == null) {
			return null;
		}
		const networkMap = new Map(env.networks.map((n) => [n.domain, n.name]));
		const ingressNodes = nodes
			.filter((n) => n.type === "gateway-https")
			.filter((n) => n.data.https !== undefined && !n.data.readonly);
		const tcpNodes = nodes
			.filter((n) => n.type === "gateway-tcp")
			.filter((n) => n.data.exposed !== undefined && !n.data.readonly);
		const findExpose = (n: AppNode): PortDomain[] => {
			return n.data.ports
				.map((p) => [n.id, p.id, p.name])
				.flatMap((sp) => {
					return tcpNodes.flatMap((i) =>
						(i.data.exposed || [])
							.filter((t) => t.serviceId === sp[0] && t.portId === sp[1])
							.map(() => ({
								network: networkMap.get(i.data.network!)!,
								subdomain: i.data.subdomain!,
								port: { name: sp[2] },
							})),
					);
				});
		};
		return {
			input: {
				appId: appId,
				managerAddr: env.managerAddr,
			},
			service: nodes
				.filter((n) => n.type === "app")
				.map((n): Service => {
					return {
						type: n.data.type,
						name: n.data.label,
						source: {
							repository: nodes
								.filter((i) => i.type === "github")
								.find((i) => i.id === n.data.repository.id)!.data.repository!.sshURL,
							branch: n.data.repository.branch,
							rootDir: n.data.repository.rootDir,
						},
						ports: (n.data.ports || [])
							.filter((p) => !n.data.dev?.enabled || (p.value != 22 && p.value != 9090))
							.map((p) => ({
								name: p.name,
								value: p.value,
								protocol: "TCP", // TODO(gio)
							})),
						env: (n.data.envVars || [])
							.filter((e) => "name" in e)
							.map((e) => ({
								name: e.name,
								alias: "alias" in e ? e.alias : undefined,
							})),
						ingress: ingressNodes
							.filter((i) => i.data.https!.serviceId === n.id)
							.map(
								(i): Ingress => ({
									network: networkMap.get(i.data.network!)!,
									subdomain: i.data.subdomain!,
									port: {
										name: n.data.ports.find((p) => p.id === i.data.https!.portId)!.name,
									},
									auth:
										i.data.auth?.enabled || false
											? {
													enabled: true,
													groups: i.data.auth!.groups,
													noAuthPathPatterns: i.data.auth!.noAuthPathPatterns,
												}
											: {
													enabled: false,
												},
								}),
							),
						expose: findExpose(n),
						preBuildCommands: n.data.preBuildCommands
							? n.data.preBuildCommands.split("\n").map((cmd) => ({ bin: cmd }))
							: [],
						dev: {
							enabled: n.data.dev ? n.data.dev.enabled : false,
							username: n.data.dev && n.data.dev.enabled ? env.user.username : undefined,
							codeServer:
								n.data.dev?.enabled && n.data.dev.expose != null
									? {
											network: networkMap.get(n.data.dev.expose.network)!,
											subdomain: n.data.dev.expose.subdomain,
										}
									: undefined,
							ssh:
								n.data.dev?.enabled && n.data.dev.expose != null
									? {
											network: networkMap.get(n.data.dev.expose.network)!,
											subdomain: n.data.dev.expose.subdomain,
										}
									: undefined,
						},
					};
				}),
			volume: nodes
				.filter((n) => n.type === "volume")
				.map(
					(n): Volume => ({
						name: n.data.label,
						accessMode: n.data.type,
						size: n.data.size,
					}),
				),
			postgresql: nodes
				.filter((n) => n.type === "postgresql")
				.map(
					(n): PostgreSQL => ({
						name: n.data.label,
						size: "1Gi", // TODO(gio)
						expose: findExpose(n).map((e) => ({ network: e.network, subdomain: e.subdomain })),
					}),
				),
			mongodb: nodes
				.filter((n) => n.type === "mongodb")
				.map(
					(n): MongoDB => ({
						name: n.data.label,
						size: "1Gi", // TODO(gio)
						expose: findExpose(n).map((e) => ({ network: e.network, subdomain: e.subdomain })),
					}),
				),
		};
	} catch (e) {
		console.log(e);
		return null;
	}
}

export interface Validator {
	(nodes: AppNode[]): Message[];
}

function CombineValidators(...v: Validator[]): Validator {
	return (n) => v.flatMap((v) => v(n));
}

function MessageTypeToNumber(t: MessageType) {
	switch (t) {
		case "FATAL":
			return 0;
		case "WARNING":
			return 1;
		case "INFO":
			return 2;
	}
}

function NodeTypeToNumber(t?: NodeType) {
	switch (t) {
		case "github":
			return 0;
		case "app":
			return 1;
		case "volume":
			return 2;
		case "postgresql":
			return 3;
		case "mongodb":
			return 4;
		case "gateway-https":
			return 5;
		case undefined:
			return 100;
	}
}

function SortingValidator(v: Validator): Validator {
	return (n) => {
		const nt = new Map(n.map((n) => [n.id, NodeTypeToNumber(n.type)]));
		return v(n).sort((a, b) => {
			const at = MessageTypeToNumber(a.type);
			const bt = MessageTypeToNumber(b.type);
			if (a.nodeId === undefined && b.nodeId === undefined) {
				if (at !== bt) {
					return at - bt;
				}
				return a.id.localeCompare(b.id);
			}
			if (a.nodeId === undefined) {
				return -1;
			}
			if (b.nodeId === undefined) {
				return 1;
			}
			if (a.nodeId === b.nodeId) {
				if (at !== bt) {
					return at - bt;
				}
				return a.id.localeCompare(b.id);
			}
			const ant = nt.get(a.id)!;
			const bnt = nt.get(b.id)!;
			if (ant !== bnt) {
				return ant - bnt;
			}
			return a.id.localeCompare(b.id);
		});
	};
}

export function CreateValidators(): Validator {
	return SortingValidator(
		CombineValidators(
			EmptyValidator,
			GitRepositoryValidator,
			ServiceValidator,
			GatewayHTTPSValidator,
			GatewayTCPValidator,
		),
	);
}

function EmptyValidator(nodes: AppNode[]): Message[] {
	if (nodes.some((n) => n.type !== "network")) {
		return [];
	}
	return [
		{
			id: "no-nodes",
			type: "FATAL",
			message: "Start by importing application source code",
			onHighlight: (store) => store.setHighlightCategory("repository", true),
			onLooseHighlight: (store) => store.setHighlightCategory("repository", false),
		},
	];
}

function GitRepositoryValidator(nodes: AppNode[]): Message[] {
	const git = nodes.filter((n) => n.type === "github");
	const noAddress: Message[] = git
		.filter((n) => n.data == null || n.data.repository == null)
		.map(
			(n) =>
				({
					id: `${n.id}-no-address`,
					type: "FATAL",
					nodeId: n.id,
					message: "Configure repository address",
					onHighlight: (store) => store.updateNode(n.id, { selected: true }),
					onLooseHighlight: (store) => store.updateNode(n.id, { selected: false }),
				}) satisfies Message,
		);
	const noApp = git
		.filter((n) => !nodes.some((i) => i.type === "app" && i.data?.repository?.id === n.id))
		.map(
			(n) =>
				({
					id: `${n.id}-no-app`,
					type: "WARNING",
					nodeId: n.id,
					message: "Connect to service",
					onHighlight: (store) => store.setHighlightCategory("Services", true),
					onLooseHighlight: (store) => store.setHighlightCategory("Services", false),
				}) satisfies Message,
		);
	return noAddress.concat(noApp);
}

function ServiceValidator(nodes: AppNode[]): Message[] {
	const apps = nodes.filter((n) => n.type === "app");
	const noName = apps
		.filter((n) => n.data == null || n.data.label == null || n.data.label === "")
		.map(
			(n): Message => ({
				id: `${n.id}-no-name`,
				type: "FATAL",
				nodeId: n.id,
				message: "Name the service",
				onHighlight: (store) => store.updateNode(n.id, { selected: true }),
				onLooseHighlight: (store) => store.updateNode(n.id, { selected: false }),
				onClick: (store) => {
					store.updateNode(n.id, { selected: true });
					store.updateNodeData<"app">(n.id, {
						activeField: "name",
					});
				},
			}),
		);
	const noSource = apps
		.filter((n) => n.data == null || n.data.repository == null || n.data.repository.id === "")
		.map(
			(n): Message => ({
				id: `${n.id}-no-repo`,
				type: "FATAL",
				nodeId: n.id,
				message: "Connect to source repository",
				onHighlight: (store) => store.updateNode(n.id, { selected: true }),
				onLooseHighlight: (store) => store.updateNode(n.id, { selected: false }),
			}),
		);
	const noRuntime = apps
		.filter((n) => n.data == null || n.data.type == null)
		.map(
			(n): Message => ({
				id: `${n.id}-no-runtime`,
				type: "FATAL",
				nodeId: n.id,
				message: "Choose runtime",
				onHighlight: (store) => store.updateNode(n.id, { selected: true }),
				onLooseHighlight: (store) => store.updateNode(n.id, { selected: false }),
				onClick: (store) => {
					store.updateNode(n.id, { selected: true });
					store.updateNodeData<"app">(n.id, {
						activeField: "type",
					});
				},
			}),
		);
	const noPorts = apps
		.filter((n) => n.data == null || n.data.ports == null || n.data.ports.length === 0)
		.map(
			(n): Message => ({
				id: `${n.id}-no-ports`,
				type: "INFO",
				nodeId: n.id,
				message: "Expose ports",
				onHighlight: (store) => store.updateNode(n.id, { selected: true }),
				onLooseHighlight: (store) => store.updateNode(n.id, { selected: false }),
			}),
		);
	const noIngress = apps.flatMap((n): Message[] => {
		if (n.data == null) {
			return [];
		}
		return (n.data.ports || [])
			.filter(
				(p) =>
					!nodes
						.filter((i) => i.type === "gateway-https")
						.some((i) => {
							if (
								i.data &&
								i.data.https &&
								i.data.https.serviceId === n.id &&
								i.data.https.portId === p.id
							) {
								return true;
							}
							return false;
						}),
			)
			.map(
				(p): Message => ({
					id: `${n.id}-${p.id}-no-ingress`,
					type: "WARNING",
					nodeId: n.id,
					message: `Connect to gateway: ${p.name} - ${p.value}`,
					onHighlight: (store) => {
						store.updateNode(n.id, { selected: true });
						store.setHighlightCategory("gateways", true);
					},
					onLooseHighlight: (store) => {
						store.updateNode(n.id, { selected: false });
						store.setHighlightCategory("gateways", false);
					},
				}),
			);
	});
	const multipleIngress = apps
		.filter((n) => n.data != null && n.data.ports != null)
		.flatMap((n) =>
			n.data.ports.map((p): Message | undefined => {
				const ing = nodes
					.filter((i) => i.type === "gateway-https")
					.filter(
						(i) =>
							i.data && i.data.https && i.data.https.serviceId === n.id && i.data.https.portId === p.id,
					);
				if (ing.length < 2) {
					return undefined;
				}
				return {
					id: `${n.id}-${p.id}-multiple-ingress`,
					type: "FATAL",
					nodeId: n.id,
					message: `Can not expose same port using multiple ingresses: ${p.name} - ${p.value}`,
					onHighlight: (store) => store.updateNode(n.id, { selected: true }),
					onLooseHighlight: (store) => store.updateNode(n.id, { selected: false }),
				};
			}),
		)
		.filter((m) => m !== undefined);
	return noName.concat(noSource).concat(noRuntime).concat(noPorts).concat(noIngress).concat(multipleIngress);
}

function GatewayHTTPSValidator(nodes: AppNode[]): Message[] {
	const ing = nodes.filter((n) => n.type === "gateway-https");
	const noNetwork: Message[] = ing
		.filter(
			(n) =>
				n.data == null ||
				n.data.network == null ||
				n.data.network == "" ||
				n.data.subdomain == null ||
				n.data.subdomain == "",
		)
		.map(
			(n): Message => ({
				id: `${n.id}-no-network`,
				type: "FATAL",
				nodeId: n.id,
				message: "Network and subdomain must be defined",
				onHighlight: (store) => store.updateNode(n.id, { selected: true }),
				onLooseHighlight: (store) => store.updateNode(n.id, { selected: false }),
			}),
		);
	const notConnected: Message[] = ing
		.filter(
			(n) =>
				n.data == null ||
				n.data.https == null ||
				n.data.https.serviceId == null ||
				n.data.https.serviceId == "" ||
				n.data.https.portId == null ||
				n.data.https.portId == "",
		)
		.map((n) => ({
			id: `${n.id}-not-connected`,
			type: "FATAL",
			nodeId: n.id,
			message: "Connect to a service port",
			onHighlight: (store) => store.updateNode(n.id, { selected: true }),
			onLooseHighlight: (store) => store.updateNode(n.id, { selected: false }),
		}));
	return noNetwork.concat(notConnected);
}

function GatewayTCPValidator(nodes: AppNode[]): Message[] {
	const ing = nodes.filter((n) => n.type === "gateway-tcp");
	const noNetwork: Message[] = ing
		.filter(
			(n) =>
				n.data == null ||
				n.data.network == null ||
				n.data.network == "" ||
				n.data.subdomain == null ||
				n.data.subdomain == "",
		)
		.map(
			(n): Message => ({
				id: `${n.id}-no-network`,
				type: "FATAL",
				nodeId: n.id,
				message: "Network and subdomain must be defined",
				onHighlight: (store) => store.updateNode(n.id, { selected: true }),
				onLooseHighlight: (store) => store.updateNode(n.id, { selected: false }),
			}),
		);
	const notConnected: Message[] = ing
		.filter((n) => n.data == null || n.data.exposed == null || n.data.exposed.length === 0)
		.map((n) => ({
			id: `${n.id}-not-connected`,
			type: "FATAL",
			nodeId: n.id,
			message: "Connect to a service port",
			onHighlight: (store) => store.updateNode(n.id, { selected: true }),
			onLooseHighlight: (store) => store.updateNode(n.id, { selected: false }),
		}));
	return noNetwork.concat(notConnected);
}
