/**
 * 钉钉 AI Card 流式渲染器 — 从 bridge-manager 钉钉分支迁入（C-2）。
 *
 * 对应原 bridge 行：
 *   onTyping  = 543-556（复用 ctx.preCreatedCard 或 createCard）；
 *   onDraft   = 631-645（throttle）；onFinal = 726-740；abort = 799-808。
 *   delivered = !!card（行 776 hasActiveCard）。
 * queue-busy 预建卡经 ctx.preCreatedCard 传入（bridge 不再持有 activeCards Map）。
 */

import type { DingtalkAdapter } from './adapter'
import type { DingTalkCardInstance } from '../../types'
import type { StreamRenderer, StreamRenderContext } from '../stream-renderer'
import { DraftThrottle } from '../stream-renderer'

export class DingTalkStreamRenderer implements StreamRenderer {
  private card: DingTalkCardInstance | null
  private readonly draft = new DraftThrottle()  // shouldThrottle + isUnchanged

  constructor(private readonly ctx: StreamRenderContext) {
    // 修复问题2：构造时即接管 queue ACK 预建卡，确保 abort 能清理（即使 onTyping 未执行，
    // 如 process 在 query 创建阶段失败）。复刻原 bridge activeCards 在 queue ACK 时即 set 的语义。
    this.card = ctx.preCreatedCard ?? null
  }

  get delivered(): boolean {
    return !!this.card
  }

  async onTyping(): Promise<void> {
    // 行 543-556
    const adapter = this.ctx.adapter as DingtalkAdapter
    this.card = this.ctx.preCreatedCard ?? await adapter.createCard(this.ctx.chatId)
    if (this.card) {
      console.log(`[DingTalkStreamRenderer] AI Card created: ${this.card.cardInstanceId}`)
    } else {
      // 行 555：卡片创建失败 → 文本 indicator
      await this.ctx.delivery.deliver(adapter, this.ctx.chatId, '', { isTypingIndicator: true })
    }
  }

  async onDraft(partialText: string): Promise<void> {
    // 行 631-645（throttle）
    if (!this.card) return  // 行 632 hasActiveCard
    if (this.draft.shouldThrottle()) return  // 行 633
    if (this.draft.isUnchanged(partialText)) return  // 行 634
    try {
      await (this.ctx.adapter as DingtalkAdapter).updateCard(this.card, partialText, false)  // 行 639
    } catch (err) {
      console.warn('[DingTalkStreamRenderer] card stream update failed:', err instanceof Error ? err.message : err)
    }
  }

  async onFinal(text: string): Promise<void> {
    // 行 726-740
    if (this.card) {
      try {
        await (this.ctx.adapter as DingtalkAdapter).finishCard(this.card, text)  // 行 731
        this.card = null  // 行 732
        return  // 行 733：卡片成功，跳过文本
      } catch (err) {
        console.warn('[DingTalkStreamRenderer] card finish failed, falling back to text:', err instanceof Error ? err.message : err)
        this.card = null  // 行 736
        // fall through 到文本投递
      }
    }
    // 行 740：文本投递
    await this.ctx.delivery.deliver(this.ctx.adapter, this.ctx.chatId, text, { skipDedup: true })
  }

  async abort(reason: 'abort' | 'error', errorMsg: string): Promise<void> {
    // 行 799-808
    if (this.card) {
      try {
        const errorText = reason === 'abort' ? '⏱ 请求超时或已取消' : `❌ Error: ${errorMsg}`
        await (this.ctx.adapter as DingtalkAdapter).finishCard(this.card, errorText)
      } catch (cardErr) {
        console.warn('[DingTalkStreamRenderer] card error finish failed:', cardErr instanceof Error ? cardErr.message : cardErr)
      }
      this.card = null
    }
  }
}
