// Package contract 定义 Meshray 开源管理器与闭源 meshray-core 增强层之间的契约。
//
// 本包为开源叶子模块：不依赖管理器（meshray）也不依赖增强层（meshray-core），
// 二者均 import 本包，从而避免 module 级循环依赖。
//
// 设计目标（来自架构决策：多仓解耦 + 编译期注入）：
//   - 管理器默认构建不 import meshray-core，因此可独立编译、以标准 WireGuard 直连运行；
//   - 增强构建（go build -tags meshray_core）空白导入 meshray-core，触发其 init() 把
//     自定义 conn.Bind 工厂与 EngineProvider 注册到本包的全局注册表；
//   - 无 meshray-core 时，GetBindFactory(false) 返回 wireguard-go 默认 Bind（原生直连），
//     NewEngineController 返回 ErrCoreNotAvailable（增强模式优雅降级）。
package contract

import (
	"errors"

	"go.uber.org/zap"
	"golang.zx2c4.com/wireguard/conn"
)

// ===== 候选地址与传输层 =====

// Candidate 对端候选地址（由信令层经 meshray-core 转发下发）
type Candidate struct {
	Addr     string `json:"addr"`     // 候选地址（ip:port）
	Type     string `json:"type"`     // 候选类型：host/srflx/relay
	Priority int    `json:"priority"` // 优先级
	Protocol string `json:"protocol"` // 协议：udp/tcp
}

// Layer 传输层类型（9 层策略），数值与 meshray-core 内部 connect.Layer 对齐
type Layer int

const (
	LayerDirectUDP Layer = iota
	LayerFakeTCP
	LayerRealTCP
	LayerTURNUDP
	LayerTURNQUIC
	LayerTURNTCP
	LayerTURNTLS
	LayerWebRTC
	LayerWS
	LayerCount
)

// String 实现 Stringer
func (l Layer) String() string {
	switch l {
	case LayerDirectUDP:
		return "Direct-UDP"
	case LayerFakeTCP:
		return "Direct-FakeTCP"
	case LayerRealTCP:
		return "Direct-RealTCP"
	case LayerTURNUDP:
		return "TURN-UDP"
	case LayerTURNQUIC:
		return "TURN-QUIC"
	case LayerTURNTCP:
		return "TURN-TCP"
	case LayerTURNTLS:
		return "TURN-TLS"
	case LayerWebRTC:
		return "WebRTC"
	case LayerWS:
		return "WS/WSS"
	default:
		return "Unknown"
	}
}

// DefaultLayerOrder 默认优先级顺序（从最优到兜底）
var DefaultLayerOrder = []Layer{
	LayerDirectUDP,
	LayerFakeTCP,
	LayerRealTCP,
	LayerTURNUDP,
	LayerTURNQUIC,
	LayerTURNTCP,
	LayerTURNTLS,
	LayerWebRTC,
	LayerWS,
}

// ICEConfig ICE 配置（STUN/TURN 服务器），用于 WebRTC 等传输层
type ICEConfig struct {
	STUNServers []string
	TURNServers []string
}

// ===== 状态 =====

// PeerStatus 单 Peer 状态
type PeerStatus struct {
	PeerKey   string `json:"peer_key"`
	Connected bool   `json:"connected"`
	Layer     string `json:"layer,omitempty"`
}

// EngineStatus 增强引擎状态
type EngineStatus struct {
	PeerCount         int                    `json:"peer_count"`
	Peers             map[string]*PeerStatus `json:"peers"`
	ActiveConnections int64                  `json:"active_connections"`
	TotalConnections  int64                  `json:"total_connections"`
	BytesSent         uint64                 `json:"bytes_sent"`
	BytesReceived     uint64                 `json:"bytes_received"`
	StrategyFallbacks int64                  `json:"strategy_fallbacks"`
	LastSwitchTime    int64                  `json:"last_switch_time"`
}

// ===== 增强引擎控制面契约 =====
//
// EngineController 由 meshray-core 实现，供管理器（开源）在 enhanced 模式调用。
type EngineController interface {
	Start() error
	Stop() error
	// NotifyPeerCandidates 由信令层调用：注入对端候选地址并触发 P2P 建连
	NotifyPeerCandidates(peerKey string, candidates []Candidate) error
	// SetICEConfig 更新 ICE/STUN/TURN 配置
	SetICEConfig(cfg ICEConfig) error
	// SetLayerOrder 设置传输层优先级顺序（策略核心配置）
	SetLayerOrder(order []Layer) error
	// GetStatus 查询引擎状态
	GetStatus() (*EngineStatus, error)
}

// EngineProvider 创建 EngineController 的工厂（由 meshray-core 注册）
type EngineProvider func(networkID string, logger *zap.Logger) (EngineController, error)

var (
	engineProvider  EngineProvider
	errCoreNotAvail = errors.New("meshray-core 未启用：增强模式不可用（仅原生直连可用）")
)

// RegisterEngineProvider 由 meshray-core 在 init 中注册
func RegisterEngineProvider(p EngineProvider) {
	engineProvider = p
}

// EngineProviderRegistered 是否已注册增强引擎提供方
func EngineProviderRegistered() bool {
	return engineProvider != nil
}

// NewEngineController 创建增强引擎；未注册 core 时返回 errCoreNotAvail
func NewEngineController(networkID string, logger *zap.Logger) (EngineController, error) {
	if engineProvider == nil {
		return nil, errCoreNotAvail
	}
	return engineProvider(networkID, logger)
}

// ===== WireGuard conn.Bind 工厂契约 =====
//
// BindFactory 创建接管 WG 收发的 conn.Bind。原生模式用 wireguard-go 默认 Bind；
// 增强模式由 meshray-core 注册自定义 Bind（在 Send/Recv 中插入 9 层传输与打洞）。
type BindFactory func(listenPort int, networkID string, logger *zap.Logger) (conn.Bind, error)

var (
	nativeBindFactory = func(listenPort int, networkID string, logger *zap.Logger) (conn.Bind, error) {
		return conn.NewDefaultBind(), nil
	}
	enhancedBindFactory BindFactory
	errBindNotEnhanced  = errors.New("meshray-core 未启用：enhanced 模式无法创建自定义 Bind")
)

// RegisterEnhancedBindFactory 由 meshray-core 在 init 中注册
func RegisterEnhancedBindFactory(f BindFactory) {
	enhancedBindFactory = f
}

// GetBindFactory 获取 Bind 工厂：
//   - enhanced=true 且已注册 core → 返回 core 的自定义 Bind 工厂；
//   - enhanced=true 但未注册 core → 返回 errBindNotEnhanced；
//   - enhanced=false → 返回 wireguard-go 默认 Bind（原生直连）。
func GetBindFactory(enhanced bool) (BindFactory, error) {
	if enhanced {
		if enhancedBindFactory == nil {
			return nil, errBindNotEnhanced
		}
		return enhancedBindFactory, nil
	}
	return nativeBindFactory, nil
}
