package office

import (
	"archive/zip"
	"bytes"
	"context"
	"io"
	"strings"
	"testing"
)

func TestRenderReport_ValidDocx(t *testing.T) {
	secs := []Section{
		{Heading: "第一章", Body: "正文内容 A&B"},
		{Heading: "第二章", Body: "正文 <内容> B"},
	}
	data, err := NewRenderer().RenderReport(context.Background(), "测试报告", secs)
	if err != nil {
		t.Fatalf("RenderReport err: %v", err)
	}
	zr, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
	if err != nil {
		t.Fatalf("产物不是合法 zip/docx: %v", err)
	}
	parts := map[string]string{}
	for _, f := range zr.File {
		rc, _ := f.Open()
		b, _ := io.ReadAll(rc)
		rc.Close()
		parts[f.Name] = string(b)
	}
	for _, need := range []string{"[Content_Types].xml", "_rels/.rels", "word/document.xml"} {
		if _, ok := parts[need]; !ok {
			t.Errorf("docx 缺少部件 %s", need)
		}
	}
	doc := parts["word/document.xml"]
	if !strings.Contains(doc, "测试报告") || !strings.Contains(doc, "第一章") || !strings.Contains(doc, "第二章") {
		t.Error("document.xml 应含标题与各章标题")
	}
	// XML 特殊字符必须转义，避免破坏文档。
	if strings.Contains(doc, "A&B") || !strings.Contains(doc, "A&amp;B") {
		t.Error("正文 & 应被转义为 &amp;")
	}
	if strings.Contains(doc, "<内容>") || !strings.Contains(doc, "&lt;内容&gt;") {
		t.Error("正文尖括号应被转义")
	}
}

func TestEscapeXML(t *testing.T) {
	got := escapeXML(`a&b<c>"d'`)
	want := "a&amp;b&lt;c&gt;&quot;d&apos;"
	if got != want {
		t.Errorf("escapeXML = %q, want %q", got, want)
	}
}
