import { z } from '@hono/zod-openapi';

export async function parseWithAwait<T>(schema: z.ZodSchema<T>, data: unknown): Promise<T> {
    // 先尝试同步解析，捕获 Promise 错误
    const syncResult = schema.safeParse(data);

    if (!syncResult.success) {
      // 提取 Promise 错误的路径信息
      const promiseErrors = syncResult.error.issues.filter(issue =>
        issue.code === 'invalid_type' &&
        issue.message.includes('received Promise')
      );

      if (promiseErrors.length > 0) {
        // 根据路径直接 await Promise
        const processedData = await resolvePromisesByPath(data, promiseErrors);

        // 重新解析处理后的数据
        return schema.parse(processedData) as T;
      }

      throw syncResult.error;
    }

    return syncResult.data as T;
  }

  async function resolvePromisesByPath(data: any, promiseErrors: any[]): Promise<any> {
    const clonedData = JSON.parse(JSON.stringify(data, (_, value) => {
      // 保留 Promise 对象，不进行序列化
      return typeof value?.then === 'function' ? value : value;
    }));

    // 根据错误路径逐个处理 Promise
    for (const error of promiseErrors) {
      const path = error.path;
      const promiseValue = getValueByPath(data, path);

      if (promiseValue && typeof promiseValue.then === 'function') {
        const resolvedValue = await promiseValue;
        setValueByPath(clonedData, path, resolvedValue);
      }
    }

    return clonedData;
  }

  function getValueByPath(obj: any, path: (string | number)[]): any {
    return path.reduce((current, key) => current?.[key], obj);
  }

  function setValueByPath(obj: any, path: (string | number)[], value: any): void {
    const lastKey = path[path.length - 1];
    const parentPath = path.slice(0, -1);
    const parent = getValueByPath(obj, parentPath);
    if (parent && lastKey !== undefined) {
      parent[lastKey] = value;
    }
  }