import { logger } from "../middleware/logger/logger.js";
import { defaultEndpointsFactory, Method } from "express-zod-api";
import { z, ZodType } from "zod";
import { Logger } from "pino";
import { VaultClient } from "./vault.js";

type OptionsProvider = () => Promise<{ vault: VaultClient }>;

let optionsProvider: OptionsProvider = async () => {
  throw new Error("Vault client is not initialized");
};

export const setOptionsProvider = (provider: OptionsProvider): void => {
  optionsProvider = provider;
};

export type CreateEndpointOptions<I extends ZodType, O extends ZodType> = {
  method: Method;
  input: I;
  output: O;
  handler: (
    input: z.infer<I>,
    options: { vault: VaultClient },
    logger: Logger
  ) => Promise<z.infer<O>>;
};

export const createEndpoint = <I extends ZodType, O extends ZodType>(
  opts: CreateEndpointOptions<I, O>
) => {
  const factory = defaultEndpointsFactory.addOptions(optionsProvider);
  return factory.build({
    method: opts.method,
    input: opts.input as any,
    output: opts.output as any,
    handler: async ({ input, options, logger: actualLogger }) => {
      const logger = actualLogger as unknown as Logger;
      logger.debug("Options:", options);
      return opts.handler(input, options as { vault: VaultClient }, logger);
    },
  });
};

export type ZodRoute = {
  [key in Method]?: ReturnType<typeof defaultEndpointsFactory.build>;
};

export const createRoute = (routes: ZodRoute) => {
  return routes;
};
