/**
 * Copyright (c) 2026 Tencent. All rights reserved.
 * Module:   TXRealtimeTTS @ TXLiteAVSDK
 */

#pragma once

#include <cstdint>

#ifndef LITEAVSDK_TTS_API
#if defined(_WIN32)
#ifdef LITEAV_EXPORTS
#define LITEAVSDK_TTS_API __declspec(dllexport)
#else
#define LITEAVSDK_TTS_API __declspec(dllimport)
#endif
#else
#define LITEAVSDK_TTS_API __attribute__((visibility("default")))
#endif
#endif  /// LITEAVSDK_TTS_API

namespace liteav {
class ITXRealtimeTTS;
}

extern "C" LITEAVSDK_TTS_API liteav::ITXRealtimeTTS* TXRealtimeTTSCreate();
extern "C" LITEAVSDK_TTS_API void TXRealtimeTTSDestroy(liteav::ITXRealtimeTTS* instance);

namespace liteav {

enum class TXRealtimeTTSMode {
  kOnline,   /// 纯在线（WebSocket/HTTP）
  kOffline,  /// 纯离线（本地引擎，无网可用）
  kMix,      /// 混合：优先在线，弱网自动降级离线，恢复后回切
};

enum class TXRealtimeTTSError {
  kOk = 0,
  kInvalidState,  /// 状态不允许（如已处于 started 状态时再次调用 start）
  kInvalidParam,  /// 配置字段非法
  kInternalError,
};

enum class TXRealtimeTTSAudioOutputMode {
  kPlaybackOnly,         /// 仅播放音频，不回调音频帧
  kCallbackOnly,         /// 仅回调音频帧，不播放
  kPlaybackAndCallback,  /// 既播放音频又回调音频帧
};

struct TXRealtimeTTSOnlineCredential {
  const char* appId = nullptr;   /// 应用 appid
  const char* userId = nullptr;  /// 用户 id
  const char* userSig = nullptr;  /// 用户签名（服务端下发，避免密钥打包进客户端）
};

/// —— 离线/混合 鉴权 ——（offline / mix 必填）
struct TXRealtimeTTSOfflineLicense {
  const char* licenseUrl = nullptr;  /// 离线授权文件下载/校验地址
  const char* licenseKey = nullptr;  /// 离线授权 key
};

/// 统一参数（必填项）；其余可选参数一律通过 callExperimentalAPI 设置。
struct TXRealtimeTTSParams {
  TXRealtimeTTSMode mode = TXRealtimeTTSMode::kOnline;  /// 引擎模式：在线 / 离线 / 混合
  TXRealtimeTTSOnlineCredential online;                 /// mode=online/mix 必填
  TXRealtimeTTSOfflineLicense offline;                  /// mode=offline/mix 必填

  const char* voiceName = nullptr;  /// 音色（音色名，必填）
  TXRealtimeTTSAudioOutputMode audioOutputMode =
      TXRealtimeTTSAudioOutputMode::kPlaybackOnly;  /// 音频输出模式：仅播放 / 仅回调 /
                                                    /// 播放并回调（默认 kPlaybackOnly）
};

struct TXSynthesizeAudioFrame {
  const uint8_t* pcmData =
      nullptr;  /// 本次音频 PCM 字节；指针仅在回调内有效，跨线程/异步使用须深拷贝
  uint32_t pcmDataSize = 0;     /// pcmData 字节数
  uint32_t sampleRate = 16000;  /// 音频采样率（Hz），如 16000/48000
  uint32_t channelCount = 1;    /// 音频通道数，1=单声道，2=双声道
  uint32_t bitWidth = 16;       /// 采样位宽（bit），固定 16
  const char* textId = nullptr;  /// 文本标识（对应 appendText 的 textId，标示本次数据所属的文本段）
  const char* textSlice = nullptr;  /// 当前合成的数据所属的文本片段
  double progress = 0.0;  /// textSlice 在 textId 对应文本段中的百分比 [0.0, 1.0]
};

/// 文本转语音回调接口
/// @note 所有回调均已切换到 UI 线程，调用方无需关心线程安全
class ITXRealtimeTTSListener {
 public:
  virtual ~ITXRealtimeTTSListener() = default;

