import { FastifyReply, FastifyRequest, RouteHandlerMethod } from "fastify";
import "fastify-cookie";
import "fastify-formbody";
import "fastify-multipart";

// Include the FastifyReply type
export { FastifyReply } from "fastify";

export type MiddlewareRequest<P>          = FastifyRequest & { middlewareParams: P };
export type HandlerMethod<T = undefined>  = (request: MiddlewareRequest<T>, reply: FastifyReply, next?: any) => void;
export type MiddlewareMethod<T>           = (request: MiddlewareRequest<T>, reply: FastifyReply, next: () => void) => void;
export type HandlerMethodWithMiddleware<T = undefined> = (request: MiddlewareRequest<MiddlewareParams<T>>, reply: FastifyReply) => void;
export type IteratorNext                  = () => void;

export type MiddlewareParams<T> = T extends MiddlewareMethod<infer X>[] ? X : never;

/**
 * A route handler that supports middleware methods
 */
export function handleMiddleware<T extends MiddlewareMethod<any>[]>(middleware: T, handler?: HandlerMethodWithMiddleware<T>) {
	let result = <HandlerMethod<T>> (async (request, reply, next) => {
		var iterator = middleware[Symbol.iterator]();
		var nextMiddleware = async () => {
			let result = iterator.next();
			if (result.done) {
				if (handler) {
					(<any>handler)(request, reply);
				} else if (next !== undefined) {
					next();
				}
				return;
			}
			result.value(request, reply, nextMiddleware);
		};
		nextMiddleware();
	});
	return <RouteHandlerMethod>result;
}
