package twt_avro_test

import (
	"bytes"
	_ "embed"
	"encoding/base64"
	"fmt"
	"log"
	"os"
	"testing"
	"time"

	"github.com/davecgh/go-spew/spew"
	twt_avro "go.sour.is/lextwt-encoding/twt-avro"
	"go.yarn.social/lextwt"
	"go.yarn.social/types"
)

func TestMarshal(t *testing.T) {
	twt_avro.Register()

	ts := must(time.Parse(time.RFC3339, "2021-01-24T02:19:54Z"))
	zone, offset := ts.Zone()
	in := twt_avro.Twt{
		Nick:          "xuu",
		URI:           "https://xuu.txt",
		Created:       ts.UnixMilli(),
		CreatedZone:   zone,
		CreatedOffset: offset,
		Msg: twt_avro.Msg(
			twt_avro.Elem(twt_avro.Subject{
				Subject: "foobar",
			}),
			twt_avro.Elem("foo"),
			twt_avro.Elem(twt_avro.Code{
				Code: "baz",
			}),
		),
	}

	data, err := in.Marshal()
	if err != nil {
		log.Fatal("marshal: ", err)
	}

	fmt.Println(data)
	// Outputs: [54 6 102 111 111]

	out := twt_avro.Twt{}
	err = out.Unmarshal(data)
	if err != nil {
		log.Fatal("unmarshal: ", err)
	}

	fmt.Printf("%#v", out)
	// Outputs: {27 foo}
}

func must[T any](t T, err error) T {
	if err != nil {
		var zero T
		return zero
	}
	return t
}

func TestFromTwt(t *testing.T) {
	twt_avro.Register()

	tests := []struct {
		in    string
		twter *types.Twter
	}{
		{
			in:    "2021-01-24T02:19:54-07:00	(#asdf1234) @xuu This is a `twt`!\u2028Next Line!",
			twter: &types.Twter{Nick: "xuu@sour.is", URI: "https://xuu.txt"},
		},
		{
			in:    "2021-01-24T02:19:54-07:00	!xuu <https://xuu.txt> #lol [lang=en]",
			twter: &types.Twter{Nick: "xuu@sour.is", URI: "https://xuu.txt"},
		},
	}

	for _, test := range tests {
		twt, err := lextwt.ParseLine(test.in, test.twter)
		if err != nil {
			log.Fatal(err)
		}

		av := twt_avro.FromTwt(twt)

		b, err := av.Marshal()
		if err != nil {
			log.Fatal(err)
		}

		t.Log(enc(b))

		out := twt_avro.Twt{}
		err = out.Unmarshal(b)
		if err != nil {
			log.Fatal(err)
		}

		t.Log(spew.Sdump(out))

		outlx := out.ToLextwt()

		outText := fmt.Sprintf("%+l", outlx)
		t.Log(outText)
		if outText != test.in {
			t.Errorf("\nexpected %s\n  got    %s", test.in, outText)
		}
		t.Log(spew.Sdump(outlx.Elems()))
	}
}

var enc = base64.RawStdEncoding.EncodeToString

//go:embed example.txt
var input []byte

func TestEncodeRegistry(t *testing.T) {
	twt_avro.Register()

	registry, err := lextwt.ParseRegistry(bytes.NewReader(input))
	if err != nil {
		log.Fatal(err)
	}

	b, err := twt_avro.EncodeRegistry(registry)
	if err != nil {
		log.Fatal(err)
	}

	t.Log(enc(b))

	out, err := twt_avro.DecodeRegistry(b)
	if err != nil {
		log.Fatal(err)
	}

	out.WriteTo(os.Stdout)
}
