package service

import (
	"encoding/json"
	"testing"

	"github.com/google/uuid"
)

func TestAssetMentionIndex(t *testing.T) {
	tests := []struct {
		name    string
		content string
		asset   string
		want    int
	}{
		{name: "space terminated mention", content: "镜头跟随 @丫丫 向前移动", asset: "丫丫", want: 13},
		{name: "punctuation terminated mention", content: "看向@客厅，停顿。", asset: "客厅", want: 6},
		{name: "end terminated mention", content: "参考@分镜 1 分镜图", asset: "分镜 1 分镜图", want: 6},
		{name: "reject shorter prefix", content: "@父亲 走进房间", asset: "父", want: -1},
		{name: "reject plain asset name", content: "父亲走进房间", asset: "父亲", want: -1},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			if got := assetMentionIndex(test.content, test.asset); got != test.want {
				t.Fatalf("assetMentionIndex(%q, %q) = %d, want %d", test.content, test.asset, got, test.want)
			}
		})
	}
}

func TestRenameAssetMentions(t *testing.T) {
	tests := []struct {
		name, content, oldName, newName, want string
		protectedNames                        []string
	}{
		{name: "all complete mentions", content: "@父亲 走向@客厅，随后看向@父亲", oldName: "父亲", newName: "老周", want: "@老周 走向@客厅，随后看向@老周"},
		{name: "Chinese description without separator", content: "@林溪微微睁大眼睛", oldName: "林溪", newName: "林溪月", want: "@林溪月微微睁大眼睛"},
		{name: "reject known longer asset", content: "@父亲 走进房间", oldName: "父", newName: "老周", protectedNames: []string{"父亲"}, want: "@父亲 走进房间"},
		{name: "ignore plain name", content: "父亲走进房间", oldName: "父亲", newName: "老周", want: "父亲走进房间"},
		{name: "punctuation in name", content: "参考@A+B。", oldName: "A+B", newName: "组合", want: "参考@组合。"},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			if got := renameAssetMentions(test.content, test.oldName, test.newName, test.protectedNames); got != test.want {
				t.Fatalf("renameAssetMentions() = %q, want %q", got, test.want)
			}
		})
	}
}

func TestRenameAssetRef(t *testing.T) {
	assetID := uuid.New()
	otherID := uuid.NewString()
	value := json.RawMessage(`[{"id":"` + assetID.String() + `","name":"父亲","type":"character"},{"id":"` + otherID + `","name":"客厅"}]`)
	got, changed, err := renameAssetRef(value, assetID, "老周")
	if err != nil {
		t.Fatal(err)
	}
	var refs []map[string]any
	if unmarshalErr := json.Unmarshal(got, &refs); unmarshalErr != nil || !changed || refs[0]["name"] != "老周" || refs[1]["name"] != "客厅" || refs[1]["id"] != otherID {
		t.Fatalf("renameAssetRef() = %s, changed=%v, err=%v", got, changed, err)
	}
}

func TestAssetRefNamesKeepsHistoricalMentionName(t *testing.T) {
	assetID := uuid.New()
	value := json.RawMessage(`[{"id":"` + assetID.String() + `","name":"改名前名称","type":"character"}]`)
	names, err := assetRefNames(value, assetID)
	if err != nil || len(names) != 1 || names[0] != "改名前名称" {
		t.Fatalf("assetRefNames() = %#v, err=%v", names, err)
	}
}
