package web_console

import (
	"bytes"
	"fmt"
	"io"
	"testing"
)

type chunkReader struct {
	buf   []byte
	chunk int
}

func (r *chunkReader) Read(p []byte) (int, error) {
	if len(r.buf) == 0 {
		return 0, io.EOF
	}
	if r.chunk <= 0 {
		return 0, fmt.Errorf("invalid chunk size: %d", r.chunk)
	}
	if len(p) > r.chunk {
		p = p[:r.chunk]
	}
	n := copy(p, r.buf)
	r.buf = r.buf[n:]
	return n, nil
}

func TestParseWindowSizeControlMessage_OKWithFragmentedReads(t *testing.T) {
	r := &chunkReader{buf: []byte("1:{\"high\":24,\"width\":80}"), chunk: 1}

	var size windowSize
	ok, err := parseWindowSizeControlMessage(r, &size)
	if err != nil {
		t.Fatalf("parseWindowSizeControlMessage: %v", err)
	}
	if !ok {
		t.Fatalf("expected ok=true")
	}
	if size.High != 24 || size.Width != 80 {
		t.Fatalf("unexpected size: %+v", size)
	}
}

func TestParseWindowSizeControlMessage_IgnoresShortMessageAndDrains(t *testing.T) {
	r := bytes.NewReader([]byte("1"))

	var size windowSize
	ok, err := parseWindowSizeControlMessage(r, &size)
	if err != nil {
		t.Fatalf("parseWindowSizeControlMessage: %v", err)
	}
	if ok {
		t.Fatalf("expected ok=false")
	}
	if r.Len() != 0 {
		t.Fatalf("expected reader to be drained, remaining=%d", r.Len())
	}
}

func TestParseWindowSizeControlMessage_IgnoresWrongPrefixAndDrains(t *testing.T) {
	r := bytes.NewReader([]byte("2:{\"high\":24,\"width\":80}"))

	var size windowSize
	ok, err := parseWindowSizeControlMessage(r, &size)
	if err != nil {
		t.Fatalf("parseWindowSizeControlMessage: %v", err)
	}
	if ok {
		t.Fatalf("expected ok=false")
	}
	if r.Len() != 0 {
		t.Fatalf("expected reader to be drained, remaining=%d", r.Len())
	}
}

func TestParseWindowSizeControlMessage_RejectsTrailingData(t *testing.T) {
	r := bytes.NewReader([]byte("1:{\"high\":24,\"width\":80}{}"))

	var size windowSize
	_, err := parseWindowSizeControlMessage(r, &size)
	if err == nil {
		t.Fatalf("expected error")
	}
}

func TestParseWindowSizeControlMessage_RejectsOutOfRange(t *testing.T) {
	r := bytes.NewReader([]byte(fmt.Sprintf("1:{\"high\":%d,\"width\":80}", maxTerminalRows+1)))

	var size windowSize
	_, err := parseWindowSizeControlMessage(r, &size)
	if err == nil {
		t.Fatalf("expected error")
	}
}
