// Package ristypes defines the data structures for RIS Live BGP messages and announcements.
package ristypes

import (
	"encoding/json"
	"time"
)

// ASPath represents a BGP AS path as a slice of AS numbers.
// It handles JSON unmarshaling of both simple arrays and nested AS sets,
// flattening any nested structures into a single sequence of AS numbers.
type ASPath []int

// UnmarshalJSON implements the json.Unmarshaler interface for ASPath.
// It handles both simple integer arrays [1, 2, 3] and nested AS sets
// like [1, [2, 3], 4], flattening them into a single slice of integers.
func (p *ASPath) UnmarshalJSON(data []byte) error {
	// First try to unmarshal as a simple array of integers
	var simple []int
	if err := json.Unmarshal(data, &simple); err == nil {
		*p = ASPath(simple)

		return nil
	}

	// If that fails, unmarshal as array of interfaces and flatten
	var raw []interface{}
	if err := json.Unmarshal(data, &raw); err != nil {
		return err
	}

	// Flatten the array
	result := make([]int, 0)
	for _, item := range raw {
		switch v := item.(type) {
		case float64:
			result = append(result, int(v))
		case []interface{}:
			// Nested array - flatten it
			for _, nested := range v {
				if num, ok := nested.(float64); ok {
					result = append(result, int(num))
				}
			}
		}
	}

	*p = ASPath(result)

	return nil
}

// RISLiveMessage represents the outer wrapper message from the RIPE RIS Live stream.
// Each message contains a Type field indicating the message type and a Data field
// containing the actual BGP message payload.
type RISLiveMessage struct {
	Type string     `json:"type"`
	Data RISMessage `json:"data"`
}

// RISMessage represents a BGP update message from the RIPE RIS Live stream.
// It contains metadata about the BGP session (peer, ASN, host) along with
// the actual BGP update data including AS path, communities, announcements,
// and withdrawals.
type RISMessage struct {
	Type            string            `json:"type"`
	Timestamp       float64           `json:"timestamp"`
	ParsedTimestamp time.Time         `json:"-"` // Parsed from Timestamp field
	Peer            string            `json:"peer"`
	PeerASN         string            `json:"peer_asn"`
	ID              string            `json:"id"`
	Host            string            `json:"host"`
	RRC             string            `json:"rrc,omitempty"`
	MrtTime         float64           `json:"mrt_time,omitempty"`
	SocketTime      float64           `json:"socket_time,omitempty"`
	Path            ASPath            `json:"path,omitempty"`
	Community       [][]int           `json:"community,omitempty"`
	Origin          string            `json:"origin,omitempty"`
	MED             *int              `json:"med,omitempty"`
	LocalPref       *int              `json:"local_pref,omitempty"`
	Announcements   []RISAnnouncement `json:"announcements,omitempty"`
	Withdrawals     []string          `json:"withdrawals,omitempty"`
	Raw             string            `json:"raw,omitempty"`
}

// RISAnnouncement represents a BGP route announcement within a RIS message.
// It contains the next hop IP address and the list of prefixes being announced
// via that next hop.
type RISAnnouncement struct {
	NextHop  string   `json:"next_hop"`
	Prefixes []string `json:"prefixes"`
}
