package ctr

import (
	"fmt"
	"strconv"
	"sync"

	"git.zkcoi.com/zkcoi/meshray/core"
	"git.zkcoi.com/zkcoi/meshray/core/connect"
	"go.uber.org/zap"
)

// Ctr meshray-ctr 调度中心
type Ctr struct {
	name      string // 组网名称（用于日志）
	networkID uint64 // 组网 ID（雪花算法 ID）
	config    *CtrConfig
	logger    *zap.Logger

	// WireGuard 管理器
	wgManager *WGManager

	// Core 实例（直接集成，无需 gRPC）
	coreInst *core.Core

	mu sync.RWMutex
}

// CtrConfig 配置
type CtrConfig struct {
	// 空配置，保留结构体以备未来扩展
}

// NewCtr 创建调度中心
func NewCtr(name string, networkID uint64, config *CtrConfig, logger *zap.Logger) (*Ctr, error) {
	ctr := &Ctr{
		name:      name,
		networkID: networkID,
		config:    config,
		logger:    logger,
	}

	// 初始化 WireGuard 管理器
	ctr.wgManager = NewWGManager(logger)

	// 初始化 Core 实例（直接集成，无需 gRPC）
	ctr.coreInst = core.NewCore(logger)

	return ctr, nil
}

// Start 启动调度中心
func (c *Ctr) Start() error {
	c.mu.Lock()
	defer c.mu.Unlock()

	c.logger.Info("启动 meshray-ctr",
		zap.String("name", c.name),
		zap.Uint64("network_id", c.networkID))

	// ✅ Watchdog 监控暂不实现（P3 阶段）
	// go c.watchdog.Start()

	return nil
}

// Stop 停止调度中心
func (c *Ctr) Stop() error {
	c.mu.Lock()
	defer c.mu.Unlock()

	c.logger.Info("停止 meshray-ctr",
		zap.Uint64("network_id", c.networkID))

	// 停止 Core 实例（直接调用方法）
	if c.coreInst != nil {
		// ✅ Close 方法已实现（会停止所有 Engine）
		c.coreInst.Close()
	}

	// 停止 WireGuard 管理
	if err := c.wgManager.Stop(); err != nil {
		c.logger.Error("停止 WireGuard 管理失败", zap.Error(err))
	}

	return nil
}

// CreateNetwork 创建网络（根据组网模式决定行为）
// - 原生模式：仅创建 WG 设备
// - 增强模式：创建 WG 设备 + 启动 Core 实例
func (c *Ctr) CreateNetwork(networkID uint64, subnet string, listenPort int, meshMode string) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	c.logger.Info("开始创建网络",
		zap.Uint64("network_id", networkID),
		zap.String("subnet", subnet),
		zap.Int("listen_port", listenPort),
		zap.String("mesh_mode", meshMode))

	// 1. 创建 WireGuard 设备（两种模式都需要）
	networkIDStr := strconv.FormatUint(networkID, 10)
	if err := c.wgManager.CreateDevice(networkIDStr, subnet, listenPort); err != nil {
		return fmt.Errorf("创建 WireGuard 设备失败：%w", err)
	}
	c.logger.Debug("WireGuard 设备创建成功",
		zap.Uint64("network_id", networkID))

	// 2. 仅增强模式需要创建并启动 Core 实例
	if meshMode == "enhanced" {
		// 直接调用 Core 实例的方法（无需 gRPC）
		metrics := core.NewMetrics()
		engine, err := c.coreInst.CreateEngine(networkIDStr, metrics)
		if err != nil {
			c.wgManager.DeleteDevice(networkIDStr) // 回滚 WG设备
			c.logger.Error("创建 Engine 失败",
				zap.Uint64("network_id", networkID),
				zap.Error(err))
			return fmt.Errorf("创建 Engine 失败：%w", err)
		}

		if err := engine.Start(); err != nil {
			// ✅ 调用 Stop 方法停止（会清理所有资源）
			engine.Stop()
			c.wgManager.DeleteDevice(networkIDStr) // 回滚 WG 设备
			c.logger.Error("启动 Engine 失败",
				zap.Uint64("network_id", networkID),
				zap.Error(err))
			return fmt.Errorf("启动 Engine 失败：%w", err)
		}

		c.logger.Info("增强模式：Engine 实例已启动",
			zap.Uint64("network_id", networkID))
	} else {
		c.logger.Info("原生模式：仅创建 WG 设备，不启动 Core",
			zap.Uint64("network_id", networkID))
	}

	c.logger.Info("网络创建成功",
		zap.Uint64("network_id", networkID),
		zap.String("mesh_mode", meshMode))

	return nil
}

