package orchestrator

import (
	"testing"

	"git.yeij.top/AskaEth/Cyrene/ai-core/internal/model"
)

func TestParseReviewMessages(t *testing.T) {
	tests := []struct {
		name     string
		input    string
		wantLen  int
		wantType []model.ReviewMessageType // type of each message in order
	}{
		{"纯聊天无括号", "叶酱，客厅灯早就开着啦", 1, []model.ReviewMessageType{model.ReviewMessageChat}},
		{"纯动作括号", "(歪着头看你)", 1, []model.ReviewMessageType{model.ReviewMessageAction}},
		{"中文括号动作", "（歪着头看你）", 1, []model.ReviewMessageType{model.ReviewMessageAction}},
		{"动作+聊天", "(歪着头看你) 叶酱，客厅灯早就开着啦♪", 2, []model.ReviewMessageType{model.ReviewMessageAction, model.ReviewMessageChat}},
		{"聊天+动作", "我帮你关掉了哦 (轻轻按下遥控器)", 2, []model.ReviewMessageType{model.ReviewMessageChat, model.ReviewMessageAction}},
		{"只有括号但无内容", "", 0, nil},
		{"空括号", "()", 1, []model.ReviewMessageType{model.ReviewMessageChat}},
		{"多段落", "第一段内容\n\n第二段内容", 2, []model.ReviewMessageType{model.ReviewMessageChat, model.ReviewMessageChat}},
		{"动作+多段聊天", "(歪头) 第一段\n\n第二段内容", 3, []model.ReviewMessageType{model.ReviewMessageAction, model.ReviewMessageChat, model.ReviewMessageChat}},
		// XML action tag tests
		{"XML纯动作", "<action>轻轻晃了晃手指</action>", 1, []model.ReviewMessageType{model.ReviewMessageAction}},
		{"XML动作+聊天", "<action>歪头看着你</action> 叶酱，今天好开心呀♪", 2, []model.ReviewMessageType{model.ReviewMessageAction, model.ReviewMessageChat}},
		{"XML聊天+动作+聊天", "你说的对 <action>轻轻敲了敲桌子</action> 不过我还有一个想法", 3, []model.ReviewMessageType{model.ReviewMessageChat, model.ReviewMessageAction, model.ReviewMessageChat}},
		{"XML多个动作", "<action>歪头</action> <action>轻轻按下遥控器</action> 帮你关掉啦~", 3, []model.ReviewMessageType{model.ReviewMessageAction, model.ReviewMessageAction, model.ReviewMessageChat}},
		{"XML混合括号降级", "开头聊天 <action>歪头</action> 中间聊天 (括号动作) 结尾聊天", 5, []model.ReviewMessageType{model.ReviewMessageChat, model.ReviewMessageAction, model.ReviewMessageChat, model.ReviewMessageAction, model.ReviewMessageChat}},
		{"XML空标签忽略", "<action></action> 正常聊天", 1, []model.ReviewMessageType{model.ReviewMessageChat}},
		{"XML多行动作", "<action>走到窗边\n拉开窗帘</action> 今天阳光真好呢♪", 2, []model.ReviewMessageType{model.ReviewMessageAction, model.ReviewMessageChat}},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := parseReviewMessages(tt.input)
			if tt.wantLen == 0 && len(got) == 0 {
				return
			}
			if len(got) != tt.wantLen {
				t.Errorf("parseReviewMessages(%q) len = %d, want %d\ngot: %+v", tt.input, len(got), tt.wantLen, got)
				return
			}
			for i, m := range got {
				if i < len(tt.wantType) && m.Type != tt.wantType[i] {
					t.Errorf("parseReviewMessages(%q)[%d].Type = %q, want %q", tt.input, i, m.Type, tt.wantType[i])
				}
			}
		})
	}
}

func TestSplitChatByLines(t *testing.T) {
	tests := []struct {
		name    string
		input   string
		wantLen int
	}{
		{"单行", "这是单行消息", 1},
		{"双换行分割", "第一段\n\n第二段", 2},
		{"三段", "第一段\n\n第二段\n\n第三段", 3},
		{"只有空白行", "\n\n\n\n", 0},
		{"混合空白", "  第一段  \n\n  第二段  ", 2},
		{"单换行不分割", "第一行\n第二行", 1}, // 单\n不分割
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := splitChatByLines(model.ReviewMessageChat, tt.input)
			if len(got) != tt.wantLen {
				t.Errorf("splitChatByLines(%q) len = %d, want %d\ngot: %+v", tt.input, len(got), tt.wantLen, got)
			}
		})
	}
}

