package eino

import (
	"context"
	"time"

	"github.com/cloudwego/eino/compose"

	"github.com/hhs/camtalk/internal/models"
	"github.com/hhs/camtalk/internal/trace"
)

// ctxKeyStartTime 请求开始时间的 context key。
type ctxKeyStartTime struct{}

// WithStartTime 将请求开始时间注入 context。
func WithStartTime(ctx context.Context, t time.Time) context.Context {
	return context.WithValue(ctx, ctxKeyStartTime{}, t)
}

// latencyFromCtx 从 context 获取开始时间并计算延迟（毫秒）。
func latencyFromCtx(ctx context.Context) int64 {
	if startTime, ok := ctx.Value(ctxKeyStartTime{}).(time.Time); ok {
		return time.Since(startTime).Milliseconds()
	}
	return 0
}

// NewDoneLambda 创建 Done Lambda 节点。
// 输入: struct{}（TTS 完成信号）→ 输出: *PipelineOutput
//
// 从 PipelineState 读取完整回复和 token 用量，发送 llm_done 到客户端。
// 历史消息追加由适配器负责（避免重复写入）。
func NewDoneLambda(defaultModel string) *compose.Lambda {
	return compose.InvokableLambda(func(ctx context.Context, _ struct{}) (PipelineOutput, error) {
		log := trace.FromContext(ctx)
		sender := senderFromCtx(ctx)
		state := stateFromCtx(ctx)

		if state == nil {
			return PipelineOutput{}, nil
		}

		state.mu.Lock()
		fullResponse := state.FullResponse.String()
		transcribedText := state.TranscribedText
		tokenUsage := state.TokenUsage
		requestID := state.RequestID
		modelName := defaultModel
		state.mu.Unlock()

		// 发送 llm_done
		if sender != nil && requestID != "" {
			done := models.WsLLMDone{
				Type:      "llm_done",
				RequestID: requestID,
				FullText:  fullResponse,
				Model:     modelName,
				LatencyMs: latencyFromCtx(ctx),
			}
			if tokenUsage != nil {
				done.TokensUsed = struct {
					Prompt     int `json:"prompt"`
					Completion int `json:"completion"`
					Total      int `json:"total"`
				}{
					Prompt:     tokenUsage.Prompt,
					Completion: tokenUsage.Completion,
					Total:      tokenUsage.Total,
				}
			}
			if err := sender.SendLLMDone(done); err != nil {
				log.Errorw("send llm_done failed", "error", err)
			}
		}

		log.Infow("query processing completed", "response_length", len(fullResponse))

		return PipelineOutput{
			TranscribedText: transcribedText,
			FullResponse:    fullResponse,
			Model:           modelName,
			TokenUsage:      tokenUsage,
		}, nil
	})
}
