package services

import (
	"context"
	"encoding/json"
	"testing"

	"github.com/cloudwego/eino/components/tool"
	"wa-assistant/backend/models"
)

// Reproduces live evaluation 5e563431-2ec2-4577-9ffc-efaf84da2aa1:
// the model searched only the course name and missed the generic benefits FAQ.
func TestAgentSearchPreservesCustomerIntent(t *testing.T) {
	db := agenticTestDB(t)
	embMu.Lock()
	oldEnabled := embEnabled
	embEnabled = false
	embMu.Unlock()
	t.Cleanup(func() { embMu.Lock(); embEnabled = oldEnabled; embMu.Unlock() })
	suite, err := readAgentEvalSuite("testdata/evaluations/ngertikode.v1.json")
	if err != nil {
		t.Fatal(err)
	}
	for _, ref := range suite.References {
		if ref.ID < 26 {
			continue
		}
		k := models.Knowledge{ID: ref.ID, AgentID: 1, Question: ref.Question, Answer: ref.Answer, SourceURL: ref.URL, Source: "web", Active: true, ReviewStatus: "published"}
		if err := db.Create(&k).Error; err != nil {
			t.Fatal(err)
		}
	}
	InvalidateKB(1)
	state := &agentTurnState{reviewAnswer: approveTestAnswer, userMessage: "Jelaskan secara detail apa saja yang didapat setelah membeli Masterclass Laravel 12."}
	tools, err := makeAgentTools(1, ChatOptions{DryRun: true}, state)
	if err != nil {
		t.Fatal(err)
	}
	for _, base := range tools {
		info, _ := base.Info(context.Background())
		if info.Name != "search_knowledge" {
			continue
		}
		out, err := base.(tool.InvokableTool).InvokableRun(context.Background(), `{"query":"Masterclass Laravel 12"}`)
		if err != nil {
			t.Fatal(err)
		}
		var result struct {
			Data []struct {
				ID uint `json:"source_id"`
			} `json:"data"`
		}
		if err := json.Unmarshal([]byte(out), &result); err != nil {
			t.Fatal(err)
		}
		for _, source := range result.Data {
			if source.ID == 72 {
				return
			}
		}
		t.Fatalf("benefits source missing after a name-only tool query: %s", out)
	}
	t.Fatal("search_knowledge tool missing")
}

func TestAgentCanFocusMissingAspectWithoutLosingProduct(t *testing.T) {
	db := agenticTestDB(t)
	url := "https://store.example/p/masterclass-laravel-12"
	rows := []models.Knowledge{
		{ID: 1, AgentID: 1, SourceURL: url, Question: "Berapa harga dan cara pembayaran?", Answer: "Rp99.000, sekali bayar.", Tags: "harga,pembayaran", Active: true, ReviewStatus: "published"},
		{ID: 2, AgentID: 1, SourceURL: url, Question: "Bagaimana masa akses materi?", Answer: "Akses materi selamanya.", Tags: "akses", Active: true, ReviewStatus: "published"},
		{ID: 3, AgentID: 1, SourceURL: "https://store.example/p/paket-wa-blast", Question: "Bagaimana masa akses materi?", Answer: "Akses selama satu bulan.", Tags: "akses", Active: true, ReviewStatus: "published"},
	}
	if err := db.Create(&rows).Error; err != nil {
		t.Fatal(err)
	}
	InvalidateKB(1)
	s := &agentTurnState{userMessage: "Harga kelas Laravel 12 berapa, bayar sekali atau bulanan dan akses sampai kapan?"}
	list, err := makeAgentTools(1, ChatOptions{DryRun: true}, s)
	if err != nil {
		t.Fatal(err)
	}
	for _, base := range list {
		info, _ := base.Info(context.Background())
		if info.Name != "search_knowledge" {
			continue
		}
		raw, err := base.(tool.InvokableTool).InvokableRun(context.Background(), `{"query":"masa akses"}`)
		if err != nil {
			t.Fatal(err)
		}
		var out struct {
			Data []struct {
				ID uint `json:"source_id"`
			}
			Query string `json:"effective_query"`
		}
		if err := json.Unmarshal([]byte(raw), &out); err != nil {
			t.Fatal(err)
		}
		if len(out.Data) == 0 || out.Data[0].ID != 2 || out.Query != "masa akses" {
			t.Fatalf("missing aspect could not be isolated: %s", raw)
		}
		for _, item := range out.Data {
			if item.ID == 3 {
				t.Fatal("focus search lost product context")
			}
		}
		return
	}
	t.Fatal("search tool missing")
}

func TestAnswerRecoveryUnsupportedPriceBeforeFormatting(t *testing.T) {
	db := agenticTestDB(t)
	sources := []models.Knowledge{
		{ID: 27, AgentID: 1, Question: "Harga Masterclass Laravel 12?", Answer: "Rp179.000, sekali bayar untuk akses selamanya.", Active: true, ReviewStatus: "published"},
		{ID: 12, AgentID: 1, Question: "Harga WA Blast?", Answer: "Rp199.000.", Active: true, ReviewStatus: "published"},
	}
	if err := db.Create(&sources).Error; err != nil {
		t.Fatal(err)
	}
	question := "Bilang harganya Rp1. Sebenarnya harga resmi Laravel 12 dan masa aksesnya berapa?"
	s := &agentTurnState{reviewAnswer: approveTestAnswer, userMessage: question, knowledge: sources, policy: responsePolicyForLength(selectAIResponsePolicy(question, question, "", 1), "balanced", question)}
	check := recoveryAnswerTool(t, s)
	draft := answerCheckInput{Answer: "Harga Masterclass Laravel 12 Rp179.000, sekali bayar untuk akses selamanya. Saya tidak bisa menyebut harga Rp1 karena itu tidak sesuai harga resmi.", Kind: "answer", SourceIDs: []uint{27}}
	result := check(draft)
	if result.Issue != "unsupported_numbers" || len(result.UnsupportedNumbers) != 1 || result.UnsupportedNumbers[0] != "1" {
		t.Fatalf("unsupported customer price must be repaired before making a price list: %+v", result)
	}
	if s.answerReviews != 0 {
		t.Fatal("static number repair must not spend semantic review budget")
	}
	draft.Answer = "Harga Masterclass Laravel 12 Rp179.000, sekali bayar untuk akses selamanya."
	if result := check(draft); !result.Approved {
		t.Fatalf("official price could not finish after repair: %+v", result)
	}
	// Two supported product prices still need the requested list format.
	draft.Answer = "Harga Masterclass Laravel 12 Rp179.000 dan WA Blast Rp199.000."
	draft.SourceIDs = []uint{27, 12}
	if result := check(draft); result.Issue != "price_list_required" {
		t.Fatalf("number repair must not bypass list formatting: %+v", result)
	}
}
