package feichibridge

import (
	"context"
	"net"
	"path/filepath"
	"sync"
	"testing"
	"time"
)

func TestTargetLogsInAndWaitsForACK(t *testing.T) {
	listener, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	defer listener.Close()
	var commands []byte
	var mu sync.Mutex
	done := make(chan error, 1)
	go func() {
		conn, acceptErr := listener.Accept()
		if acceptErr != nil {
			done <- acceptErr
			return
		}
		defer conn.Close()
		for count := 0; count < 2; count++ {
			frame, readErr := readFrame(conn)
			if readErr != nil {
				done <- readErr
				return
			}
			mu.Lock()
			commands = append(commands, frame[2])
			mu.Unlock()
			body := []byte(nil)
			if len(frame) >= 31 {
				body = append(body, frame[24:30]...)
			}
			ack, buildErr := buildFrame('#', frame[2], 0x01, string(frame[4:21]), body)
			if buildErr != nil {
				done <- buildErr
				return
			}
			if writeErr := writeFull(conn, ack); writeErr != nil {
				done <- writeErr
				return
			}
		}
		done <- nil
	}()

	store, err := OpenStateStore(filepath.Join(t.TempDir(), "state.json"))
	if err != nil {
		t.Fatal(err)
	}
	target, err := NewTarget(TargetConfig{
		Address: listener.Addr().String(), PlatformID: "FEICHIBRIDGE00001",
		Username: "bridge", Password: "secret", Timeout: time.Second,
	}, store)
	if err != nil {
		t.Fatal(err)
	}
	frame, err := (Encoder{}).DataFrame(CommandRealtime, "LTEST32960VIN0001", time.Now(), Record{"2201": "1"})
	if err != nil {
		t.Fatal(err)
	}
	if err := target.Send(context.Background(), frame); err != nil {
		t.Fatal(err)
	}
	if err := <-done; err != nil {
		t.Fatal(err)
	}
	mu.Lock()
	defer mu.Unlock()
	if len(commands) != 2 || commands[0] != CommandLogin || commands[1] != CommandRealtime {
		t.Fatalf("commands = %x", commands)
	}
	if target.LastACK().IsZero() {
		t.Fatal("last ACK was not recorded")
	}
}
