package conversion

import (
	"time"

	"nex/backend/internal/conversion/canonical"

	"github.com/google/uuid"
)

// ConversionMiddleware 转换中间件接口
type ConversionMiddleware interface {
	Intercept(req *canonical.CanonicalRequest, clientProtocol, providerProtocol string, ctx *ConversionContext) (*canonical.CanonicalRequest, error)
	InterceptStreamEvent(event *canonical.CanonicalStreamEvent, clientProtocol, providerProtocol string, ctx *ConversionContext) (*canonical.CanonicalStreamEvent, error)
}

// ConversionContext 转换上下文
type ConversionContext struct {
	ConversionID  string
	InterfaceType InterfaceType
	Timestamp     time.Time
	Metadata      map[string]any
}

// NewConversionContext 创建转换上下文
func NewConversionContext(ifaceType InterfaceType) *ConversionContext {
	return &ConversionContext{
		ConversionID:  uuid.New().String(),
		InterfaceType: ifaceType,
		Timestamp:     time.Now().UTC(),
		Metadata:      make(map[string]any),
	}
}

// MiddlewareChain 中间件链
type MiddlewareChain struct {
	middlewares []ConversionMiddleware
}

// NewMiddlewareChain 创建中间件链
func NewMiddlewareChain() *MiddlewareChain {
	return &MiddlewareChain{
		middlewares: make([]ConversionMiddleware, 0),
	}
}

// Use 添加中间件
func (c *MiddlewareChain) Use(mw ConversionMiddleware) {
	c.middlewares = append(c.middlewares, mw)
}

// Apply 对请求按顺序执行所有中间件
func (c *MiddlewareChain) Apply(req *canonical.CanonicalRequest, clientProtocol, providerProtocol string, ctx *ConversionContext) (*canonical.CanonicalRequest, error) {
	result := req
	for _, mw := range c.middlewares {
		var err error
		result, err = mw.Intercept(result, clientProtocol, providerProtocol, ctx)
		if err != nil {
			return nil, err
		}
	}
	return result, nil
}

// ApplyStreamEvent 对流式事件按顺序执行所有中间件
func (c *MiddlewareChain) ApplyStreamEvent(event *canonical.CanonicalStreamEvent, clientProtocol, providerProtocol string, ctx *ConversionContext) (*canonical.CanonicalStreamEvent, error) {
	result := event
	for _, mw := range c.middlewares {
		var err error
		result, err = mw.InterceptStreamEvent(result, clientProtocol, providerProtocol, ctx)
		if err != nil {
			return nil, err
		}
	}
	return result, nil
}
