package syslog_test

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"log/slog"
	"net"
	"net/netip"
	"strconv"
	"strings"
	"time"

	syslog "codeberg.org/git-pages/go-slog-syslog"
)

var currentTime = time.Unix(2524608000, 0)

func Example() {
	address, done := listen()

	strptr := func(s string) *string { return &s }
	handler, err := syslog.NewHandler(&syslog.HandlerOptions{
		Address:          address,
		Hostname:         strptr("miyuko"),
		AppName:          "catware",
		ProcID:           strptr("1"),
		StructuredDataID: "catware@65535",
	})
	if err != nil {
		panic(err)
	}

	l := slog.New(handler).WithGroup("cat").With("name", nil)

	l = l.With(slog.Group("emotion",
		"mood", "inquisitive",
		"approachable", true,
	))

	l = l.With(slog.Group("social",
		"accepts-pets", true,
	))

	l = l.WithGroup("wake")

	l.Debug(
		"cat waking up",
		"waketime", currentTime,
		"reason", "external-disturbance",
	)

	handler.Flush(1 * time.Second)
	handler.Close()
	<-done
	// Output:
	// <7>1 2050-01-01T00:00:00Z miyuko catware 1 - [catware@65535 cat.emotion.approachable="true" cat.emotion.mood="inquisitive" cat.name="<nil>" cat.social.accepts-pets="true" cat.wake.reason="external-disturbance" cat.wake.waketime="2050-01-01 00:00:00 +0000 UTC"] cat waking up
}

func listen() (address string, done chan struct{}) {
	laddr := netip.MustParseAddrPort("127.0.0.1:0")
	listener, err := net.ListenTCP("tcp", net.TCPAddrFromAddrPort(laddr))
	if err != nil {
		panic(err)
	}

	done = make(chan struct{})
	go func() {
		defer func() { done <- struct{}{} }()
		conn, err := listener.Accept()
		if err != nil {
			panic(err)
		}
		reader := bufio.NewReader(conn)
		for {
			byteCountStr, err := reader.ReadString(' ')
			if errors.Is(err, io.EOF) {
				return
			} else if err != nil {
				panic(err)
			}

			byteCount, err := strconv.Atoi(byteCountStr[:len(byteCountStr)-1])
			if err != nil {
				panic(err)
			}

			msgBytes := make([]byte, byteCount)
			if _, err := io.ReadFull(reader, msgBytes); err != nil {
				panic(err)
			}

			// make the dynamic parts not so dynamic anymore
			msg := string(msgBytes)
			msg = strings.ReplaceAll(msg, "GMT", "UTC")
			sep1 := strings.IndexRune(msg, ' ')
			sep2 := sep1 + strings.IndexRune(msg[sep1+1:], ' ')
			fmt.Printf("%s %s%s\n", msg[:sep1], currentTime.Format(time.RFC3339Nano), msg[sep2+1:])
		}
	}()

	return fmt.Sprintf("tcp/%s", listener.Addr()), done
}
