package app

import (
	"fmt"
	"net"
	"proxy-server/gateway/core"
	"proxy-server/utils"
	"sync"
)

type Stoppable interface {
	Stop()
}

var (
	Id             int32
	Name           string
	PlatformSecret string // 平台密钥，验证接收的请求是否属于平台

	Edges   = core.SyncMap[int32, *core.Edge]{} // 节点信息表		（包外只读！数据存储有关联性，所有写入操作只在包内进行）
	Assigns = core.SyncMap[uint16, int32]{}     // 分配索引		（包外只读！数据存储有关联性，所有写入操作只在包内进行）

	Permits = core.SyncMap[int32, *core.Permit]{} // 节点权限表	（包外只读！数据存储有关联性，所有写入操作只在包内进行）

	CtrlConnWg  utils.CountWaitGroup             // 控制通道计数器
	DataConnWg  utils.CountWaitGroup             // 数据通道计数器
	FwdLesWg    utils.CountWaitGroup             // 转发监听端口计数器
	UserConnWg  utils.CountWaitGroup             // 用户连接计数器
	UserConnMap core.SyncMap[string, *core.Conn] // 用户连接暂存

	LockPortAssign = sync.Mutex{}               // 锁定端口分配，防止并发冲突
	EdgeUpdates    = make(chan *core.Edge, 100) // 节点更新通知通道
)

func OnlineEdgeNew(id int32, port uint16, addr *net.TCPAddr) error {
	if addr == nil {
		return fmt.Errorf("边缘节点 %d 地址无效", id)
	}
	info, err := IpGeo(addr.IP)
	if err != nil {
		return fmt.Errorf("查询 geo 信息失败：%w", err)
	}

	var host = addr.IP.String()
	var edge = &core.Edge{
		Id:     id,
		Host:   &host,
		Port:   &port,
		Prov:   &info.Prov,
		City:   &info.City,
		Isp:    &info.Isp,
		Status: &core.EdgeOnline,
	}

	Edges.Store(id, edge)
	Assigns.Store(port, id)
	EdgeUpdates <- edge

	return nil
}

func OnlineEdgeUpdate(id int32, addr *net.TCPAddr) error {
	if addr == nil {
		return fmt.Errorf("边缘节点 %d 地址无效", id)
	}
	edge, ok := Edges.Load(id)
	if !ok {
		return fmt.Errorf("边缘节点 %d 不存在", id)
	}

	edge.Status = &core.EdgeOnline
	toUpdate := &core.Edge{
		Id:     edge.Id,
		Status: &core.EdgeOnline,
	}

	host := addr.IP.String()
	if edge.Host == nil || *edge.Host != host {
		edge.Host = &host
		toUpdate.Host = &host
	}

	EdgeUpdates <- toUpdate

	return nil
}

func OfflineEdge(id int32) error {
	edge, ok := Edges.Load(id)
	if !ok || edge == nil {
		return fmt.Errorf("边缘节点 %d 不存在", id)
	}

	edge.Status = &core.EdgeOffline
	EdgeUpdates <- &core.Edge{
		Id:     id,
		Status: &core.EdgeOffline,
	}

	return nil
}

func StoreEdge(edge *core.Edge) error {
	if edge == nil || edge.Id == 0 {
		return fmt.Errorf("无效的边缘节点: %+v", edge)
	}

	Edges.Store(edge.Id, edge)
	if edge.Port != nil {
		Assigns.Store(*edge.Port, edge.Id)
	}
	return nil
}

func LoadPermit(port uint16) *core.Permit {
	id, ok := Assigns.Load(port)
	if !ok {
		return nil
	}

	permit, ok := Permits.Load(id)
	if !ok {
		return nil
	}

	return permit
}

func StorePermit(def *core.PermitDef) {
	Permits.Store(def.Id, &def.Permit)
}
