import _regeneratorRuntime from '@babel/runtime/regenerator';
import { _ as __awaiter } from '../tslib.es6-848120af.js';
import { ab2str } from './helper.mjs';

/**
 * 解析 H5 环境下的 SSE 数据流
 * @param {Object} params - 参数对象
 * @param {Function} params.success - 成功回调函数
 * @param {Function} params.fail - 失败回调函数
 * @param {Function} params.complete - 完成回调函数
 * @param {Response} params.response - 响应对象
 * @returns {Promise} 返回一个 Promise，处理 SSE 数据流
 * @example
 * ```ts
 * const response = await fetch('/api/sse', { method: 'POST' });
 * await parseSSEChunkInH5({
 *   response,
 *   success: (chunk, line) => console.log(chunk),
 *   fail: ({ response }) => console.error(response.status),
 *   complete: () => console.log('finish'),
 * });
 * ```
 */
var parseSSEChunkInH5 = function parseSSEChunkInH5(_ref) {
  var success = _ref.success,
    fail = _ref.fail,
    complete = _ref.complete,
    response = _ref.response;
  return __awaiter(void 0, void 0, void 0, /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
    var reader, decoder, processText;
    return _regeneratorRuntime.wrap(function (_context2) {
      while (1) switch (_context2.prev = _context2.next) {
        case 0:
          processText = function _processText(_ref2) {
            var done = _ref2.done,
              value = _ref2.value;
            return __awaiter(this, void 0, void 0, /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
              var chunk, buffers, i, line, _response;
              return _regeneratorRuntime.wrap(function (_context) {
                while (1) switch (_context.prev = _context.next) {
                  case 0:
                    if (!done) {
                      _context.next = 1;
                      break;
                    }
                    complete === null || complete === void 0 ? void 0 : complete(true);
                    return _context.abrupt("return", Promise.resolve());
                  case 1:
                    chunk = decoder.decode(value);
                    buffers = chunk.toString().split(/\r?\n/);
                    i = 0;
                    while (i < buffers.length) {
                      line = buffers[i];
                      _response = line.slice(5);
                      success === null || success === void 0 ? void 0 : success(_response, line);
                      buffers.splice(i, 1);
                    }
                    return _context.abrupt("return", reader.read().then(processText));
                  case 2:
                  case "end":
                    return _context.stop();
                }
              }, _callee);
            }));
          };
          if (response === null || response === void 0 ? void 0 : response.ok) {
            _context2.next = 1;
            break;
          }
          // 失败中不调用完成，如果需要，业务自行在 fail 中调用
          // 防止业务在 fail 中调用 complete 时，complete 被调用两次
          fail === null || fail === void 0 ? void 0 : fail({
            response: response
          });
          // 抛出错误以便链式调用中的下一个.catch()处理
          return _context2.abrupt("return", Promise.reject(new Error('Request failed')));
        case 1:
          reader = response.body.getReader();
          decoder = new TextDecoder();
          if (reader) {
            _context2.next = 2;
            break;
          }
          return _context2.abrupt("return", Promise.reject(new Error('[SSE] 获取reader失败')));
        case 2:
          return _context2.abrupt("return", reader.read().then(processText));
        case 3:
        case "end":
          return _context2.stop();
      }
    }, _callee2);
  }));
};
/**
 * 在 H5 环境下发起 SSE 请求的核心函数
 * @param {Object} params - 参数对象
 * @param {string} params.url - 请求 URL
 * @param {any} params.data - 请求数据
 * @param {Function} params.success - 成功回调函数
 * @param {Function} params.fail - 失败回调函数
 * @param {Function} params.complete - 完成回调函数
 * @returns {Promise} 返回一个 Promise，包含响应对象
 * @example
 * ```ts
 * fetchSSECoreInH5({
 *   url: 'https://example.com/sse',
 *   data: { input: 'hello' },
 *   success: (chunk) => console.log(chunk),
 *   fail: ({ response }) => console.error('failed'),
 *   complete: () => console.log('done'),
 * });
 * ```
 */
