import z, { ZodObject, ZodRawShape } from 'zod';

type Paramifiable<T> = (T extends string ? string : never) | (T extends number ? number : never) | (T extends boolean ? boolean : never) | string | null;
type UpdateArgs<Schema> = Schema extends ZodObject<ZodRawShape> ? Partial<{
    [K in keyof z.infer<Schema>]: Paramifiable<z.infer<Schema>[K]>;
}> : Record<string, string | number | boolean | null>;
interface QueryGuardAdapter {
    /** 現在の search 部分 (`?foo=1&bar=2`) を返す */
    getSearch(): string;
    /** search を pushState/replaceState 相当で更新する */
    setSearch(next: string): void;
    /** `popstate` 等を購読し、変化時にコールバックを呼ぶ */
    subscribe(cb: () => void): () => void;
}
type Optionalise<T> = {
    [K in keyof T]: T[K] | undefined;
};
/**
 * SearchParamsOptions
 * -------------------
 * resolver:  z.object() スキーマ（無ければゆるい string 辞書）
 * preprocess: 読み込み時に key/value を加工
 * adapter:   URL 操作をフレームワークに合わせて差し替え
 */
type QueryGuardOptions<Schema extends ZodObject<ZodRawShape> | undefined = undefined> = {
    resolver?: Schema;
    preprocess?: Schema extends ZodObject<ZodRawShape> ? (key: keyof z.infer<Schema> & string, value: string) => string : (key: string, value: string) => string;
    adapter?: QueryGuardAdapter;
    mode?: 'strict' | 'pick';
};
declare function useQueryGuard<Schema extends ZodObject<ZodRawShape> | undefined = undefined>(options?: QueryGuardOptions<Schema>): {
    data: Schema extends ZodObject<ZodRawShape> ? Optionalise<z.infer<Schema>> : Record<string, string | undefined>;
    isReady: boolean;
    isError: boolean;
    updateParams: (params: UpdateArgs<Schema>) => void;
};

export { type QueryGuardAdapter, type QueryGuardOptions, useQueryGuard };