// DeleteNetwork 删除网络
func (c *Ctr) DeleteNetwork(networkID uint64) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	c.logger.Info("开始删除网络",
		zap.Uint64("network_id", networkID))

	// 1. Core 实例不需要显式删除（它是内存中的对象）
	// 如果需要清理，可以在未来实现 Engine.Stop() 方法
	networkIDStr := strconv.FormatUint(networkID, 10)

	// 2. 删除 WireGuard 设备
	if err := c.wgManager.DeleteDevice(networkIDStr); err != nil {
		return fmt.Errorf("删除 WireGuard 设备失败：%w", err)
	}

	c.logger.Info("网络删除成功",
		zap.Uint64("network_id", networkID))

	return nil
}

// AddPeer 添加 Peer
func (c *Ctr) AddPeer(networkID uint64, publicKey, allowedIP string) error {
	c.mu.RLock()
	defer c.mu.RUnlock()

	c.logger.Info("添加 Peer",
		zap.Uint64("network_id", networkID),
		zap.String("public_key", publicKey[:8]+"..."))

	// 1. 添加到 WireGuard
	networkIDStr := strconv.FormatUint(networkID, 10)
	if err := c.wgManager.AddPeer(networkIDStr, publicKey, allowedIP); err != nil {
		return fmt.Errorf("添加 Peer 失败：%w", err)
	}

	// 2. 通知 Core
	// 如果已经在 Enhanced 模式，需要接管刚刚加入的这个 Peer
	engine, err := c.coreInst.GetEngine(networkIDStr)
	if err == nil && engine != nil {
		// 引擎存在，说明是 enhanced 模式
		// 由 Core 分配一个本地端口
		localPort, err := engine.Bind(publicKey, 0)
		if err != nil {
			c.logger.Error("增强模式动态 AddPeer Bind 失败", zap.Error(err))
		} else {
			// 通知 WG 更新为本地代理 Endpoint
			newEndpoint := fmt.Sprintf("127.0.0.1:%d", localPort)
			if err := c.wgManager.UpdatePeerEndpoint(networkIDStr, publicKey, newEndpoint); err != nil {
				c.logger.Warn("增强模式自动重写 Endpoint 失败", zap.Error(err))
				engine.Unbind(publicKey)
			} else {
				c.logger.Info("增强模式：动态 Peer 添加并成功代理给 Core",
					zap.String("public_key", publicKey[:8]+"..."),
					zap.String("new_endpoint", newEndpoint))
			}
		}
	} else {
		c.logger.Debug("Core 未启动，普通模式无需代理 Peer", zap.Uint64("network_id", networkID))
	}

	return nil
}

// RemovePeer 移除 Peer
func (c *Ctr) RemovePeer(networkID uint64, publicKey string) error {
	c.mu.RLock()
	defer c.mu.RUnlock()

	c.logger.Info("移除 Peer",
		zap.Uint64("network_id", networkID),
		zap.String("public_key", publicKey[:8]+"..."))

	// 从 WireGuard 移除
	networkIDStr := strconv.FormatUint(networkID, 10)
	if err := c.wgManager.RemovePeer(networkIDStr, publicKey); err != nil {
		return fmt.Errorf("移除 Peer 失败：%w", err)
	}

	// 通知 Core 卸载这台 Peer 的监听
	engine, err := c.coreInst.GetEngine(networkIDStr)
	if err == nil && engine != nil {
		engine.Unbind(publicKey)
		c.logger.Info("增强模式：Core 已解除对该 Peer 的挂载", zap.String("public_key", publicKey[:8]+"..."))
	}

	return nil
}

// SetSTUNTURNConfig 为指定网络设置 STUN/TURN 配置
func (c *Ctr) SetSTUNTURNConfig(networkID uint64, stunServers []string, turnServers []connect.TURNServerConfig) error {
	c.mu.RLock()
	defer c.mu.RUnlock()

	networkIDStr := strconv.FormatUint(networkID, 10)

	// 获取 Engine 实例
	engine, err := c.coreInst.GetEngine(networkIDStr)
	if err != nil {
		c.logger.Debug("网络未启动增强模式，跳过 STUN/TURN 配置",
			zap.Uint64("network_id", networkID))
		return nil // 无需错误，因为原生模式不需要
	}

	// 更新 WebRTC 工厂的 ICE 配置
	engine.SetICEConfig(connect.ICEConfig{
		STUNServers: stunServers,
		TURNServers: turnServers,
	})

	c.logger.Info("STUN/TURN 配置已设置",
		zap.Uint64("network_id", networkID),
		zap.Int("stun_count", len(stunServers)),
		zap.Int("turn_count", len(turnServers)))

	return nil
}
func (c *Ctr) GetStatus(networkID uint64) (*NetworkStatus, error) {
	c.mu.RLock()
	defer c.mu.RUnlock()

	networkIDStr := strconv.FormatUint(networkID, 10)
	status := &NetworkStatus{
		NetworkID: networkIDStr,
	}

	// 获取 WireGuard 状态
	wgStatus, err := c.wgManager.GetStatus(networkIDStr)
	if err != nil {
		return nil, err
	}
	status.WGStatus = wgStatus

	// 获取 Core 状态（直接调用 Engine 的方法）
	engine, err := c.coreInst.GetEngine(networkIDStr)
	if err == nil && engine != nil {
		coreStatus, err := engine.GetStatus()
		if err == nil {
			status.CoreStatus = coreStatus
		}
	}

	return status, nil
}