function fetchSSECoreInH5(_ref3) {
  var url = _ref3.url,
    data = _ref3.data,
    success = _ref3.success,
    fail = _ref3.fail,
    complete = _ref3.complete;
  return new Promise(function (resolve, reject) {
    var controller = new AbortController();
    fetch(url, {
      method: 'POST',
      headers: {
        accept: 'application/json, text/plain, */*',
        'content-type': 'application/json;charset=UTF-8'
      },
      body: JSON.stringify(data),
      credentials: 'include',
      // mode: 'cors',
      signal: controller.signal
    }).then(function (response) {
      resolve(response);
      parseSSEChunkInH5({
        response: response,
        success: success,
        fail: fail,
        complete: complete
      });
    })["catch"](function (err) {
      reject(err);
    });
  });
}
/**
 * 获取登录 Cookie
 * @param {Function} isTestEnv - 是否为测试环境的函数
 * @returns {string} 返回拼接后的 Cookie 字符串
 */
function getLoginCookie(isTestEnv) {
  var headerCookie = '';
  var testEnv = isTestEnv === null || isTestEnv === void 0 ? void 0 : isTestEnv();
  var cookieSuffix = testEnv ? '@test' : '@prod';
  if (uni.getStorageSync("request-mp-set-cookie".concat(cookieSuffix))) {
    headerCookie = uni.getStorageSync("request-mp-set-cookie".concat(cookieSuffix));
  }
  if (uni.getStorageSync("user-info-sessionid".concat(cookieSuffix))) {
    // 如果是测试环境，需要设置到tiplogin_sessionid_test
    var sessionKey = 'tiplogin_sessionid';
    if (isTestEnv === null || isTestEnv === void 0 ? void 0 : isTestEnv()) {
      sessionKey = 'tiplogin_sessionid_test';
    }
    headerCookie += ";".concat(sessionKey, "=").concat(uni.getStorageSync("user-info-sessionid".concat(cookieSuffix)), ";");
  }
  return headerCookie;
}
/**
 * 解析 MP 环境下的 SSE 数据块
 * @param {Object} params - 参数对象
 * @param {string} params.chunk - 数据块
 * @param {Fail} [params.fail] - 失败回调函数
 * @param {Success} [params.success] - 成功回调函数
 * @example
 * ```ts
 * parseSSEChunkInMP({
 *   chunk: 'data: hello\ndata: world\n',
 *   success: (data, line) => console.log(data),
 *   fail: () => console.error('parse error'),
 * });
 * ```
 */
var parseSSEChunkInMP = function parseSSEChunkInMP(_ref4) {
  var chunk = _ref4.chunk,
    fail = _ref4.fail,
    success = _ref4.success;
  var buffers = chunk.toString().split(/\r?\n/);
  var i = 0;
  try {
    while (i < buffers.length) {
      var line = buffers[i];
      var response = line.slice(5);
      success === null || success === void 0 ? void 0 : success(response, line);
      buffers.splice(i, 1);
    }
  } catch (err) {
    fail === null || fail === void 0 ? void 0 : fail(false);
  }
};
/**
 * 在 MP 环境下发起 SSE 请求的核心函数
 * @param {RequestParams} params - 请求参数
 * @returns {Promise} 返回一个 Promise，包含请求任务对象
 * @example
 * ```ts
 * fetchSSECoreInMP({
 *   url: 'https://example.com/sse',
 *   data: { input: 'hello' },
 *   success: (data) => console.log(data),
 *   fail: (err) => console.error(err),
 *   complete: () => console.log('done'),
 *   isTestEnv: () => false,
 * });
 * ```
 */
