import { GeneratedJsWithTypes, header } from "./common.js";

export function serverCodegen(): GeneratedJsWithTypes {
  const serverDTS = `
    ${header(
      "Generated utilities for implementing server-side Convex query and mutation functions."
    )}
    import {
      ActionBuilderForAPI,
      MutationBuilderForDataModel,
      QueryBuilderForDataModel,
      ActionCtx as GenericActionCtx,
      QueryCtx as GenericQueryCtx,
      MutationCtx as GenericMutationCtx,
      DatabaseReader as GenericDatabaseReader,
      DatabaseWriter as GenericDatabaseWriter,
    } from "convex/server";
    import type { DataModel } from "./dataModel.js";
    import type { API } from "./api.js";

    /**
     * Define a query in this Convex app's public API.
     *
     * This function will be allowed to read your Convex database and will be accessible from the client.
     *
     * @param func - The query function. It receives a {@link QueryCtx} as its first argument.
     * @returns The wrapped query. Include this as an \`export\` to name it and make it accessible.
     */
    export declare const query: QueryBuilderForDataModel<DataModel>;

    /**
     * Define a mutation in this Convex app's public API.
     *
     * This function will be allowed to modify your Convex database and will be accessible from the client.
     *
     * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
     * @returns The wrapped mutation. Include this as an \`export\` to name it and make it accessible.
     */
    export declare const mutation: MutationBuilderForDataModel<DataModel>;

    /**
     * Define an action in this Convex app's public API.
     *
     * An action is a function which can execute any JavaScript code, including non-deterministic
     * code and code with side-effects. Actions are often used to call into third-party services.
     * Actions execute in a Node.js environment and can interact with the database indirectly by
     * calling queries and mutations via the provided \`dbFunctions\` object. Actions need to be defined
     * in the \`/convex/actions  directory\`. Queries and mutations, on the other hand, must be defined
     * outside of the \`/convex/actions directory\`.
     *
     * @param func - The action. It receives a {@link ActionCtx} as its first argument.
     * @returns The wrapped action. Include this as an \`export\` to name it and make it accessible.
     */
    export declare const action: ActionBuilderForAPI<API>;

    /**
     * A set of services for use within Convex query functions.
     *
     * The query context is passed as the first argument to any Convex query
     * function run on the server.
     *
     * This differs from the {@link MutationCtx} because all of the services are
     * read-only.
     */
    export type QueryCtx = GenericQueryCtx<DataModel>;

    /**
     * A set of services for use within Convex mutation functions.
     *
     * The mutation context is passed as the first argument to any Convex mutation
     * function run on the server.
     */
    export type MutationCtx = GenericMutationCtx<DataModel>;

    /**
     * A set of services for use within Convex mutation functions.
     *
     * The mutation context is passed as the first argument to any Convex mutation
     * function run on the server.
     */
    export type ActionCtx = GenericActionCtx<API>;

    /**
     * An interface to read from the database within Convex query functions.
     *
     * The two entry points are {@link DatabaseReader.get}, which fetches a single
     * document by its {@link Id}, or {@link DatabaseReader.query}, which starts
     * building a query.
     */
    export type DatabaseReader = GenericDatabaseReader<DataModel>;

    /**
     * An interface to read from and write to the database within Convex mutation
     * functions.
     *
     * Convex guarantees that all writes within a single mutation are
     * executed atomically, so you never have to worry about partial writes leaving
     * your data in an inconsistent state. See [the Convex Guide](https://docs.convex.dev/understanding/convex-fundamentals/functions#atomicity-and-optimistic-concurrency-control)
     * for the guarantees Convex provides your functions.
     */
    export type DatabaseWriter = GenericDatabaseWriter<DataModel>;`;

  const serverJS = `
    ${header(
      "Generated utilities for implementing server-side Convex query and mutation functions."
    )}
    import {
      actionGeneric,
      queryGeneric,
      mutationGeneric,
    } from "convex/server";

    /**
     * Define a query in this Convex app's public API.
     *
     * This function will be allowed to read your Convex database and will be accessible from the client.
     *
     * @param func - The query function. It receives a {@link QueryCtx} as its first argument.
     * @returns The wrapped query. Include this as an \`export\` to name it and make it accessible.
     */
    export const query = queryGeneric;

    /**
     * Define a mutation in this Convex app's public API.
     *
     * This function will be allowed to modify your Convex database and will be accessible from the client.
     *
     * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
     * @returns The wrapped mutation. Include this as an \`export\` to name it and make it accessible.
     */
    export const mutation = mutationGeneric;

    /**
     * Define a function in this Convex app's public API.
     *
     * This is a generic function which unlike queries and mutations can execute any
     * JavaScript code. Node functions execute in a Node.js environment and can
     * interact with the database by calling queries and mutations via the provided
     * convex object. Node functions need to be defined in /convex/node directory.
     *
     * @param func - The function. It receives a {@link ActionCtx} as its first argument.
     * @returns The wrapped function. Include this as an \`export\` to name it and make it accessible.
     */
    export const action = actionGeneric;`;

  return {
    DTS: serverDTS,
    JS: serverJS,
  };
}
