package nsdxml_test

import (
	"bytes"
	"encoding/xml"
	"errors"
	"strings"
	"testing"

	"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/nsdxml"
)

func TestCharmap1251RoundTrip(t *testing.T) {
	cases := []string{
		"",
		"abc",
		"Привет, мир!",
		"Иванов И.И.",
		"АБВГД абвгд",
		"символы: №, ©, ®, «», „текст", // включая cp1251 пунктуацию
	}
	for _, s := range cases {
		s := s
		t.Run(s, func(t *testing.T) {
			enc, err := nsdxml.EncodeWindows1251([]byte(s))
			if err != nil {
				t.Fatalf("EncodeWindows1251: %v", err)
			}
			dec := nsdxml.DecodeWindows1251(enc)
			if string(dec) != s {
				t.Errorf("round-trip разошёлся: %q -> %x -> %q", s, enc, dec)
			}
		})
	}
}

func TestEncodeUnmappable(t *testing.T) {
	_, err := nsdxml.EncodeWindows1251([]byte("эмодзи: 😀"))
	if !errors.Is(err, nsdxml.ErrUnmappable) {
		t.Errorf("ожидалась ErrUnmappable, получено: %v", err)
	}
}

func TestCharsetReader(t *testing.T) {
	src := []byte{0xC8, 0xE2, 0xE0, 0xED, 0xEE, 0xE2} // "Иванов" в windows-1251
	r, err := nsdxml.CharsetReader("windows-1251", bytes.NewReader(src))
	if err != nil {
		t.Fatalf("CharsetReader: %v", err)
	}
	buf := new(bytes.Buffer)
	if _, err := buf.ReadFrom(r); err != nil {
		t.Fatalf("ReadFrom: %v", err)
	}
	if buf.String() != "Иванов" {
		t.Errorf("получено %q, ожидалось %q", buf.String(), "Иванов")
	}
}

func TestCharsetReaderUnknown(t *testing.T) {
	_, err := nsdxml.CharsetReader("koi8-r", bytes.NewReader(nil))
	if err == nil {
		t.Error("ожидалась ошибка для неизвестной кодировки")
	}
}

func TestMarshalUnmarshalRoundTrip(t *testing.T) {
	type entry struct {
		XMLName xml.Name `xml:"entry"`
		Name    string   `xml:"name"`
		Value   string   `xml:"value"`
	}
	original := entry{Name: "Иванов И.И.", Value: "тест"}
	data, err := nsdxml.Marshal(original)
	if err != nil {
		t.Fatalf("Marshal: %v", err)
	}
	if !strings.HasPrefix(string(nsdxml.DecodeWindows1251(data)), `<?xml version="1.0" encoding="windows-1251"?>`) {
		t.Fatalf("в выходе нет пролога windows-1251")
	}
	var parsed entry
	if err := nsdxml.Unmarshal(data, &parsed); err != nil {
		t.Fatalf("Unmarshal: %v", err)
	}
	if parsed.Name != original.Name || parsed.Value != original.Value {
		t.Errorf("round-trip разошёлся: %+v vs %+v", original, parsed)
	}
}
