package api

import (
	"context"
	"net/http"
	"strings"
	"testing"
	"time"

	"fiko-ai/internal/claim"
)

// claims_reports_test.go — GET /api/claims/reports (Faz 9). Hesap sohbetteki rapor niyetiyle aynıdır
// (claim.BuildReport); burada yalnızca HTTP katmanı sınanır: kimlik, parametre doğrulama, vektör sızmaması.

// seedTyped tipli (alanlı) bir kayıt koyar.
func (e *claimsEnv) seedTyped(t *testing.T, id, kind, text string, fields map[string]string, authorID string) {
	t.Helper()
	now := time.Date(2026, 10, 5, 9, 0, 0, 0, time.UTC)
	c := claim.Claim{
		ID: id, Kind: kind, Text: text, Key: claim.NormalizeKey(text), AuthorID: authorID, AuthorName: "yazar",
		CreatedAt: now, UpdatedAt: now, Status: claim.StatusActive, Fields: fields,
		Embedding: []float32{1, 0, 0}, EmbedModel: "m",
	}
	if err := e.repo.Create(context.Background(), &c); err != nil {
		t.Fatal(err)
	}
}

// reportFixture B-12 projesi + biri gecikmiş (2000 her zaman geçmiş), biri tamamlanmış iki görev koyar.
func (e *claimsEnv) reportFixture(t *testing.T, authorID string) {
	t.Helper()
	e.seedTyped(t, "p1", "proje", "B-12", map[string]string{"ad": "B-12", "sorumlu": "Mehmet", "durum": "devam", "bitis": "2099-01-01"}, authorID)
	e.seedTyped(t, "g1", claim.KindGorev, "İşleme programı hazırlanacak",
		map[string]string{"proje": "B-12", "atanan": "Ahmet", "son_tarih": "2000-01-01", "durum": "acik"}, authorID)
	e.seedTyped(t, "g2", claim.KindGorev, "Kalıp çizimi",
		map[string]string{"proje": "B-12", "durum": "tamamlandi"}, authorID)
}

func TestClaimsAPI_Reports(t *testing.T) {
	e := claimsServer(t, true, true)
	a := registerClaimActors(t, e.s)
	e.reportFixture(t, a.ali.User.ID)

	// Oturumsuz 401.
	if resp, _ := do(t, e.s, http.MethodGet, "/api/claims/reports?type=proje_ozet", nil, nil); resp.StatusCode != http.StatusUnauthorized {
		t.Fatalf("oturumsuz rapor 401 olmalı: %d", resp.StatusCode)
	}
	// Türsüz / bilinmeyen tür 400 (ve /:id olarak yutulmaz).
	for _, q := range []string{"", "?type=bozuk"} {
		if resp, raw := do(t, e.s, http.MethodGet, "/api/claims/reports"+q, nil, bearer(a.veli.Token)); resp.StatusCode != http.StatusBadRequest {
			t.Errorf("tür %q: 400 beklenirdi, %d %s", q, resp.StatusCode, raw)
		}
	}

	// Gecikmiş görev: herhangi bir doğrulanmış üye görür; hesap sunucuda yapılmış.
	resp, raw := do(t, e.s, http.MethodGet, "/api/claims/reports?type=gecikmis_gorev", nil, bearer(a.veli.Token))
	if resp.StatusCode != http.StatusOK {
		t.Fatalf("gecikmiş görev raporu: %d %s", resp.StatusCode, raw)
	}
	rep := decode[claim.ReportResult](t, raw)
	if rep.Type != claim.ReportOverdue || len(rep.Tasks) != 1 || rep.Tasks[0].ID != "g1" || !rep.Tasks[0].Overdue || rep.Tasks[0].DaysLate <= 0 {
		t.Fatalf("gecikmiş görev yanlış: %+v", rep)
	}
	if !strings.Contains(rep.Text, "İşleme programı") {
		t.Errorf("rapor metni sunucuda üretilmeli: %q", rep.Text)
	}
	if strings.Contains(strings.ToLower(string(raw)), "embedding") {
		t.Fatalf("vektör yanıta sızdı: %s", raw)
	}

	// Proje durumu: ad verilir; 2 görevden 1'i bitmiş → %50.
	resp, raw = do(t, e.s, http.MethodGet, "/api/claims/reports?type=proje_durumu&project=B-12", nil, bearer(a.veli.Token))
	if resp.StatusCode != http.StatusOK {
		t.Fatalf("proje durumu: %d %s", resp.StatusCode, raw)
	}
	rep = decode[claim.ReportResult](t, raw)
	if len(rep.Projects) != 1 || rep.Projects[0].Progress != 50 || rep.Projects[0].Overdue != 1 {
		t.Fatalf("proje durumu yanlış: %+v", rep.Projects)
	}

	// Özet raporunda project parametresi yok sayılır.
	resp, raw = do(t, e.s, http.MethodGet, "/api/claims/reports?type=proje_ozet&project=yok", nil, bearer(a.veli.Token))
	if resp.StatusCode != http.StatusOK {
		t.Fatalf("proje özeti: %d %s", resp.StatusCode, raw)
	}
	if rep = decode[claim.ReportResult](t, raw); len(rep.Projects) != 1 || rep.NotFound {
		t.Fatalf("özet project parametresinden etkilenmemeli: %+v", rep)
	}
}

func TestClaimsAPI_ReportsMembershipOffAndNotConfigured(t *testing.T) {
	e := claimsServer(t, false, true)
	if resp, raw := do(t, e.s, http.MethodGet, "/api/claims/reports?type=proje_ozet", nil, nil); resp.StatusCode != http.StatusForbidden {
		t.Errorf("üyelik kapalıyken 403 beklenirdi: %d %s", resp.StatusCode, raw)
	}
	e2 := claimsServer(t, true, false)
	a := registerUser(t, e2.s, "patron")
	if resp, _ := do(t, e2.s, http.MethodGet, "/api/claims/reports?type=proje_ozet", nil, bearer(a.Token)); resp.StatusCode != http.StatusServiceUnavailable {
		t.Errorf("servis yokken 503 beklenirdi: %d", resp.StatusCode)
	}
}
