package xray

import (
	"bytes"

	"github.com/mhsanaei/3x-ui/v3/util/json_util"
)

// Config represents the complete Xray configuration structure.
// It contains all sections of an Xray config file including inbounds, outbounds, routing, etc.
type Config struct {
	LogConfig        json_util.RawMessage `json:"log"`
	RouterConfig     json_util.RawMessage `json:"routing"`
	DNSConfig        json_util.RawMessage `json:"dns,omitempty"`
	InboundConfigs   []InboundConfig      `json:"inbounds"`
	OutboundConfigs  json_util.RawMessage `json:"outbounds"`
	Transport        json_util.RawMessage `json:"transport,omitempty"`
	Policy           json_util.RawMessage `json:"policy"`
	API              json_util.RawMessage `json:"api"`
	Stats            json_util.RawMessage `json:"stats"`
	Reverse          json_util.RawMessage `json:"reverse,omitempty"`
	FakeDNS          json_util.RawMessage `json:"fakedns,omitempty"`
	Observatory      json_util.RawMessage `json:"observatory,omitempty"`
	BurstObservatory json_util.RawMessage `json:"burstObservatory,omitempty"`
	Metrics          json_util.RawMessage `json:"metrics"`
}

// Equals compares two Config instances for deep equality.
func (c *Config) Equals(other *Config) bool {
	if len(c.InboundConfigs) != len(other.InboundConfigs) {
		return false
	}
	for i, inbound := range c.InboundConfigs {
		if !inbound.Equals(&other.InboundConfigs[i]) {
			return false
		}
	}
	if !bytes.Equal(c.LogConfig, other.LogConfig) {
		return false
	}
	if !bytes.Equal(c.RouterConfig, other.RouterConfig) {
		return false
	}
	if !bytes.Equal(c.DNSConfig, other.DNSConfig) {
		return false
	}
	if !bytes.Equal(c.OutboundConfigs, other.OutboundConfigs) {
		return false
	}
	if !bytes.Equal(c.Transport, other.Transport) {
		return false
	}
	if !bytes.Equal(c.Policy, other.Policy) {
		return false
	}
	if !bytes.Equal(c.API, other.API) {
		return false
	}
	if !bytes.Equal(c.Stats, other.Stats) {
		return false
	}
	if !bytes.Equal(c.Reverse, other.Reverse) {
		return false
	}
	if !bytes.Equal(c.FakeDNS, other.FakeDNS) {
		return false
	}
	if !bytes.Equal(c.Metrics, other.Metrics) {
		return false
	}
	return true
}
