package claim

import (
	"context"
	"os"
	"strings"
	"testing"
	"time"

	"fiko-ai/internal/llm"
	"fiko-ai/internal/llm/ollama"
)

// TestE2E_GercekOllama_Rapor (Faz 9) ayırıcının "rapor" niyetini gerçek modelle dener ve liste/soru
// ayrımının BOZULMADIĞINI doğrular (prompt'a rapor türü eklendi). Yalnızca CLAIM_E2E_OLLAMA=1 iken çalışır.
//
//	CLAIM_E2E_OLLAMA=1 go test ./internal/claim -run TestE2E_GercekOllama_Rapor -v -timeout 10m
func TestE2E_GercekOllama_Rapor(t *testing.T) {
	if os.Getenv("CLAIM_E2E_OLLAMA") != "1" {
		t.Skip("CLAIM_E2E_OLLAMA=1 değil; gerçek Ollama denemesi atlandı")
	}
	model := e2eEnv("CLAIM_E2E_MODEL", "gemma4:latest")
	embed := e2eEnv("CLAIM_E2E_EMBED", "qwen3-embedding")
	base := e2eEnv("OLLAMA_BASE_URL", "http://localhost:11434")
	prov := ollama.New(base, model, 5*time.Minute).WithEmbedModel(embed)
	var embedder llm.Embedder = prov

	// Tarihler gerçek saatten bağımsız olsun: 2000 her zaman geçmiş, 2099 her zaman gelecek.
	repo := readRepo(t,
		repProject("p1", "B-12", map[string]string{"sorumlu": "Mehmet", "durum": "devam", "bitis": "2099-01-01"}),
		repTask("g1", "İşleme programı hazırlanacak", map[string]string{"proje": "B-12", "atanan": "Ahmet", "son_tarih": "2000-01-01", "durum": "acik"}, StatusActive),
		repTask("g2", "Kalıp çizimi", map[string]string{"proje": "B-12", "durum": "tamamlandi"}, StatusActive),
		readClaim("f1", KindFirma, "ACME Kalıp müşterimizdir", StatusActive, nil),
	)
	rd := NewReader(repo, prov, embedder, ReadConfig{Model: model, EmbedModel: embed})
	ctx, cancel := context.WithTimeout(context.Background(), 8*time.Minute)
	defer cancel()

	cases := []struct {
		msg  string
		want Intent
	}{
		{"gecikmiş görevler hangileri?", Intent{Type: IntentReport, Report: ReportOverdue}},
		{"kimin işi gecikti, süresi geçenleri göster", Intent{Type: IntentReport, Report: ReportOverdue}},
		{"B-12 projesi ne durumda?", Intent{Type: IntentReport, Report: ReportProject, Project: "B-12"}},
		{"B-12 ne kadar bitti", Intent{Type: IntentReport, Report: ReportProject, Project: "B-12"}},
		{"projelerin durumunu özetle", Intent{Type: IntentReport, Report: ReportSummary}},
		// Gerilemeler: bunlar rapor OLMAMALI.
		{"firmaların listesini ver", Intent{Type: IntentList, Kind: KindFirma}},
		{"tüm görevleri listele", Intent{Type: IntentList, Kind: KindGorev}},
		{"ACME Kalıp ne zamandan beri müşterimiz?", Intent{Type: IntentQuestion}},
		{"Merhaba, nasılsın?", Intent{Type: IntentQuestion}},
	}
	for _, c := range cases {
		start := time.Now()
		got, err := rd.Classify(ctx, c.msg)
		if err != nil {
			t.Errorf("%q: Classify hata: %v", c.msg, err)
			continue
		}
		ok := got.Type == c.want.Type && got.Kind == c.want.Kind && got.Report == c.want.Report &&
			NormalizeKey(got.Project) == NormalizeKey(c.want.Project)
		t.Logf("%-48q → %+v (%s) %s", c.msg, got, time.Since(start).Round(time.Millisecond), map[bool]string{true: "OK", false: "YANLIŞ"}[ok])
		if !ok {
			t.Errorf("%q: ayırıcı = %+v, beklenen %+v", c.msg, got, c.want)
		}
	}

	// Uçtan uca: gerçek ayırıcı + sunucu raporu.
	p, err := rd.Prepare(ctx, "B-12 projesi ne durumda?", Actor{ID: "u1", Name: "Fikri", Role: RolePatron})
	if err != nil {
		t.Fatalf("Prepare: %v", err)
	}
	if p.Report == nil || !strings.Contains(p.Append, "%50 (2 görevden 1 tamamlandı)") || !strings.Contains(p.Append, "gün gecikti") {
		t.Errorf("proje raporu beklenen sayıları taşımıyor (rapor=%v):\n%s", p.Report != nil, p.Append)
	}
	t.Logf("rapor:\n%s", p.Append)
}