function fetchSSECoreInMP(_ref5) {
  var url = _ref5.url,
    data = _ref5.data,
    success = _ref5.success,
    _fail = _ref5.fail,
    complete = _ref5.complete,
    isTestEnv = _ref5.isTestEnv;
  return new Promise(function (resolve) {
    // 开启分块接收，模拟 SSE
    var requestTask = wx.request({
      url: url,
      method: 'POST',
      responseType: 'arraybuffer',
      enableChunked: true,
      header: {
        Accept: 'text/event-stream',
        'content-type': 'application/json;charset=UTF-8',
        cookie: getLoginCookie(isTestEnv),
        'Cache-Control': 'no-cache'
      },
      data: data,
      success: function success(res) {
        console.log('[SSE] success: ', res);
        complete === null || complete === void 0 ? void 0 : complete(true, res);
      },
      fail: function fail(err) {
        console.log('[SSE] fail: ', err);
        _fail === null || _fail === void 0 ? void 0 : _fail(err);
      }
    });
    // 监听数据到达事件
    requestTask.onChunkReceived(function (res) {
      // res.data 是 ArrayBuffer，需要转换为字符串
      var chunk = ab2str(res.data);
      parseSSEChunkInMP({
        chunk: chunk,
        fail: _fail,
        success: success
      });
    });
    resolve(requestTask);
  });
}
/**
 * 发起 SSE 请求的核心函数，根据环境自动选择 H5 或 MP 实现
 * @param {RequestParams} params - 请求参数
 * @param {string} params.url - 请求地址
 * @param {Object} params.data - 请求数据
 * @param {Function} params.success - 成功回调
 * @param {Function} params.fail - 失败回调
 * @param {Function} params.complete - 完成回调
 * @returns {Promise} 返回一个 Promise，包含请求任务或响应对象
 * @example
 * ```ts
 * import { safeJsonParse } from 't-comm/es/json';
 *
 * import { fetchSSECore, type RequestParams } from 't-comm/es/sse';
 *
 * // 检查是否结束，业务自定义
 * function checkFinish(str) {
 *   const data: any = safeJsonParse(str);
 *   return data?.status === 3;
 * }
 *
 * // 业务二次封装，把自己的请求数据、自定义的处理数据的逻辑放进去
 * export function sendChatMessage({
 *   input,
 *   sessionId,
 *   extraInfo,
 *   expectedOp,
 *
 *   success,
 *   fail,
 *   complete,
 * }: {
 *   input: string;
 *   sessionId?: string;
 *   extraInfo?: string;
 *   expectedOp?: Record<string, any>;
 *
 *   success?: (data: any) => void;
 *   fail?: RequestParams['fail'];
 *   complete?: RequestParams['complete'];
 * }) {
 *   const origin = isTestEnv() ? 'https://xx.com' : 'https://xx.com';
 *   const url = `${origin}/xx.xx.xx.xx/xx?g_app_tk=${cookie.get('tip_token')}&tstamp=${Date.now()}`;
 *   const reqData = {
 *     input,
 *     session_id: sessionId,
 *     extra_info: extraInfo,
 *     expected_op: expectedOp,
 *   };
 *
 *   const parsedSuccess = (str, fullStr) => {
 *     const data: any = safeJsonParse(str);
 *     const fullData: any = safeJsonParse(fullStr);
 *
 *     if (checkFinish(str)) {
 *       complete?.(str);
 *       return;
 *     }
 *
 *     // 检查是否失败，业务自定义
 *     if (fullData?.err_msg) {
 *       fail?.(data);
 *       return;
 *     }
 *
 *     success?.(data);
 *   };
 *
 *   return fetchSSECore({
 *     url,
 *     data: reqData,
 *     success: parsedSuccess,
 *     fail,
 *     complete,
 *     isTestEnv,
 *   });
 * }
 *
 * ```
 */
function fetchSSECore(_ref6) {
  var url = _ref6.url,
    data = _ref6.data,
    success = _ref6.success,
    fail = _ref6.fail,
    complete = _ref6.complete,
    isTestEnv = _ref6.isTestEnv;
  if (typeof wx !== 'undefined' && typeof wx.request === 'function' && typeof fetch === 'undefined' && typeof AbortController === 'undefined') {
    return fetchSSECoreInMP({
      url: url,
      data: data,
      success: success,
      fail: fail,
      complete: complete,
      isTestEnv: isTestEnv
    });
  }
  return fetchSSECoreInH5({
    url: url,
    data: data,
    success: success,
    fail: fail,
    complete: complete
  });
}

export { fetchSSECore, fetchSSECoreInH5, fetchSSECoreInMP, parseSSEChunkInH5, parseSSEChunkInMP };
