import { AppNode, Env, GatewayHttpsNode, 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 }[];
};

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);
		const tcpNodes = nodes.filter((n) => n.type === "gateway-tcp").filter((n) => n.data.exposed !== undefined);
		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 || []).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: GatewayHttpsNode): 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 }))
							: [],
					};
				}),
			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 ingress: ${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);
}