// TestE2E_GercekOllama_ProjeGorevZinciri doğal dille girilen proje/görev bilgisinin tipli kayda çevrilip
// raporlandığını gerçek modelle dener (yazma → alan çıkarma → rapor). Yalnızca CLAIM_E2E_OLLAMA=1 iken çalışır.
//
//	CLAIM_E2E_OLLAMA=1 go test ./internal/claim -run TestE2E_GercekOllama_ProjeGorevZinciri -v -timeout 15m
func TestE2E_GercekOllama_ProjeGorevZinciri(t *testing.T) {
	if os.Getenv("CLAIM_E2E_OLLAMA") != "1" {
		t.Skip("CLAIM_E2E_OLLAMA=1 değil; gerçek Ollama denemesi atlandı")
	}
	model := e2eEnv("CLAIM_E2E_MODEL", "gemma4:latest")
	embed := e2eEnv("CLAIM_E2E_EMBED", "qwen3-embedding")
	base := e2eEnv("OLLAMA_BASE_URL", "http://localhost:11434")
	prov := ollama.New(base, model, 5*time.Minute).WithEmbedModel(embed)
	var embedder llm.Embedder = prov
	repo, audit := NewMemoryRepo(), NewMemoryAuditRepo()
	svc := NewService(repo, audit, prov, embedder, Config{Model: model, EmbedModel: embed}, nil)
	defer svc.Close()
	ctx, cancel := context.WithTimeout(context.Background(), 12*time.Minute)
	defer cancel()
	actor := Actor{ID: "usr_fikri", Name: "Fikri", Role: RolePatron}

	// Mutlak tarihler kullanılır: model göreli ifadeyi ("cuma") çözmez, çözümü kod yapar; bu test
	// yalnızca alan çıkarma + rapor zincirini sınar. Bugün 2026-10-06 varsayımı yok: 2020 geçmiş, 2099 gelecek.
	start := time.Now()
	res, err := svc.Write(ctx, actor, "Kalıp B-12 projesi Mehmet'te, bitiş tarihi 31.12.2099, öncelik yüksek, şu an devam ediyor. "+
		"Ahmet 01.03.2020 tarihine kadar B-12 işleme programını hazırlasın. "+
		"Ayşe 01.01.2099 tarihine kadar B-12 montajını bitirsin. "+
		"B-12 kalıp çizimi tamamlandı.")
	if err != nil {
		t.Fatalf("Write: %v", err)
	}
	t.Logf("yazma %s sürdü: %s", time.Since(start).Round(time.Second), res.Summary())

	projects, _ := repo.List(ctx, Filter{Kinds: []string{"proje"}}, 0, 0)
	tasks, _ := repo.List(ctx, Filter{Kinds: []string{KindGorev}}, 0, 0)
	all, _ := repo.List(ctx, Filter{}, 0, 0)
	for _, c := range all {
		t.Logf("kayıt [%s] %q alanlar=%v", c.Kind, c.Text, c.Fields)
	}
	if len(projects) != 1 || len(tasks) < 2 {
		t.Fatalf("1 proje ve en az 2 görev beklenirdi: proje=%d görev=%d", len(projects), len(tasks))
	}

	rd := NewReader(repo, prov, embedder, ReadConfig{Model: model, EmbedModel: embed})

	// Tamamlanma bildirimi: mevcut görevin durumu değişmeli; eski "açık" kayıt gecikmiş sayılmaya DEVAM etmemeli.
	res2, err := svc.Write(ctx, actor, "Ahmet B-12 işleme programını bitirdi.")
	if err != nil {
		t.Fatalf("Write (tamamlanma): %v", err)
	}
	t.Logf("tamamlanma yazması: %s", res2.Summary())
	after, _ := repo.List(ctx, Filter{Kinds: []string{KindGorev}}, 0, 0)
	for _, c := range after {
		t.Logf("görev sonrası durum=%s %q alanlar=%v", c.Status, c.Text, c.Fields)
	}

	over, err := rd.Report(ctx, ReportRequest{Type: ReportOverdue}, actor)
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("gecikmiş görev raporu:\n%s", over.Text)
	if len(over.Tasks) != 0 {
		t.Errorf("Ahmet işi bitirdi: gecikmiş görev kalmamalıydı, var: %+v", over.Tasks)
	}

	proj, err := rd.Report(ctx, ReportRequest{Type: ReportProject, Project: "B-12"}, actor)
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("proje raporu:\n%s", proj.Text)
	if proj.NotFound || len(proj.Projects) != 1 {
		t.Fatalf("B-12 bulunamadı: %s", proj.Text)
	}
	if p := proj.Projects[0]; p.Overdue != 0 || p.Done < 1 {
		t.Errorf("B-12: gecikmiş=%d tamamlanan=%d; beklenen 0 ve ≥1", p.Overdue, p.Done)
	}
}
