import * as better_call0 from "better-call";
import { StandardSchemaV1 } from "better-call";
import { GenericEndpointContext, InferOptionSchema } from "better-auth";
import { z } from "zod";
import { createAuthEndpoint } from "better-auth/api";

//#region src/utils/transform.d.ts
type CapitalizeFirst<S extends string> = S extends `${infer First}${infer Rest}` ? `${Uppercase<First>}${Rest}` : S;
type TransformPath<S extends string> = S extends `${infer Head}/${infer Tail}` ? TransformPath<`${Head}${CapitalizeFirst<Tail>}`> : S extends `${infer Head}-${infer Tail}` ? TransformPath<`${Head}${CapitalizeFirst<Tail>}`> : CapitalizeFirst<S>;
type KebabStart<S extends string> = S extends `-${infer R}` ? KebabStart<R> : S extends `/${infer R}` ? KebabStart<R> : S extends `${infer F}${infer R}` ? F extends Lowercase<F> ? `${F}${KebabCont<R>}` : `${Lowercase<F>}${KebabCont<R>}` : S;
type KebabCont<S extends string> = S extends `${infer F}${infer R}` ? F extends "-" | "/" ? `-${KebabStart<R>}` : F extends Lowercase<F> ? `${F}${KebabCont<R>}` : `-${Lowercase<F>}${KebabCont<R>}` : S;
type TransformClientPath<S extends string> = KebabStart<S>;
//#endregion
//#region src/internal-types.d.ts
type Permission = {
  statement: string;
  permissions: string[];
};
type AllOptional<T$1> = { [K in keyof T$1]-?: {} extends Pick<T$1, K> ? true : false }[keyof T$1] extends true ? true : false;
type MakeOptionalIfAllOptional<T$1> = AllOptional<T$1> extends true ? T$1 | undefined : T$1;
type InferPreferenceInput<S extends PreferenceScopeAttributes, P extends PreferenceSchemaAttribute, OmitValue extends boolean = false> = MakeOptionalIfAllOptional<(OmitValue extends true ? {} : {
  value: StandardSchemaV1.InferInput<P["type"]>;
}) & (S["requireScopeId"] extends true ? {
  scopeId: string;
} : {
  scopeId?: string;
})>;
type InferPreferenceOutput<Preference extends string, S extends PreferenceScopeAttributes, P extends PreferenceSchemaAttribute> = StandardSchemaV1.InferOutput<P["type"]> | S["defaultValues"] extends { [key in Preference]: infer V } ? V extends (() => infer R) ? Awaited<R> : V extends undefined ? null : V : null;
type EndpointPair<Scope extends string, Preference extends string, S extends PreferenceScopeAttributes, P extends PreferenceSchemaAttribute> = {
  set: ReturnType<typeof createAuthEndpoint<`/preferences/${TransformClientPath<Scope>}/${TransformClientPath<Preference>}/set`, {
    method: "POST";
    metadata: {
      $Infer: {
        body: InferPreferenceInput<S, P>;
      };
    };
  }, void>>;
  get: ReturnType<typeof createAuthEndpoint<`/preferences/${TransformClientPath<Scope>}/${TransformClientPath<Preference>}/get`, {
    method: "GET";
    metadata: {
      $Infer: {
        query: InferPreferenceInput<S, P, true>;
      };
    };
  }, InferPreferenceOutput<Preference, S, P>>>;
};
type FilteredGroupPreferences<T$1 extends Partial<Record<string, boolean>>> = { [K in keyof T$1 as T$1[K] extends false ? never : K]: T$1[K] };
type InferGroupInput<S extends PreferenceScopeAttributes, G extends PreferenceScopeGroupAttributes<S["preferences"]>, OmitValue extends boolean = false> = MakeOptionalIfAllOptional<(OmitValue extends true ? {} : {
  values: { [K in keyof FilteredGroupPreferences<G["preferences"]>]: StandardSchemaV1.InferInput<S["preferences"][K]["type"]> };
}) & {
  scopeId?: string;
}>;
type InferGroupOutput<S extends PreferenceScopeAttributes, G extends PreferenceScopeGroupAttributes<S["preferences"]>> = { [K in keyof FilteredGroupPreferences<G["preferences"]>]: StandardSchemaV1.InferOutput<S["preferences"][K]["type"]> | null };
type GroupEndpointPair<Scope extends string, Group extends string, S extends PreferenceScopeAttributes, G extends PreferenceScopeGroupAttributes<S["preferences"]>> = {
  set: G["operations"] extends undefined | "write" | ["write", "read"] | ["read", "write"] ? ReturnType<typeof createAuthEndpoint<`/preferences/${TransformClientPath<Scope>}/$${TransformClientPath<Group>}/set`, {
    method: "POST";
    metadata: {
      $Infer: {
        body: InferGroupInput<S, G>;
      };
    };
  }, void>> : never;
  get: G["operations"] extends undefined | "read" | ["write", "read"] | ["read", "write"] ? ReturnType<typeof createAuthEndpoint<`/preferences/${TransformClientPath<Scope>}/$${TransformClientPath<Group>}/get`, {
    method: "GET";
    metadata: {
      $Infer: {
        query: InferGroupInput<S, G, true>;
      };
    };
  }, InferGroupOutput<S, G>>> : never;
};
type AffixedGroupEndpoints<Scope extends string, Group extends string, S extends PreferenceScopeAttributes, G extends PreferenceScopeGroupAttributes<S["preferences"]>> = { [K in keyof GroupEndpointPair<Scope, Group, S, G> as `${Extract<K, string>}${TransformPath<Scope>}${TransformPath<Group>}Preferences`]: GroupEndpointPair<Scope, Group, S, G>[K] };
type AffixedEndpoints<Scope extends string, Preference extends string, S extends PreferenceScopeAttributes, P extends PreferenceSchemaAttribute> = { [K in keyof EndpointPair<Scope, Preference, S, P> as `${Extract<K, string>}${TransformPath<Scope>}${TransformPath<Preference>}Preference`]: EndpointPair<Scope, Preference, S, P>[K] };
type PreferenceScopesToEndpoints<S extends Record<string, PreferenceScopeAttributes>> = { [K in keyof S & string]: { [T in keyof S[K]["preferences"] & string]: AffixedEndpoints<K, T, S[K], S[K]["preferences"][T]> }[keyof S[K]["preferences"] & string] & (S[K]["groups"] extends infer V ? V extends Record<string, PreferenceScopeGroupAttributes> ? { [T in keyof V & string]: AffixedGroupEndpoints<K, T, S[K], V[T]> }[keyof V & string] : {} : {}) }[keyof S & string];
//#endregion
//#region src/schema.d.ts
declare const schema: {
  preference: {
    fields: {
      userId: {
        type: "string";
        required: false;
        references: {
          model: string;
          field: string;
        };
      };
      scopeId: {
        type: "string";
        required: false;
      };
      scope: {
        type: "string";
      };
      key: {
        type: "string";
      };
      value: {
        type: "string";
        sortable: true;
      };
      updatedAt: {
        type: "date";
        required: true;
        input: false;
        defaultValue: () => Date;
        onUpdate: () => Date;
      };
    };
  };
};
//#endregion
//#region src/types.d.ts
type PreferenceSchemaAttribute<S = any> = {
  type: StandardSchemaV1<unknown, S>;
  sensitive?: boolean;
  secret?: string;
};
type PreferenceScopeGroupAttributes<S extends Record<string, PreferenceSchemaAttribute> = Record<string, PreferenceSchemaAttribute>> = {
  preferences: Partial<Record<keyof S, boolean>>;
  operations?: "read" | "write" | ["read", "write"] | ["write", "read"];
};
type PreferenceScopeAttributes<S extends Record<string, PreferenceSchemaAttribute> = Record<string, PreferenceSchemaAttribute>, G extends Record<string, PreferenceScopeGroupAttributes<S>> = Record<string, PreferenceScopeGroupAttributes<S>>> = {
  preferences: S;
  groups?: G;
  defaultValues?: Partial<{ [K in keyof S]: StandardSchemaV1.InferInput<S[K]["type"]> | (() => Promise<StandardSchemaV1.InferInput<S[K]["type"]>> | StandardSchemaV1.InferInput<S[K]["type"]>) }>;
  canRead?: ((data: {
    key: string[];
    scope: string;
    scopeId?: string;
  }, ctx: GenericEndpointContext) => Promise<boolean> | boolean | Promise<Permission> | Permission) | boolean | Permission;
  canWrite?: ((data: {
    key: string[];
    scope: string;
    scopeId?: string;
    values: Record<string, JSONType>;
  }, ctx: GenericEndpointContext) => Promise<boolean> | boolean | Promise<Permission> | Permission) | boolean | Permission;
  requireScopeId?: boolean;
  disableUserBinding?: boolean;
  mergeStrategy?: "deep" | "replace";
  sensitive?: boolean;
  secret?: string;
};
type PreferencesOptions<Scopes extends Record<string, PreferenceScopeAttributes> = Record<string, PreferenceScopeAttributes>> = {
  scopes: Scopes;
  schema?: InferOptionSchema<typeof schema>;
};
type JSONType = z.infer<ReturnType<typeof z.json>>;
//#endregion
//#region src/index.d.ts
declare const preferences: {
  <S extends Record<string, PreferenceScopeAttributes>, O extends PreferencesOptions<S>>(options: O & {
    scopes: S;
  }): {
    id: "preferences";
    endpoints: {
      getPreference: {
        <AsResponse extends boolean = false, ReturnHeaders extends boolean = false>(inputCtx_0: {
          body?: undefined;
        } & {
          method?: "GET" | undefined;
        } & {
          query: {
            scope: string;
            key: string;
            scopeId?: string | undefined;
          };
        } & {
          params?: Record<string, any>;
        } & {
          request?: Request;
        } & {
          headers?: HeadersInit;
        } & {
          asResponse?: boolean;
          returnHeaders?: boolean;
          use?: better_call0.Middleware[];
          path?: string;
        } & {
          asResponse?: AsResponse | undefined;
          returnHeaders?: ReturnHeaders | undefined;
        }): Promise<[AsResponse] extends [true] ? Response : [ReturnHeaders] extends [true] ? {
          headers: Headers;
          response: any;
        } : any>;
        options: {
          method: "GET";
          query: z.ZodObject<{
            scope: z.ZodString;
            scopeId: z.ZodOptional<z.ZodString>;
            key: z.ZodString;
          }, z.core.$strip>;
        } & {
          use: any[];
        };
        path: "/preferences/get-preference";
      };
      setPreference: {
        <AsResponse extends boolean = false, ReturnHeaders extends boolean = false>(inputCtx_0: {
          body: {
            scope: string;
            key: string;
            value: z.core.util.JSONType;
            scopeId?: string | undefined;
          };
        } & {
          method?: "POST" | undefined;
        } & {
          query?: Record<string, any> | undefined;
        } & {
          params?: Record<string, any>;
        } & {
          request?: Request;
        } & {
          headers?: HeadersInit;
        } & {
          asResponse?: boolean;
          returnHeaders?: boolean;
          use?: better_call0.Middleware[];
          path?: string;
        } & {
          asResponse?: AsResponse | undefined;
          returnHeaders?: ReturnHeaders | undefined;
        }): Promise<[AsResponse] extends [true] ? Response : [ReturnHeaders] extends [true] ? {
          headers: Headers;
          response: void;
        } : void>;
        options: {
          method: "POST";
          body: z.ZodObject<{
            scope: z.ZodString;
            scopeId: z.ZodOptional<z.ZodString>;
            key: z.ZodString;
            value: z.ZodJSONSchema;
          }, z.core.$strip>;
          use: ((inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<{
            session: {
              session: Record<string, any> & {
                id: string;
                createdAt: Date;
                updatedAt: Date;
                userId: string;
                expiresAt: Date;
                token: string;
                ipAddress?: string | null | undefined;
                userAgent?: string | null | undefined;
              };
              user: Record<string, any> & {
                id: string;
                createdAt: Date;
                updatedAt: Date;
                email: string;
                emailVerified: boolean;
                name: string;
                image?: string | null | undefined;
              };
            } | null;
          }>)[];
        } & {
          use: any[];
        };
        path: "/preferences/set-preference";
      };
    } & PreferenceScopesToEndpoints<S>;
    options: O & {
      scopes: S;
    };
    schema: {
      preference: {
        fields: {
          userId: {
            type: "string";
            required: false;
            references: {
              model: string;
              field: string;
            };
          };
          scopeId: {
            type: "string";
            required: false;
          };
          scope: {
            type: "string";
          };
          key: {
            type: "string";
          };
          value: {
            type: "string";
            sortable: true;
          };
          updatedAt: {
            type: "date";
            required: true;
            input: false;
            defaultValue: () => Date;
            onUpdate: () => Date;
          };
        };
      };
    };
    $ERROR_CODES: {
      readonly PREFERENCE_SCOPE_NOT_FOUND: "Scope not found";
      readonly PREFERENCE_SCOPE_PREFERENCE_NOT_FOUND: "Scope preference not found";
      readonly PREFERENCE_SCOPE_ID_IS_REQUIRED: "Scope id is required";
      readonly PREFERENCE_MISSING_PERMISSION: "Missing permission";
      readonly PREFERENCES_ADMIN_PLUGIN_NOT_SETUP: "Admin plugin is not set up";
    };
    $Infer: {
      PreferenceScopes: Extract<keyof S, string>;
      "~PreferenceScopesDef": S;
    };
  };
  createScope: <S extends Record<string, PreferenceSchemaAttribute>, G extends Record<string, PreferenceScopeGroupAttributes<S>>, D extends PreferenceScopeAttributes<S, G>>(data: D & {
    preferences: S;
    groups?: G;
  }) => D & {
    preferences: S;
    groups?: G;
  };
};
declare const createPreferenceScope: <S extends Record<string, PreferenceSchemaAttribute>, G extends Record<string, PreferenceScopeGroupAttributes<S>>, D extends PreferenceScopeAttributes<S, G>>(data: D & {
  preferences: S;
  groups?: G;
}) => D & {
  preferences: S;
  groups?: G;
};
//#endregion
//#region src/client.d.ts
declare const preferencesClient: <Scopes extends {
  $Infer: {
    "~PreferenceScopesDef": Record<string, PreferenceScopeAttributes>;
  };
}>() => {
  id: "preferences";
  $InferServerPlugin: ReturnType<typeof preferences<Scopes["$Infer"]["~PreferenceScopesDef"], PreferencesOptions<Scopes["$Infer"]["~PreferenceScopesDef"]>>>;
  getActions: () => {
    $Infer: {
      PreferenceScopes: Extract<keyof Scopes["$Infer"]["~PreferenceScopesDef"], string>;
    };
  };
};
//#endregion
export { PreferenceSchemaAttribute as a, PreferencesOptions as c, JSONType as i, createPreferenceScope as n, PreferenceScopeAttributes as o, preferences as r, PreferenceScopeGroupAttributes as s, preferencesClient as t };