package panel

import (
	"github.com/goccy/go-json"
	"regexp"
	"strconv"
	"strings"
)

type NodeInfo struct {
	Host            string            `json:"host"`
	ServerPort      int               `json:"server_port"`
	ServerName      string            `json:"server_name"`
	Network         string            `json:"network"`
	NetworkSettings json.RawMessage   `json:"networkSettings"`
	Cipher          string            `json:"cipher"`
	ServerKey       string            `json:"server_key"`
	Tls             int               `json:"tls"`
	Routes          []Route           `json:"routes"`
	BaseConfig      *BaseConfig       `json:"base_config"`
	Rules           []DestinationRule `json:"-"`
	localNodeConfig `json:"-"`
}
type Route struct {
	Id     int         `json:"id"`
	Match  interface{} `json:"match"`
	Action string      `json:"action"`
	//ActionValue interface{} `json:"action_value"`
}
type BaseConfig struct {
	PushInterval any `json:"push_interval"`
	PullInterval any `json:"pull_interval"`
}
type DestinationRule struct {
	ID      int
	Pattern *regexp.Regexp
}
type localNodeConfig struct {
	NodeId      int
	NodeType    string
	TLSType     string
	EnableVless bool
	EnableTls   bool
	SpeedLimit  int
	DeviceLimit int
}

func (c *Client) GetNodeInfo() (nodeInfo *NodeInfo, err error) {
	const path = "/api/v1/server/UniProxy/config"
	r, err := c.client.R().Get(path)
	if err = c.checkResponse(r, path, err); err != nil {
		return
	}
	err = json.Unmarshal(r.Body(), &nodeInfo)
	if err != nil {
		return
	}
	if c.etag == r.Header().Get("ETag") { // node info not changed
		return nil, nil
	}
	nodeInfo.NodeId = c.NodeId
	nodeInfo.NodeType = c.NodeType
	for i := range nodeInfo.Routes { // parse rules from routes
		if nodeInfo.Routes[i].Action == "block" {
			var matchs []string
			if _, ok := nodeInfo.Routes[i].Match.(string); ok {
				matchs = strings.Split(nodeInfo.Routes[i].Match.(string), ",")
			} else {
				matchs = nodeInfo.Routes[i].Match.([]string)
			}
			for _, v := range matchs {
				nodeInfo.Rules = append(nodeInfo.Rules, DestinationRule{
					ID:      nodeInfo.Routes[i].Id,
					Pattern: regexp.MustCompile(v),
				})
			}
		}
	}
	nodeInfo.Routes = nil
	if _, ok := nodeInfo.BaseConfig.PullInterval.(int); !ok {
		i, _ := strconv.Atoi(nodeInfo.BaseConfig.PullInterval.(string))
		nodeInfo.BaseConfig.PullInterval = i
	}
	if _, ok := nodeInfo.BaseConfig.PushInterval.(int); !ok {
		i, _ := strconv.Atoi(nodeInfo.BaseConfig.PushInterval.(string))
		nodeInfo.BaseConfig.PushInterval = i
	}
	c.etag = r.Header().Get("Etag")
	return
}