/**
 * 企微 replyStream 流式渲染器 — 从 bridge-manager 企微分支迁入（C-2）。
 *
 * 对应原 bridge 行：
 *   onTyping  = 536-540；onDraft = 622-628（throttle）；onFinal = 691-712；
 *   abort     = 813-825；destroy = cleanupActiveFrame（行 852-854）。
 *
 * 🔥地雷3 delivered：原代码行 776 的 No-response 检查（!draftMessageId && !hasActiveCard
 * && !cardMessageId）对企微三项皆空 → 企微 result.text 为空时**总会**发 '_(No text response)_'
 * 覆盖 onTyping 的 placeholder。为精确镜像，delivered 恒为 false（企微不参与 draft/card 检查）。
 */

import type { WecomAdapter } from './adapter'
import type { StreamRenderer, StreamRenderContext } from '../stream-renderer'
import { DraftThrottle } from '../stream-renderer'
import { extractTemplateCards } from './template-cards'

export class WecomStreamRenderer implements StreamRenderer {
  private readonly draft = new DraftThrottle()  // shouldThrottle + isUnchanged

  constructor(private readonly ctx: StreamRenderContext) {}

  get delivered(): boolean {
    // 镜像原代码行 776：企微 draftMessageId/cardInstanceId/cardController 三项皆空，
    // result.text 空时总会触发 No-response 文本。delivered 恒 false 精确复刻此行为。
    return false
  }

  async onTyping(): Promise<void> {
    // 行 536-540：思考占位 via replyStream
    const adapter = this.ctx.adapter as WecomAdapter
    try {
      await adapter.replyStreamDraft(this.ctx.chatId, '⏳ 正在思考…')
    } catch { /* best effort */ }
  }

  async onDraft(partialText: string): Promise<void> {
    // 行 622-628（throttle）
    if (this.draft.shouldThrottle()) return
    if (this.draft.isUnchanged(partialText)) return
    try {
      await (this.ctx.adapter as WecomAdapter).replyStreamDraft(this.ctx.chatId, partialText)
    } catch { /* ignore stream errors during draft */ }
  }

  async onFinal(text: string): Promise<void> {
    // 行 691-712
    const adapter = this.ctx.adapter as WecomAdapter
    const { cards, remainingText } = extractTemplateCards(text)
    for (const card of cards) {
      try {
        await this.ctx.delivery.deliver(adapter, this.ctx.chatId, '', { templateCard: card, skipDedup: true })
      } catch (err) {
        console.warn('[WecomStreamRenderer] template card delivery failed:', err instanceof Error ? err.message : err)
      }
    }
    const finalText = remainingText || (cards.length > 0 ? '📋 卡片消息已发送。' : '')
    if (finalText) {
      const result = await adapter.replyStreamFinal(this.ctx.chatId, finalText)
      if (result === 'error') {
        // 行 703-708：仅 error 才 fallback（stream/fallback/failed 已发送，不重复）
        console.warn('[WecomStreamRenderer] replyStreamFinal returned error, falling back to text')
        await this.ctx.delivery.deliver(adapter, this.ctx.chatId, finalText, { skipDedup: true })
      }
    }
  }

  async abort(reason: 'abort' | 'error', errorMsg: string): Promise<void> {
    // 行 813-825：replyStreamFinal 已发送错误，bridge catch 对企微不再发（行 839）
    const adapter = this.ctx.adapter as WecomAdapter
    const errorText = reason === 'abort' ? '⏱ 请求超时或已取消' : `❌ Error: ${errorMsg}`
    try {
      const result = await adapter.replyStreamFinal(this.ctx.chatId, errorText)
      if (result === 'error') {
        console.warn('[WecomStreamRenderer] replyStreamFinal error handler failed, sending via delivery')
        await this.ctx.delivery.deliver(adapter, this.ctx.chatId, errorText, { skipDedup: true })
      }
    } catch { /* best effort — bridge catch 对企微不再发，避免重复 */ }
  }

  destroy(): void {
    // 行 852-854：清理 active frame
    ;(this.ctx.adapter as WecomAdapter).cleanupActiveFrame(this.ctx.chatId)
  }
}
