import type { output, TailorAnyDBField } from "@tailor-platform/sdk";
import type { Kysely, Selectable, Insertable, Updateable } from "@tailor-platform/sdk/kysely";

export type InferSchema<T> = T extends Kysely<infer S> ? S : never;
export type { Selectable, Insertable, Updateable };

export type EmptyFields = {};

// Fields every db.type has: implicit id plus db.fields.timestamps().
export type CommonReservedFields = "id" | "createdAt" | "updatedAt";

// A string-literal type so the message shows in the assignability error.
type ReservedFieldError<K extends string> = `Cannot redefine built-in field '${K}'`;

// Turns reserved keys in F into a compile error, leaving other keys intact.
export type NoReservedFields<
  F extends Record<string, TailorAnyDBField>,
  Reserved extends string,
> = {
  [K in keyof F]: K extends Reserved ? ReservedFieldError<K> : F[K];
};

// TODO: Ideally use Kysely Insertable-equivalent type from SDK instead of inferring from output<T>
export type FieldsToInsertable<F> = {
  [K in keyof F as null extends output<F[K]> ? never : K]: output<F[K]>;
} & {
  [K in keyof F as null extends output<F[K]> ? K : never]?: output<F[K]>;
};