// SwitchMode 切换传输模式（原生→增强）
// 仅支持 "native" → "enhanced" 单向切换
func (c *Ctr) SwitchMode(networkID uint64, mode string) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	c.logger.Info("开始切换传输模式",
		zap.Uint64("network_id", networkID),
		zap.String("target_mode", mode))

	// 1. 验证目标模式
	if mode != "enhanced" {
		return fmt.Errorf("仅支持切换到 enhanced 模式，当前请求：%s", mode)
	}

	networkIDStr := strconv.FormatUint(networkID, 10)

	// 2. 获取当前 WG 状态（获取 Peer 数量）
	wgStatus, err := c.wgManager.GetStatus(networkIDStr)
	if err != nil {
		return fmt.Errorf("获取 WG 状态失败：%w", err)
	}

	c.logger.Info("获取到 WG 状态",
		zap.Int("peer_count", wgStatus.PeerCount))

	// 3. 创建并启动 Core Engine（增强模式核心）
	metrics := core.NewMetrics()
	engine, err := c.coreInst.CreateEngine(networkIDStr, metrics)
	if err != nil {
		return fmt.Errorf("创建 Core Engine 失败：%w", err)
	}

	if err := engine.Start(); err != nil {
		return fmt.Errorf("启动 Core Engine 失败：%w", err)
	}

	c.logger.Info("Core Engine 已启动",
		zap.Uint64("network_id", networkID))

	// 4. 获取 Peer 列表
	peers, err := c.wgManager.ListPeers(networkIDStr)
	if err != nil {
		return fmt.Errorf("获取 Peer 列表失败：%w", err)
	}

	// 5. 修改 Peer Endpoint → 127.0.0.1:{port}，并且让 Core 绑定
	// 增强模式下，所有 Peer 的 Endpoint 都指向本地回环地址
	for _, peer := range peers {
		// 1. Core 引擎动态接管，传 0 意为让操作系统挑个未占用的随意回环端口
		localPort, err := engine.Bind(peer.PublicKey, 0)
		if err != nil {
			c.logger.Error("Engine Bind 失败",
				zap.String("public_key", peer.PublicKey[:8]+"..."),
				zap.Error(err))
			continue
		}

		newEndpoint := fmt.Sprintf("127.0.0.1:%d", localPort)

		// 2. 将此端口告知 WG 更新 Endpoint
		if err := c.wgManager.UpdatePeerEndpoint(networkIDStr, peer.PublicKey, newEndpoint); err != nil {
			c.logger.Warn("更新 Peer Endpoint 失败",
				zap.String("public_key", peer.PublicKey[:8]+"..."),
				zap.Error(err))

			// 如果更新失败，解绑 Core
			engine.Unbind(peer.PublicKey)
			continue
		}

		c.logger.Info("Peer Endpoint 已成功切换并接入 Core",
			zap.String("public_key", peer.PublicKey[:8]+"..."),
			zap.String("original_endpoint", peer.Endpoint),
			zap.String("new_endpoint", newEndpoint))
	}

	c.logger.Info("传输模式切换成功（基础功能已实现，P3 阶段待完善）",
		zap.Uint64("network_id", networkID),
		zap.String("mode", mode))

	return nil
}

// UpdateCoreConfig 更新 Core 配置（策略修改后同步）
// ✅ P3-1 阶段实现
func (c *Ctr) UpdateCoreConfig(networkID uint64, config interface{}) error {
	c.mu.RLock()
	defer c.mu.RUnlock()

	c.logger.Info("更新 Core 配置",
		zap.Uint64("network_id", networkID))

	// ✅ P3-1 阶段 - 暂不实现
	// 未来实现：
	// 1. 根据策略类型解析配置
	// 2. 调用 Core 的 UpdateConfig 方法
	// 3. 持久化到数据库

	return fmt.Errorf("UpdateCoreConfig 尚未实现（P3-1 阶段）")
}

// GetWGMode 获取系统 WG 模式
func (c *Ctr) GetWGMode() string {
	return c.wgManager.GetWGMode()
}

// NetworkStatus 网络状态
type NetworkStatus struct {
	NetworkID  string             `json:"network_id"`
	WGStatus   *WGStatus          `json:"wg_status"`
	CoreStatus *core.EngineStatus `json:"core_status,omitempty"`
}
