import type { StandardSchemaV1 } from "@standard-schema/spec";
import type { IsLiteralBoolean } from "../../lib/types";
export type SchemaToType<T extends StandardSchemaV1> = StandardSchemaV1.InferOutput<T>;
export interface SchemaOptions<Output = unknown, Optional extends boolean = boolean> {
    predicates?: ((data: Output) => boolean) | ((data: Output) => boolean)[];
    optional?: Optional;
}
export interface Schema<Output = unknown> extends StandardSchemaV1<Output> {
    type: string;
    options: SchemaOptions<Output>;
    errors: (data: unknown) => ReadonlyArray<StandardSchemaV1.Issue>;
    guard: (data: unknown) => data is Output;
}
export interface UnknownSchema extends Schema {
    type: "unknown";
}
export interface StringSchema extends Schema<string> {
    type: "string";
}
export interface NumberSchema extends Schema<number> {
    type: "number";
}
export interface BooleanSchema extends Schema<boolean> {
    type: "boolean";
}
export interface UndefinedSchema extends Schema<undefined> {
    type: "undefined";
}
export interface NullSchema extends Schema<null> {
    type: "null";
}
export interface NullishSchema extends Schema<null | undefined> {
    type: "nullish";
}
export interface FunctionSchema extends Schema<(...args: any[]) => any> {
    type: "function";
}
export type ObjectConstructor = new (...args: any[]) => Object;
export interface InstanceSchema<Constructor extends ObjectConstructor = ObjectConstructor> extends Schema<InstanceType<Constructor>> {
    type: "instance";
    constructor: Constructor;
}
export type ObjectShape = {
    [key: string]: Schema<any>;
};
export type ObjectShapeToOutput<T extends ObjectShape> = {
    [K in keyof T as T[K] extends Schema<any> ? IsLiteralBoolean<T[K]["options"]["optional"]> extends true ? undefined extends T[K]["options"]["optional"] ? K : never : false extends T[K]["options"]["optional"] ? K : never : never]: T[K] extends Schema<any> ? StandardSchemaV1.InferOutput<T[K]> : never;
} & {
    [K in keyof T as T[K] extends Schema<any> ? IsLiteralBoolean<T[K]["options"]["optional"]> extends true ? never : true extends T[K]["options"]["optional"] ? K : never : never]?: T[K] extends Schema<any> ? StandardSchemaV1.InferOutput<T[K]> : never;
};
export interface ObjectSchema<Shape extends ObjectShape = ObjectShape> extends Schema<ObjectShapeToOutput<Shape>> {
    type: "object";
    shape: Shape;
}
export interface ArraySchema<Item extends Schema<any> = Schema<any>> extends Schema<StandardSchemaV1.InferOutput<Item>[]> {
    type: "array";
    items: Item[];
}
export interface UnionSchema<Member extends Schema<any> = Schema<any>> extends Schema<StandardSchemaV1.InferOutput<Member>> {
    type: "union";
    members: Member[];
}
export interface RecordSchema<Value extends Schema<any> = Schema<any>> extends Schema<Record<string, StandardSchemaV1.InferOutput<Value>>> {
    type: "record";
    values: Value[];
}
export interface SetSchema<Value extends Schema<any> = Schema<any>> extends Schema<Set<StandardSchemaV1.InferOutput<Value>>> {
    type: "set";
    values: Value[];
}
export interface MapSchema<Key extends Schema<any> = Schema<any>, Value extends Schema<any> = Schema<any>> extends Schema<Map<StandardSchemaV1.InferOutput<Key>, StandardSchemaV1.InferOutput<Value>>> {
    type: "map";
    keys: Key[];
    values: Value[];
}
