import { TSchema, Static } from "@sinclair/typebox";
import { GenericSchema, GenericSchemaAsync, InferInput, InferOutput } from "valibot";
import { Schema as Schema$1, InferType } from "yup";
import { z } from "zod";

type IfInstalled<T> = any extends T ? never : T;
type Schema =
	| IfInstalled<z.ZodType>
	| IfInstalled<GenericSchema>
	| IfInstalled<GenericSchemaAsync>
	| IfInstalled<Schema$1>
	| IfInstalled<TSchema>;
type Infer<S extends Schema> =
	S extends IfInstalled<z.ZodType>
		? z.infer<S>
		: S extends IfInstalled<GenericSchema>
			? InferOutput<S>
			: S extends IfInstalled<GenericSchemaAsync>
				? InferOutput<S>
				: S extends IfInstalled<Schema$1>
					? InferType<S>
					: S extends IfInstalled<TSchema>
						? Static<S>
						: never;
type InferIn<S extends Schema> =
	S extends IfInstalled<z.ZodType>
		? z.input<S>
		: S extends IfInstalled<GenericSchema>
			? InferInput<S>
			: S extends IfInstalled<GenericSchemaAsync>
				? InferInput<S>
				: S extends IfInstalled<Schema$1>
					? InferType<S>
					: S extends IfInstalled<TSchema>
						? Static<S>
						: never;
type InferArray<BAS extends readonly Schema[]> = {
	[K in keyof BAS]: Infer<BAS[K]>;
};
type InferInArray<BAS extends readonly Schema[]> = {
	[K in keyof BAS]: InferIn<BAS[K]>;
};
type ValidationIssue = {
	message: string;
	path?: Array<string | number | symbol>;
};
interface ValidationAdapter {
	validate<S extends Schema>(
		schema: S,
		data: unknown
	): Promise<
		| {
				success: true;
				data: Infer<S>;
		  }
		| {
				success: false;
				issues: ValidationIssue[];
		  }
	>;
	validate<S extends IfInstalled<z.ZodType>>(
		schema: S,
		data: unknown
	): Promise<
		| {
				success: true;
				data: Infer<S>;
		  }
		| {
				success: false;
				issues: ValidationIssue[];
		  }
	>;
	validate<S extends IfInstalled<GenericSchema>>(
		schema: S,
		data: unknown
	): Promise<
		| {
				success: true;
				data: Infer<S>;
		  }
		| {
				success: false;
				issues: ValidationIssue[];
		  }
	>;
	validate<S extends IfInstalled<GenericSchemaAsync>>(
		schema: S,
		data: unknown
	): Promise<
		| {
				success: true;
				data: Infer<S>;
		  }
		| {
				success: false;
				issues: ValidationIssue[];
		  }
	>;
	validate<S extends IfInstalled<Schema$1>>(
		schema: S,
		data: unknown
	): Promise<
		| {
				success: true;
				data: Infer<S>;
		  }
		| {
				success: false;
				issues: ValidationIssue[];
		  }
	>;
	validate<S extends IfInstalled<TSchema>>(
		schema: S,
		data: unknown
	): Promise<
		| {
				success: true;
				data: Infer<S>;
		  }
		| {
				success: false;
				issues: ValidationIssue[];
		  }
	>;
}

export type { IfInstalled, Infer, InferArray, InferIn, InferInArray, Schema, ValidationAdapter, ValidationIssue };