  /// 合成开始（鉴权通过 / 会话已建立），可在此切换 UI 状态。
  virtual void onStarted() {}

  /// 文本播放进度回调：逐片回调（流式）。
  /// @param textId    当前文本段标识
  /// @param textSlice 正在播放的文本切片
  virtual void onPlaybackProgress(const char* textId, const char* textSlice) {}

  /// 合成进度回调。仅当 audioOutputMode 为 kCallbackOnly 或 kPlaybackAndCallback 时触发。
  /// @param audioFrame 本次合成的音频帧（TXSynthesizeAudioFrame）
  virtual void onSynthesizedAudioFrame(const TXSynthesizeAudioFrame& audioFrame) {}

  /// 合成结束（成功或失败）。
  /// @param code 错误码，== TXRealtimeTTSError::kOk 表示成功完成；否则表示任意阶段失败
  ///             （鉴权失败 / 弱网 / 内部错误等）
  /// @param msg  错误信息（仅回调期间有效，可为 nullptr）
  virtual void onCompleted(int32_t code, const char* msg) {}
};

class ITXRealtimeTTS {
 public:
  virtual ~ITXRealtimeTTS() = default;

  /// 设置事件回调监听。
  /// @param listener 事件回调监听器（ITXRealtimeTTSListener 实现；传 nullptr 可取消监听）
  /// @return TXRealtimeTTSError 中的值。
  virtual int32_t setListener(ITXRealtimeTTSListener* listener) = 0;

  /// 启动实时 TTS 合成与播放。
  /// @param param 配置参数（TXRealtimeTTSParams）
  /// @return TXRealtimeTTSError 中的值。
  virtual int32_t start(const TXRealtimeTTSParams& param) = 0;

  /// 停止合成与播放。
  /// @return TXRealtimeTTSError 中的值。
  virtual int32_t stop() = 0;

  /// 暂停合成与播放。
  /// @return TXRealtimeTTSError 中的值。
  virtual int32_t pause() = 0;

  /// 恢复合成与播放。
  /// @return TXRealtimeTTSError 中的值。
  virtual int32_t resume() = 0;

  /// 清空当前待播放与待合成的文本数据。
  /// 调用 clear 之后，SDK 内部会立即丢弃所有排队文本，且保证不会再触发任何属于 clear 前 textId
  /// 的进度回调。
  /// @return TXRealtimeTTSError 中的值。
  virtual int32_t clear() = 0;

  /// 追加待合成文本（流式输入）。
  /// @param textId 文本标识（UTF-8，用于标识本次追加的文本）
  /// @param text   文本内容（UTF-8，必填）
  /// @param isEnd  是否为本段文本的最后一片，true 表示文本输入结束（默认 false）
  /// @return TXRealtimeTTSError 中的值。
  virtual int32_t appendText(const char* textId, const char* text, bool isEnd = false) = 0;

  /// 设置音量。
  /// @param volume 音量值，取值范围 [0, 200]，默认 100 = 正常
  /// @return TXRealtimeTTSError 中的值。
  virtual int32_t setVolume(float volume) = 0;

  /// 设置语速。
  /// @param speed 语速值，取值范围 [1, 3]，默认 1 = 正常
  /// @return TXRealtimeTTSError 中的值。
  virtual int32_t setSpeed(float speed) = 0;

  /// 实验性 API 调用接口
  /// @param jsonParams JSON 格式的参数字符串
  /// @return JSON 格式的返回结果
  virtual const char* callExperimentalAPI(const char* jsonParams) = 0;
};

}  // namespace liteav
