package services

import (
	"context"
	"testing"
	"time"

	"gorm.io/gorm"
	"wa-assistant/backend/models"
)

func TestKnowledgeFreshnessBlocksChangedDeletedAndExpiredAnswers(t *testing.T) {
	for _, tc := range []struct {
		name, issue string
		mutate      func(*gorm.DB, models.Knowledge) error
	}{
		{"deleted", "source_unavailable", func(db *gorm.DB, k models.Knowledge) error { return db.Delete(&k).Error }},
		{"archived", "source_unavailable", func(db *gorm.DB, k models.Knowledge) error {
			return db.Model(&k).UpdateColumns(map[string]any{"active": false, "review_status": "archived"}).Error
		}},
		{"changed without timestamp", "source_changed", func(db *gorm.DB, k models.Knowledge) error {
			return db.Model(&k).UpdateColumn("answer", "Informasi pengganti").Error
		}},
		{"expired", "source_unavailable", func(db *gorm.DB, k models.Knowledge) error {
			return db.Model(&k).UpdateColumn("effective_until", time.Now().Add(-time.Second)).Error
		}},
		{"future", "source_unavailable", func(db *gorm.DB, k models.Knowledge) error {
			return db.Model(&k).UpdateColumn("effective_from", time.Now().Add(time.Hour)).Error
		}},
	} {
		t.Run(tc.name, func(t *testing.T) {
			db := agenticTestDB(t)
			k := models.Knowledge{AgentID: 1, Question: "Hosting?", Answer: "Membutuhkan VPS.", Active: true, ReviewStatus: "published"}
			if err := db.Create(&k).Error; err != nil {
				t.Fatal(err)
			}
			result := createChatResult(1, k.Answer, "fixture", false, []models.Knowledge{k}, "", "Hosting?", nil, RetrievalTrace{ResponseValidated: true})
			if issue := result.KnowledgeIssue(context.Background(), 1); issue != "" {
				t.Fatal("current answer rejected", issue)
			}
			if err := tc.mutate(db, k); err != nil {
				t.Fatal(err)
			}
			result.EnforceCurrentKnowledge(context.Background(), 1)
			if !result.Escalate || result.Reply != "" || result.Trace.AnswerCheckIssue != tc.issue || result.Trace.ResponseValidated {
				t.Fatalf("stale answer deliverable: %+v", result)
			}
		})
	}
}

func TestKnowledgeFreshnessScopesSourcesAndPreservesReadExcerpt(t *testing.T) {
	db := agenticTestDB(t)
	k := models.Knowledge{AgentID: 1, Question: "Hosting?", Answer: "Membutuhkan VPS. Syarat tambahan yang belum dibaca.", Active: true, ReviewStatus: "published"}
	if err := db.Create(&k).Error; err != nil {
		t.Fatal(err)
	}
	k.Answer = "Membutuhkan VPS."
	got, issue := currentKnowledgeSources(context.Background(), 1, []models.Knowledge{k})
	if issue != "" || len(got) != 1 || got[0].Answer != k.Answer || got[0].CharCount <= len([]rune(k.Answer)) {
		t.Fatal("unread tail leaked into evidence or valid excerpt rejected")
	}
	if _, issue := currentKnowledgeSources(context.Background(), 2, []models.Knowledge{k}); issue != "source_unavailable" {
		t.Fatal("foreign source accepted", issue)
	}
	if issue := (ChatResult{Reply: "Terima kasih."}).KnowledgeIssue(context.Background(), 1); issue != "" {
		t.Fatal("social reply requires fictitious source")
	}
}
