import type { UseTRPCMutationResult } from "@trpc/react-query/shared";
import { api, type RouterInputs, type RouterOutputs } from "../trpc";
/**
 * 定义 MutationType 类型，用于提取指定实体类型的特定 mutation 方法名。
 * @template T - 实体类型的键名（如 'post', 'user'）
 * @description 该类型通过遍历 RouterInputs[T] 的键名，筛选出符合条件的 mutation 方法名（如 'create', 'update' 等）。
 */
type MutationType<T extends keyof RouterInputs> = keyof {
	[K in keyof RouterInputs[T]]: K extends
		| "create"
		| "update"
		| "deleteMany"
		| "softDeleteByIds"
		| "restoreByIds"
		| "updateOrder"
		? RouterInputs[T][K]
		: never;
};
/**
 * 定义 MutationOptions 类型，用于配置特定 mutation 方法的回调函数。
 * @template T - 实体类型的键名
 * @template K - mutation 方法名
 * @description 该类型包含一个可选的 onSuccess 回调函数，用于在 mutation 成功时执行。
 */
type MutationOptions<
	T extends keyof RouterInputs,
	K extends MutationType<T>,
> = {
	onSuccess?: (
		data: RouterOutputs[T][K], // mutation 成功后的返回数据
		variables: RouterInputs[T][K], // mutation 的输入参数
		context?: unknown // 可选的上下文信息
	) => void;
};

/**
 * 定义 EntityOptions 类型，用于配置实体类型的所有 mutation 方法的回调函数。
 * @template T - 实体类型的键名
 * @description 该类型是一个对象，键为 mutation 方法名，值为对应的 MutationOptions 配置。
 */
type EntityOptions<T extends keyof RouterInputs> = {
	[K in MutationType<T>]?: MutationOptions<T, K>;
};

/**
 * 工具类型：简化 UseTRPCMutationResult 的类型断言。
 * @template T - 实体类型的键名
 * @template K - mutation 方法名
 * @description 该类型用于简化 UseTRPCMutationResult 的类型定义，使其更易读。
 */
export type MutationResult<
	T extends keyof RouterInputs,
	K extends MutationType<T>,
> = UseTRPCMutationResult<
	RouterOutputs[T][K], // mutation 成功后的返回数据
	unknown, // mutation 的错误类型
	RouterInputs[T][K], // mutation 的输入参数
	unknown // mutation 的上下文类型
>;

/**
 * 自定义 Hook：用于处理实体的 mutation 操作，并内置缓存失效机制。
 * @template T - 实体类型的键名（如 'post', 'user'）
 * @param {T} key - 实体键名
 * @param {EntityOptions<T>} [options] - 可选的 mutation 回调函数配置
 * @returns 返回一个包含多个 mutation 函数的对象
 * @description 该 Hook 封装了常见的 mutation 操作（如 create, update, deleteMany 等），并在每次 mutation 成功后自动失效相关缓存。
 */
export function useEntity<T extends keyof RouterInputs>(
	key: T,
	options?: EntityOptions<T>
) {
	const utils = api.useUtils(); // 获取 tRPC 的工具函数，用于操作缓存

	/**
	 * 创建 mutation 处理函数。
	 * @template K - mutation 方法名
	 * @param {K} mutation - mutation 方法名
	 * @returns 返回一个配置好的 mutation 函数
	 * @description 该函数根据传入的 mutation 方法名，生成对应的 mutation 函数，并配置 onSuccess 回调。
	 */

	const createMutationHandler = <K extends MutationType<T>>(mutation: K) => {
		const mutationFn = api[key as any][mutation]; // 获取对应的 tRPC mutation 函数
		return mutationFn.useMutation({
			onSuccess: (data, variables, context) => {
				utils[key].invalidate(); // 失效指定实体的缓存
				options?.[mutation]?.onSuccess?.(data, variables, context); // 调用用户自定义的 onSuccess 回调
			},
		});
	};

	// 返回包含多个 mutation 函数的对象
	return {
		create: createMutationHandler("create") as MutationResult<T, "create">, // 创建实体的 mutation 函数
		createCourse: createMutationHandler("createCourse") as MutationResult<
			T,
			"createCourse"
		>, // 创建实体的 mutation 函数
		update: createMutationHandler("update") as MutationResult<T, "create">, // 更新实体的 mutation 函数
		deleteMany: createMutationHandler("deleteMany") as MutationResult<
			T,
			"deleteMany"
		>, // 批量删除实体的 mutation 函数
		softDeleteByIds: createMutationHandler(
			"softDeleteByIds"
		) as MutationResult<T, "softDeleteByIds">, // 软删除实体的 mutation 函数
		restoreByIds: createMutationHandler("restoreByIds") as MutationResult<
			T,
			"restoreByIds"
		>, // 恢复软删除实体的 mutation 函数
		updateOrder: createMutationHandler("updateOrder") as MutationResult<
			T,
			"updateOrder"
		>, // 更新实体顺序的 mutation 函数
		updateOrderByIds: createMutationHandler(
			"updateOrderByIds"
		) as MutationResult<T, "updateOrderByIds">, // 更新实体顺序的 mutation 函数
	};
}
