package services

import (
	"context"
	einomodel "github.com/cloudwego/eino-ext/components/model/openai"
	"os"
	"strings"
	"testing"
	"time"
	"wa-assistant/backend/models"
)

func TestLiveDeepSeekFactGapRegressions(t *testing.T) {
	if os.Getenv("CHATLOOP_RUN_LIVE_DEEPSEEK") != "1" {
		t.Skip("opt-in paid factual checks, isolated data")
	}
	p, _, _, _ := liveDeepSeekAssistantSnapshot(t)
	cm, err := einomodel.NewChatModel(context.Background(), nativeAIModelConfig(p, 2200, .2))
	if err != nil {
		t.Fatal(err)
	}
	observed := &observedChatModel{inner: cm, provider: p.Key, modelName: p.Model}
	review := modelAnswerReviewer(observed)
	for _, tc := range []struct {
		name, q, a, e string
		accepted      bool
	}{
		{"social_claim", "Ada garansi?", "Semua produk bergaransi seumur hidup.", "", false},
		{"clarification_assumption", "Saya ingin retur", "Apakah Anda ingin memakai garansi seumur hidup kami?", "", false},
		{"plain_clarification", "Saya ingin beli", "Produk mana yang ingin dibeli?", "", true},
		{"partial_answer", "Harga dan masa akses Paket Belajar berapa?", "Harga Paket Belajar Rp99.000, sekali bayar.", "Harga Paket Belajar Rp99.000, sekali bayar. Akses materi selamanya.", false},
		{"complete_answer", "Harga dan masa akses Paket Belajar berapa?", "Paket Belajar Rp99.000, sekali bayar, akses materi selamanya.", "Harga Paket Belajar Rp99.000, sekali bayar. Akses materi selamanya.", true},
	} {
		t.Run(tc.name, func(t *testing.T) {
			out, err := review(context.Background(), tc.q, tc.a, tc.e)
			accepted := out.Supported && !out.Incomplete && !out.ConflictingSources && len(out.UnsupportedClaims) == 0 && len(out.MissingAspects) == 0
			t.Logf("accepted=%t complete=%t conflict=%t", accepted, !out.Incomplete, out.ConflictingSources)
			if err != nil || accepted != tc.accepted {
				t.Fatalf("incorrect live verdict: %+v err=%v", out, err)
			}
		})
	}
	t.Run("training_negation", func(t *testing.T) {
		source := "Paket Toko hanya untuk pemakaian internal. Dilarang menjual ulang source code Paket Toko atau menggunakannya untuk klien."
		for _, tc := range []struct {
			answer string
			valid  bool
		}{
			{"Paket Toko boleh dijual ulang dan digunakan untuk klien.", false},
			{"Paket Toko hanya untuk internal, dilarang dijual ulang atau digunakan untuk klien.", true},
		} {
			issues, err := reviewKnowledgeBatch(context.Background(), observed, "Lisensi Paket Toko", source, []QAPair{{Question: "Apa batasan lisensi Paket Toko?", Answer: tc.answer, Evidence: source}})
			if err != nil || (len(issues) == 0) != tc.valid {
				t.Fatalf("training verdict wrong: valid=%t issues=%v err=%v", tc.valid, issues, err)
			}
		}
	})
	t.Run("training_pipeline", func(t *testing.T) {
		source := "Toko Nusa menerima retur maksimal 7 hari setelah barang diterima. Barang wajib belum dipakai. Bukti pembelian wajib disertakan."
		items, err := generateKnowledgeWithModel(context.Background(), observed, "Kebijakan retur Toko Nusa", source)
		if err != nil || len(items) == 0 {
			t.Fatalf("reviewed training failed: %v", err)
		}
		for _, item := range items {
			if issue := validateKnowledgeEvidence(source, item); issue != "" {
				t.Fatal(issue)
			}
		}
		t.Logf("accepted FAQs=%d", len(items))
	})
}

func TestLiveDeepSeekPublishedCorrectionReplacesOldHistory(t *testing.T) {
	if os.Getenv("CHATLOOP_RUN_LIVE_DEEPSEEK") != "1" {
		t.Skip("opt-in paid correction acceptance, isolated data")
	}
	liveDeepSeekAssistantSnapshot(t)
	db := agenticTestDB(t)
	if err := db.AutoMigrate(&models.AppSetting{}, &models.Agent{}, &models.Product{}); err != nil {
		t.Fatal(err)
	}
	agent := models.Agent{ID: 1, TenantID: 1, AgenticEnabled: true, ResponseLength: "short", SystemPrompt: "Kamu asisten Toko Kebun. Gunakan pengetahuan terbit untuk fakta bisnis."}
	old := models.Knowledge{ID: 1, AgentID: 1, Question: "Berapa harga Paket Kebun?", Answer: "Harga Paket Kebun Rp75.000.", Source: "manual", ReviewStatus: "published", Active: true, Scope: "general"}
	correction := models.Knowledge{ID: 2, AgentID: 1, Question: "Biaya membeli Paket Kebun", Answer: "Harga Paket Kebun Rp99.000.", Source: "correction", ReviewStatus: "draft", Scope: "general", SupersedesID: 1}
	for _, row := range []any{&agent, &old, &correction, &models.AppSetting{Key: "ai_provider", Value: "deepseek"}} {
		if err := db.Create(row).Error; err != nil {
			t.Fatal(err)
		}
	}
	if err := db.Model(&correction).Update("active", false).Error; err != nil {
		t.Fatal(err)
	}
	InvalidateKB(1)
	q := "Berapa harga Paket Kebun?"
	before, err := chatAgentic(agent, agent.SystemPrompt, "ramah", q, nil, ChatOptions{Context: context.Background(), DryRun: true})
	if err != nil || before.Escalate || !strings.Contains(strings.ReplaceAll(before.Reply, ".", ""), "75000") {
		t.Fatalf("draft replaced live fact: %q %v", before.Reply, err)
	}
	if err := db.Model(&old).Updates(map[string]any{"active": false, "review_status": "archived"}).Error; err != nil {
		t.Fatal(err)
	}
	if err := db.Model(&correction).Updates(map[string]any{"active": true, "review_status": "published", "verified_at": time.Now()}).Error; err != nil {
		t.Fatal(err)
	}
	InvalidateKB(1)
	after, err := chatAgentic(agent, agent.SystemPrompt, "ramah", q, []models.ChatHistory{{Message: q, Reply: before.Reply}}, ChatOptions{Context: context.Background(), DryRun: true})
	if err != nil || after.Escalate || !strings.Contains(strings.ReplaceAll(after.Reply, ".", ""), "99000") || strings.Contains(after.Reply, "75") {
		t.Fatalf("published correction lost to history: %q %v", after.Reply, err)
	}
	t.Logf("before=%q after=%q", before.Reply, after.Reply)
}
