// Package lua 提供 Lua 中间件配置
package lua

import (
	"fmt"
	"time"
)

// MiddlewareConfig Lua 中间件配置（配置文件格式）
type MiddlewareConfig struct {
	Scripts        []ScriptConfig    `yaml:"scripts"`
	GlobalSettings GlobalLuaSettings `yaml:"global_settings"`
	Enabled        bool              `yaml:"enabled"`
}

// ScriptConfig 单个脚本配置
type ScriptConfig struct {
	// Path 脚本路径
	Path string `yaml:"path"`

	// Phase 执行阶段
	// 可选值：rewrite、access、content、log、header_filter、body_filter
	Phase string `yaml:"phase"`

	// Timeout 执行超时
	Timeout time.Duration `yaml:"timeout"`

	// Enabled 是否启用此脚本（默认 true）
	Enabled bool `yaml:"enabled"`
}

// GlobalLuaSettings 全局 Lua 设置
type GlobalLuaSettings struct {
	// MaxConcurrentCoroutines 最大并发协程数
	MaxConcurrentCoroutines int `yaml:"max_concurrent_coroutines"`

	// CoroutineTimeout 协程执行超时
	CoroutineTimeout time.Duration `yaml:"coroutine_timeout"`

	// CodeCacheSize 字节码缓存条目数
	CodeCacheSize int `yaml:"code_cache_size"`

	// MaxExecutionTime 单脚本最大执行时间
	MaxExecutionTime time.Duration `yaml:"max_execution_time"`

	// CoroutineStackSize 协程栈大小（默认64，最大256）
	// 较小的栈减少内存分配，适用于简单脚本
	CoroutineStackSize int `yaml:"coroutine_stack_size"`

	// CoroutinePoolWarmup 协程池预热数量，启动时预创建
	CoroutinePoolWarmup int `yaml:"coroutine_pool_warmup"`

	// EnableFileWatch 启用文件变更检测
	EnableFileWatch bool `yaml:"enable_file_watch"`

	// MinimizeStackMemory 启用栈内存自动收缩以减少内存占用
	MinimizeStackMemory bool `yaml:"minimize_stack_memory"`
}

// DefaultMiddlewareConfig 默认 Lua 中间件配置
func DefaultMiddlewareConfig() *MiddlewareConfig {
	return &MiddlewareConfig{
		Enabled: false,
		Scripts: []ScriptConfig{},
		GlobalSettings: GlobalLuaSettings{
			MaxConcurrentCoroutines: 1000,
			CoroutineTimeout:        30 * time.Second,
			CodeCacheSize:           1000,
			EnableFileWatch:         true,
			MaxExecutionTime:        30 * time.Second,
		},
	}
}

// Validate 验证 Lua 中间件配置
func (c *MiddlewareConfig) Validate() error {
	if !c.Enabled {
		return nil
	}

	// 验证脚本配置
	for i, script := range c.Scripts {
		if script.Path == "" {
			return fmt.Errorf("scripts[%d].path is required", i)
		}

		// 验证 Phase 值
		if err := validatePhase(script.Phase); err != nil {
			return fmt.Errorf("scripts[%d]: %w", i, err)
		}

		// 验证超时时间
		if script.Timeout > 0 && script.Timeout < time.Second {
			return fmt.Errorf("scripts[%d].timeout must be at least 1s", i)
		}
	}

	// 验证全局设置
	if c.GlobalSettings.MaxConcurrentCoroutines < 1 {
		return fmt.Errorf("global_settings.max_concurrent_coroutines must be at least 1")
	}

	if c.GlobalSettings.CoroutineTimeout > 0 && c.GlobalSettings.CoroutineTimeout < time.Second {
		return fmt.Errorf("global_settings.coroutine_timeout must be at least 1s")
	}

	return nil
}

// validatePhase 验证阶段值
func validatePhase(phase string) error {
	if phase == "" {
		return fmt.Errorf("phase is required")
	}

	validPhases := map[string]bool{
		"rewrite":       true,
		"access":        true,
		"content":       true,
		"log":           true,
		"header_filter": true,
		"body_filter":   true,
	}

	if !validPhases[phase] {
		return fmt.Errorf("invalid phase '%s', must be one of: rewrite, access, content, log, header_filter, body_filter", phase)
	}

	return nil
}

// ParsePhase 将字符串转换为 Phase 常量
func ParsePhase(s string) (Phase, error) {
	switch s {
	case "rewrite":
		return PhaseRewrite, nil
	case "access":
		return PhaseAccess, nil
	case "content":
		return PhaseContent, nil
	case "log":
		return PhaseLog, nil
	case "header_filter":
		return PhaseHeaderFilter, nil
	case "body_filter":
		return PhaseBodyFilter, nil
	default:
		return PhaseInit, fmt.Errorf("unknown phase: %s", s)
	}
}

// ToEngineConfig 将全局设置转换为引擎配置
func (s *GlobalLuaSettings) ToEngineConfig() *Config {
	cfg := &Config{
		MaxConcurrentCoroutines: s.MaxConcurrentCoroutines,
		CoroutineTimeout:        s.CoroutineTimeout,
		CodeCacheSize:           s.CodeCacheSize,
		CodeCacheTTL:            time.Hour, // 默认值
		EnableFileWatch:         s.EnableFileWatch,
		MaxExecutionTime:        s.MaxExecutionTime,
		EnableOSLib:             false, // 安全默认值
		EnableIOLib:             false,
		EnableLoadLib:           false,
	}

	// 设置协程栈优化选项
	if s.CoroutineStackSize > 0 {
		cfg.CoroutineStackSize = s.CoroutineStackSize
	} else {
		cfg.CoroutineStackSize = 64 // 默认优化值
	}

	// 设置栈内存优化选项
	cfg.MinimizeStackMemory = s.MinimizeStackMemory

	// 设置协程池预热
	if s.CoroutinePoolWarmup > 0 {
		cfg.CoroutinePoolWarmup = s.CoroutinePoolWarmup
	} else {
		cfg.CoroutinePoolWarmup = 4 // 默认预热数量
	}

	return cfg
}
