package aoiprxkit

import (
	"encoding/binary"
	"errors"
)

type RTPPacket struct {
	Version        uint8
	Padding        bool
	Extension      bool
	CSRCCount      uint8
	Marker         bool
	PayloadType    uint8
	SequenceNumber uint16
	Timestamp      uint32
	SSRC           uint32
	Payload        []byte
}

func ParseRTPPacket(buf []byte) (RTPPacket, error) {
	if len(buf) < 12 {
		return RTPPacket{}, errors.New("RTP packet too short")
	}
	b0 := buf[0]
	b1 := buf[1]
	p := RTPPacket{
		Version:        b0 >> 6,
		Padding:        (b0 & 0x20) != 0,
		Extension:      (b0 & 0x10) != 0,
		CSRCCount:      b0 & 0x0F,
		Marker:         (b1 & 0x80) != 0,
		PayloadType:    b1 & 0x7F,
		SequenceNumber: binary.BigEndian.Uint16(buf[2:4]),
		Timestamp:      binary.BigEndian.Uint32(buf[4:8]),
		SSRC:           binary.BigEndian.Uint32(buf[8:12]),
	}
	if p.Version != 2 {
		return RTPPacket{}, errors.New("unsupported RTP version")
	}
	headerLen := 12 + int(p.CSRCCount)*4
	if len(buf) < headerLen {
		return RTPPacket{}, errors.New("RTP packet too short for CSRC list")
	}
	if p.Extension {
		if len(buf) < headerLen+4 {
			return RTPPacket{}, errors.New("RTP packet too short for extension")
		}
		extLenWords := int(binary.BigEndian.Uint16(buf[headerLen+2 : headerLen+4]))
		headerLen += 4 + extLenWords*4
		if len(buf) < headerLen {
			return RTPPacket{}, errors.New("RTP packet too short for full extension")
		}
	}
	payload := buf[headerLen:]
	if p.Padding {
		if len(payload) == 0 {
			return RTPPacket{}, errors.New("RTP packet has invalid padding")
		}
		padLen := int(payload[len(payload)-1])
		if padLen <= 0 || padLen > len(payload) {
			return RTPPacket{}, errors.New("RTP packet has invalid pad length")
		}
		payload = payload[:len(payload)-padLen]
	}
	// ALIASING FIX: copy payload bytes before returning. The caller reuses
	// the receive buffer on every ReadFromUDP call, so any RTPPacket stored
	// in the jitter buffer for later delivery would have its Payload slice
	// silently overwritten by the next incoming packet.
	p.Payload = append([]byte(nil), payload...)
	return p, nil
}
