package core

import (
	"fmt"
	"sync"

	"go.uber.org/zap"
)

// Core 进程入口 - 管理多个 Engine 实例
type Core struct {
	engines map[string]*Engine // engineID -> Engine
	mu      sync.RWMutex
	logger  *zap.Logger
}

// NewCore 创建 Core 实例（进程入口）
func NewCore(logger *zap.Logger) *Core {
	return &Core{
		engines: make(map[string]*Engine),
		logger:  logger,
	}
}

// CreateEngine 创建 Engine 实例
func (c *Core) CreateEngine(engineID string, metrics *Metrics) (*Engine, error) {
	c.mu.Lock()
	defer c.mu.Unlock()

	// 检查是否已存在
	if _, ok := c.engines[engineID]; ok {
		return nil, fmt.Errorf("engine %s already exists", engineID)
	}

	// 创建新 Engine
	engine := NewEngine(c.logger, metrics)
	c.engines[engineID] = engine

	c.logger.Info("创建 Engine 实例",
		zap.String("engine_id", engineID))

	return engine, nil
}

// GetEngine 获取 Engine 实例
func (c *Core) GetEngine(engineID string) (*Engine, error) {
	c.mu.RLock()
	defer c.mu.RUnlock()

	engine, ok := c.engines[engineID]
	if !ok {
		return nil, fmt.Errorf("engine %s not found", engineID)
	}

	return engine, nil
}

// RemoveEngine 移除 Engine 实例
func (c *Core) RemoveEngine(engineID string) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	engine, ok := c.engines[engineID]
	if !ok {
		return fmt.Errorf("engine %s not found", engineID)
	}

	// 停止 Engine
	if err := engine.Stop(); err != nil {
		c.logger.Warn("停止 Engine 失败",
			zap.String("engine_id", engineID),
			zap.Error(err))
	}

	delete(c.engines, engineID)
	c.logger.Info("移除 Engine 实例",
		zap.String("engine_id", engineID))

	return nil
}

// ListEngines 列出所有 Engine ID
func (c *Core) ListEngines() []string {
	c.mu.RLock()
	defer c.mu.RUnlock()

	ids := make([]string, 0, len(c.engines))
	for id := range c.engines {
		ids = append(ids, id)
	}
	return ids
}

// Count 获取 Engine 数量
func (c *Core) Count() int {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return len(c.engines)
}

// Close 关闭所有 Engine
func (c *Core) Close() error {
	c.mu.Lock()
	defer c.mu.Unlock()

	for id, engine := range c.engines {
		if err := engine.Stop(); err != nil {
			c.logger.Warn("停止 Engine 失败",
				zap.String("engine_id", id),
				zap.Error(err))
		}
	}

	c.engines = make(map[string]*Engine)
	c.logger.Info("关闭所有 Engine")

	return nil
}
