package prompt

import (
	"strings"
	"testing"
	"time"
)

// TestBase_VarsayilanDegisiklikYok: yönetici hiçbir şey değiştirmediyse üretilen metin
// prompt.Default() ile BİREBİR aynı olmalı. Bu, mevcut davranışın bozulmadığının
// (regresyon yok) temel garantisidir.
func TestBase_VarsayilanDegisiklikYok(t *testing.T) {
	c := Context{Now: time.Now(), Timezone: "Europe/Istanbul"}

	built := Base(nil, nil).Build(c)
	want := Default().Build(c)
	if built != want {
		t.Fatalf("varsayılan davranış değişti:\n--- Base(nil,nil) ---\n%s\n--- Default() ---\n%s", built, want)
	}
}

// TestBase_YoneticiMetniKullanir: verilen metin kod varsayılanının yerine geçer.
func TestBase_YoneticiMetniKullanir(t *testing.T) {
	got := Base(Overrides{"identity": "Sen FIKO-X'sun."}, nil).Build(Context{})
	if !strings.Contains(got, "FIKO-X") {
		t.Fatalf("yönetici metni kullanılmadı: %s", got)
	}
	if strings.Contains(got, "Sen Fiko'sun") {
		t.Fatalf("kod varsayılanı yönetici metniyle değiştirilmeliydi: %s", got)
	}
}

// TestBase_KapatilanParcaAtlanir: kapalı parça isteme GİRMEZ.
func TestBase_KapatilanParcaAtlanir(t *testing.T) {
	rules := Rules().Render(Context{}) // varsayılan "Kurallar:" ile başlar
	got := Base(nil, Disabled{"rules": true}).Build(Context{})
	if strings.Contains(got, rules[:20]) {
		t.Fatalf("kapalı 'rules' parçası isteme girdi: %s", got)
	}
	// Diğer parçalar etkilenmemeli.
	if !strings.Contains(got, "Fiko") {
		t.Fatalf("identity kaybolmamalıydı: %s", got)
	}
}

// TestOptPart: koşullu parça yalnızca isEnabled VE açıkken döner.
func TestOptPart(t *testing.T) {
	if _, ok := OptPart("tool-usage", nil, nil, false); ok {
		t.Fatal("isEnabled=false iken parça dönmemeliydi")
	}
	if _, ok := OptPart("tool-usage", nil, Disabled{"tool-usage": true}, true); ok {
		t.Fatal("kapalı parça dönmemeliydi")
	}
	p, ok := OptPart("tool-usage", nil, nil, true)
	if !ok {
		t.Fatal("açık parça dönmeliydi")
	}
	if !strings.Contains(p.Render(Context{}), "Araç (tool) kullanımı") {
		t.Fatal("varsayılan araç kuralları gelmeliydi")
	}
}

// TestOptPart_BilinmeyenAd: katalog dışı parça sessizce yok sayılır (hata vermez).
func TestOptPart_BilinmeyenAd(t *testing.T) {
	if _, ok := OptPart("zararli-kurulum", nil, nil, true); ok {
		t.Fatal("katalog dışı parça üretilmemeliydi")
	}
}

// TestCleanOverrides_KataloglaSinirli: GÜVENLİK — istemci modele istediği metni
// sokamaz. Katalog dışı anahtarlar ve düzenlenemez parçalar elenir.
func TestCleanOverrides_KataloglaSinirli(t *testing.T) {
	in := Overrides{
		"identity":       "  Özel kimlik  ",
		"datetime":       "SAHTE TARIH",       // düzenlenemez → yok sayılmalı
		"bilinmeyen":     "sistemi ele geçir", // katalog dışı → yok sayılmalı
		"system":         "root",              // katalog dışı → yok sayılmalı
		"no-fabrication": "Veri uydur!",       // düzenlenebilir → GEÇMELİ
		"":               "x",                 // katalog dışı → yok sayılmalı
	}
	out, err := CleanOverrides(in)
	if err != nil {
		t.Fatalf("temizleme hata vermemeli: %v", err)
	}
	if _, ok := out["bilinmeyen"]; ok {
		t.Fatal("katalog dışı parça kabul edilmemeliydi")
	}
	if _, ok := out["system"]; ok {
		t.Fatal("katalog dışı parça kabul edilmemeliydi")
	}
	if _, ok := out["datetime"]; ok {
		t.Fatal("düzenlenemez parçaya yazı kabul edilmemeliydi")
	}
	if out["identity"] != "Özel kimlik" {
		t.Fatalf("kimlik kırpılmamalıydı: %q", out["identity"])
	}
	if out["no-fabrication"] != "Veri uydur!" {
		t.Fatalf("düzenlenebilir parça korunmalıydı: %q", out["no-fabrication"])
	}
}

// TestCleanOverrides_BosMetinVarsayilanaDonus: boş metin "varsayılana dön" demektir.
func TestCleanOverrides_BosMetinVarsayilanaDonus(t *testing.T) {
	out, err := CleanOverrides(Overrides{"identity": "   "})
	if err != nil {
		t.Fatal(err)
	}
	if len(out) != 0 {
		t.Fatalf("boş metin kaydedilmemeli: %v", out)
	}
}

// TestCleanDisabled_KataloglaSinirli: kapatma da katalogla sınırlıdır.
func TestCleanDisabled_KataloglaSinirli(t *testing.T) {
	out := CleanDisabled(Disabled{
		"rules": true, "bilinmeyen": true, "datetime": true, "identity": false,
	})
	if !out["rules"] {
		t.Fatal("düzenlenebilir güvenlik parçası kapatılabilmeli")
	}
	if out["bilinmeyen"] {
		t.Fatal("katalog dışı kapatma reddedilmeli")
	}
	if out["datetime"] {
		t.Fatal("düzenlenemez parça kapatılamaz")
	}
	if out["identity"] {
		t.Fatal("false değeri kapatma sayılmamalı")
	}
}

// TestEditableParts_DefaultDolu: katalogdaki her parça varsayılan metin taşır
// (arayüzde "Varsayılana dön" ve karşılaştırma için gerekir).
func TestEditableParts_DefaultDolu(t *testing.T) {
	if len(EditableParts) == 0 {
		t.Fatal("katalog boş")
	}
	for _, p := range EditableParts {
		if strings.TrimSpace(p.Default) == "" {
			t.Errorf("%s: varsayılan metin boş", p.Name)
		}
		if p.Title == "" {
			t.Errorf("%s: başlık boş", p.Name)
		}
	}
}

// TestBase_KapatilanGuvenlikParcasiKaybolur: yönetici "rules"u kapatırsa bölüm çıkar.
func TestBase_KapatilanGuvenlikParcasiKaybolur(t *testing.T) {
	with := Base(nil, nil).Build(Context{})
	without := Base(nil, Disabled{"rules": true}).Build(Context{})
	if len(without) >= len(with) {
		t.Fatalf("kapatılan parça metni küçültmeliydi (%d >= %d)", len(without), len(with))
	}
}