func TestSplitReviewLongMessage(t *testing.T) {
	tests := []struct {
		name    string
		input   string
		wantMax int // max messages expected (1 for short)
	}{
		{"短消息不拆分", "这是一条短消息", 1},
		{"刚好80字", "这是一条刚好八十字的消息测试一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十", 1},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := splitReviewLongMessage(model.ReviewMessageChat, tt.input)
			if len(got) > tt.wantMax {
				t.Errorf("splitReviewLongMessage(%q) len = %d, want <= %d", tt.input, len(got), tt.wantMax)
			}
			for _, m := range got {
				if m.Type != model.ReviewMessageChat {
					t.Errorf("splitReviewLongMessage msg type = %q, want chat", m.Type)
				}
			}
		})
	}
}

func TestSplitLongText(t *testing.T) {
	tests := []struct {
		name   string
		input  string
		maxLen int
	}{
		{"短文本不分割", "短文本", 80},
		{"空文本", "", 80},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			runes := []rune(tt.input)
			got := splitLongText(model.ReviewMessageChat, runes, tt.maxLen)
			if tt.input == "" && len(got) == 0 {
				return
			}
			if len(got) == 0 {
				t.Errorf("splitLongText returned empty for non-empty input")
			}
			// Verify all chunks preserve type and aren't empty
			for i, m := range got {
				if m.Type != model.ReviewMessageChat {
					t.Errorf("splitLongText[%d].Type = %q, want chat", i, m.Type)
				}
				if m.Content == "" && tt.input != "" {
					t.Errorf("splitLongText[%d].Content is empty", i)
				}
			}
		})
	}
}

// TestSplitLongTextLong verifies that a long text is split at sentence boundaries (80-rune max)
func TestSplitLongTextLong(t *testing.T) {
	// Build a string > 80 runes with sentence breaks
	input := "今天天气真好呀。" +
		"我们去公园散步吧，然后可以去喝杯咖啡。" +
		"你觉得怎么样呢？顺便可以叫上朋友一起去。" +
		"人多热闹一些呢。" +
		"今天的阳光也特别好，适合出去走走，呼吸新鲜空气对身体有好处。"

	runes := []rune(input)
	maxLen := 80

	if len(runes) <= maxLen {
		t.Skip("test requires input > 80 runes")
	}

	got := splitLongText(model.ReviewMessageChat, runes, maxLen)
	if len(got) < 2 {
		t.Errorf("splitLongText on >80 rune text should produce >= 2 chunks, got %d", len(got))
	}

	// Verify each chunk is <= maxLen
	for i, m := range got {
		if len([]rune(m.Content)) > maxLen {
			t.Errorf("chunk[%d] has %d runes, exceeds max %d", i, len([]rune(m.Content)), maxLen)
		}
	}
}

// TestParseReviewMessagesEdgeCases covers edge inputs
func TestParseReviewMessagesEdgeCases(t *testing.T) {
	// Multiple action brackets
	result := parseReviewMessages("(笑) 这句话很有意思呢 (摇摇头) 不过我理解你的意思")
	if len(result) < 3 {
		t.Errorf("Expected at least 3 messages, got %d: %+v", len(result), result)
	}

	// Only action brackets
	result = parseReviewMessages("(点头)")
	if len(result) != 1 || result[0].Type != model.ReviewMessageAction {
		t.Errorf("Expected 1 action message, got: %+v", result)
	}

	// Unicode content
	result = parseReviewMessages("（微笑）叶酱，今天好开心呀♪ 一起加油吧✨")
	if len(result) < 2 {
		t.Errorf("Expected at least 2 messages, got %d: %+v", len(result), result)
	}
}

// TestIsSimpleGreetingEdgeCases covers whitespace and casing
func TestIsSimpleGreetingEdgeCases(t *testing.T) {
	a := &IntentAnalyzer{}

	// Whitespace handling
	if !a.isSimpleGreeting("  你好  ") {
		t.Error("isSimpleGreeting with surrounding spaces should match")
	}
	// Case insensitivity
	if !a.isSimpleGreeting("Hello") {
		t.Error("isSimpleGreeting should be case-insensitive for English")
	}
	// Very long message is not a greeting
	if a.isSimpleGreeting("昔涟你好呀，今天我想跟你说一件很重要很重要的事情") {
		t.Error("Long message should not be detected as simple greeting")
	}
}

// TestIsStrongIoTCommandEdgeCases covers edge cases
func TestIsStrongIoTCommandEdgeCases(t *testing.T) {
	a := &IntentAnalyzer{}

	// "开" within non-IoT word should not match alone
	if a.isStrongIoTCommand("开心的一天") {
		t.Error("'开心' should not trigger IoT command")
	}
	// Combined with device word
	if !a.isStrongIoTCommand("帮我把卧室空调打开可以吗") {
		t.Error("'打开'+'空调' should trigger IoT command")
	}
	// Only device word
	if a.isStrongIoTCommand("风扇声音好大") {
		t.Error("'风扇' alone should not trigger IoT command")
	}
}
