package rag

import (
	"bufio"
	"context"
	"encoding/json"
	"fmt"
	"log"
	"strings"
	"sync"
	"time"

	FikoYTCtx "server/sistem/fikoyt_ctx"
	fiko_mongo "server/sistem/fikoyt_mongo"

	"github.com/gofiber/fiber/v3"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo/options"
)

// --- Mesaj Sınıflandırma (Intent Detection) ---

func mesajBilgiSorgusuMu(mesaj string) bool {
	temiz := strings.ToLower(strings.TrimSpace(mesaj))
	if len(temiz) < 3 {
		return false
	}

	// Kesin sohbet/selamlaşma kalıpları
	selamlar := []string{
		"merhaba", "selam", "hey", "naber", "nasılsın", "iyi günler",
		"günaydın", "iyi akşamlar", "iyi geceler", "hoşça kal",
		"teşekkürler", "sağol", "tamam", "ok", "evet", "hayır",
		"anladım", "peki", "görüşürüz", "bye", "bb", "sa", "as",
		"selamun aleyküm", "aleyküm selam", "merhabalar", "tşk",
		"ne yapabilirsin", "yardım et", "yardım",
	}
	for _, s := range selamlar {
		if temiz == s {
			return false
		}
	}

	// Veri sorgusu anahtar kelimeleri — bunlar varsa kesinlikle RAG gerekli
	veriKelimeleri := []string{
		"kaç", "kim", "kimin", "nerede", "hangi", "listele", "göster",
		"bul", "ara", "say", "toplam", "istatistik", "rapor",
		"firma", "personel", "cihaz", "makine", "sipariş", "üretim",
		"bakım", "vardiya", "kalite", "enerji", "cnc", "mail",
		"soyağacı", "akraba", "amca", "dayı", "baba", "anne", "eş",
		"kayıt", "veri", "durum", "son ", "bugün", "dün",
	}
	for _, k := range veriKelimeleri {
		if strings.Contains(temiz, k) {
			return true
		}
	}

	// Soru işareti varsa muhtemelen bilgi sorgusu
	if strings.Contains(temiz, "?") {
		return true
	}

	// 3+ kelime ve kısa değilse muhtemelen bilgi sorgusu
	kelimeler := strings.Fields(temiz)
	if len(kelimeler) >= 4 {
		return true
	}

	return false
}

// --- Rate Limiter ---

var (
	aktifChatler   = map[string]int{}
	aktifChatlerMu sync.Mutex
)

func rateLimitKontrol(kullaniciId string) bool {
	aktifChatlerMu.Lock()
	defer aktifChatlerMu.Unlock()
	return aktifChatler[kullaniciId] < ragAyar().MaxChatPerUser
}

func rateLimitAl(kullaniciId string) {
	aktifChatlerMu.Lock()
	aktifChatler[kullaniciId]++
	aktifChatlerMu.Unlock()
}

func rateLimitBirak(kullaniciId string) {
	aktifChatlerMu.Lock()
	if aktifChatler[kullaniciId] > 0 {
		aktifChatler[kullaniciId]--
	}
	aktifChatlerMu.Unlock()
}

// --- Tool Kullanım Analizi ---

const ToolKullanimVT = "FikoYT.sistem.rag.tool_kullanim"

func toolKullanimLogla(toolAdi string, kullaniciId string, sureMs int64, basarili bool, hata string) {
	ctx := context.TODO()
	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")

	doc := bson.M{
		"vt": ToolKullanimVT,
		"veri": bson.M{
			"tool":          toolAdi,
			"kullanici_id":  kullaniciId,
			"sure_ms":       sureMs,
			"basarili":      basarili,
			"hata":          hata,
		},
		"olusturma": time.Now(),
	}

	kol.InsertOne(ctx, doc)
}

func toolKullanimHandler(c fiber.Ctx) error {
	if ayarAdminKontrol(c) == nil {
		return c.Status(403).JSON(fiber.Map{"hata": "Yetkiniz yok"})
	}
	ctx := context.TODO()
	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")

	pipeline := []bson.M{
		{"$match": bson.M{"vt": ToolKullanimVT}},
		{"$group": bson.M{
			"_id":          "$veri.tool",
			"toplam":       bson.M{"$sum": 1},
			"basarili":     bson.M{"$sum": bson.M{"$cond": bson.A{"$veri.basarili", 1, 0}}},
			"ortSure":      bson.M{"$avg": "$veri.sure_ms"},
			"sonKullanim":  bson.M{"$max": "$olusturma"},
		}},
		{"$sort": bson.M{"toplam": -1}},
	}

	cursor, err := kol.Aggregate(ctx, pipeline)
	if err != nil {
		return c.Status(500).JSON(fiber.Map{"hata": err.Error()})
	}

	var sonuclar []bson.M
	cursor.All(ctx, &sonuclar)
	if sonuclar == nil {
		sonuclar = []bson.M{}
	}

	return c.JSON(fiber.Map{"toollar": sonuclar})
}

// --- Shared Context Builder ---

type SohbetBaglam struct {
	KonusmaId      primitive.ObjectID
	Mesajlar       []map[string]string
	RagSonuclar    []bson.M
	KaynakIdler    []string
	KullaniciMesaj bson.M
	Fk             *FikoYTCtx.FikoYTCtx
	KullaniciIdStr string
	YeniMi         bool
	Resimler       []string
}

const (
	maxDosyaSayisi     = 5
	maxMetinDosyaChar  = 30000
	maxResimBase64Byte = 12 * 1024 * 1024
)

func sohbetBaglamiHazirla(c fiber.Ctx) (*SohbetBaglam, error) {
	fk, err := kullaniciAl(c)
	if err != nil {
		return nil, err
	}

	var istek struct {
		KonusmaID string `json:"konusma_id"`
		Mesaj     string `json:"mesaj"`
		VT        string `json:"vt"`
		Dosyalar  []struct {
			Isim   string `json:"isim"`
			Tip    string `json:"tip"` // "metin" | "resim"
			Icerik string `json:"icerik"`
		} `json:"dosyalar"`
	}
	json.Unmarshal(c.Body(), &istek)

	if istek.Mesaj == "" && len(istek.Dosyalar) == 0 {
		return nil, c.Status(400).JSON(fiber.Map{"hata": "mesaj gerekli"})
	}
	if istek.Mesaj == "" {
		istek.Mesaj = "Eklediğim dosyaları incele ve özetle."
	}
	if len(istek.Dosyalar) > maxDosyaSayisi {
		return nil, c.Status(400).JSON(fiber.Map{"hata": fmt.Sprintf("En fazla %d dosya eklenebilir", maxDosyaSayisi)})
	}

	// Dosyaları ayrıştır: metinler bağlama, resimler vision modele
	var dosyaBaglam strings.Builder
	var resimler []string
	var dosyaMeta bson.A
	toplamResimByte := 0
	for _, d := range istek.Dosyalar {
		if d.Isim == "" || d.Icerik == "" {
			continue
		}
		if d.Tip == "resim" {
			toplamResimByte += len(d.Icerik)
			if toplamResimByte > maxResimBase64Byte {
				return nil, c.Status(413).JSON(fiber.Map{"hata": "Resimler çok büyük (toplam ~12MB sınırı)"})
			}
			resimler = append(resimler, d.Icerik)
			dosyaMeta = append(dosyaMeta, bson.M{"isim": d.Isim, "tip": "resim"})
		} else {
			icerik := d.Icerik
			if len(icerik) > maxMetinDosyaChar {
				icerik = icerik[:maxMetinDosyaChar] + "\n...[dosya kısaltıldı]"
			}
			dosyaBaglam.WriteString(fmt.Sprintf("--- DOSYA: %s ---\n%s\n\n", d.Isim, icerik))
			dosyaMeta = append(dosyaMeta, bson.M{"isim": d.Isim, "tip": "metin"})
		}
	}

	kullaniciId := fk.AktifKullanici.IsleObjectId().Id
	kullaniciIdStr := fmt.Sprintf("%v", kullaniciId)

	if !rateLimitKontrol(kullaniciIdStr) {
		return nil, c.Status(429).JSON(fiber.Map{"hata": "Çok fazla eşzamanlı sohbet. Lütfen bekleyin."})
	}

	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")

	var konusmaId primitive.ObjectID
	var mevcutIcerikler bson.A
	yeniMi := false

	if istek.KonusmaID != "" {
		oid, err := primitive.ObjectIDFromHex(istek.KonusmaID)
		if err != nil {
			return nil, c.Status(400).JSON(fiber.Map{"hata": "Geçersiz konuşma ID"})
		}
		var doc bson.M
		err = kol.FindOne(context.TODO(), bson.M{
			"_id":               oid,
			"vt":                SohbetVT,
			"veri.kullanici_id": kullaniciId,
		}).Decode(&doc)
		if err != nil {
			return nil, c.Status(404).JSON(fiber.Map{"hata": "Sohbet bulunamadı"})
		}
		konusmaId = oid
		if ic, ok := doc["icerikler"].(bson.A); ok {
			mevcutIcerikler = ic
		}
	} else {
		isim := fmt.Sprintf("%v", fk.AktifKullanici.Isim)
		baslik := istek.Mesaj
		if len(baslik) > 60 {
			baslik = guvenliKes(baslik, 60) + "..."
		}
		result, err := kol.InsertOne(context.TODO(), bson.M{
			"vt": SohbetVT,
			"veri": bson.M{
				"baslik":         baslik,
				"kullanici_id":   kullaniciId,
				"kullanici_ismi": isim,
				"sezon_id":       sezonIdAl(fk),
			},
			"icerikler":  bson.A{},
			"olusturma":  time.Now(),
			"guncelleme": time.Now(),
		})
		if err != nil {
			return nil, c.Status(500).JSON(fiber.Map{"hata": err.Error()})
		}
		konusmaId = result.InsertedID.(primitive.ObjectID)
		yeniMi = true
	}

	kullaniciMesaj := bson.M{
		"rol":   "kullanici",
		"metin": istek.Mesaj,
		"zaman": time.Now(),
	}
	if len(dosyaMeta) > 0 {
		kullaniciMesaj["dosyalar"] = dosyaMeta
	}

	var gecmisMesajlar []map[string]string
	for _, ic := range mevcutIcerikler {
		if m, ok := ic.(bson.M); ok {
			rol, _ := m["rol"].(string)
			metin, _ := m["metin"].(string)
			if rol == "kullanici" {
				gecmisMesajlar = append(gecmisMesajlar, map[string]string{"role": "user", "content": metin})
			} else if rol == "asistan" {
				gecmisMesajlar = append(gecmisMesajlar, map[string]string{"role": "assistant", "content": metin})
			}
		}
	}

	// Mesaj sınıflandırma — basit sohbet mi yoksa veri sorgusu mu?
	aktifAyar := ragAyar()
	bilgiSorgusuMu := aktifAyar.RagAktif && mesajBilgiSorgusuMu(istek.Mesaj)
	superMi := fk.AktifKullanici.YetkiVarmi("Super Yonetici")

	var kisiselBaglam, sistemBaglam, sabitBaglam string
	var sonuclar []bson.M

	if bilgiSorgusuMu {
		kisiselBaglam = kullaniciBaglamiOlustur(kullaniciId, fk)
		if superMi {
			sistemBaglam = sistemIstatistikBaglami()
		}
		sabitBaglam = sabitBaglamYukle()

		// Soru tipine göre kaynak sayısı ayarla
		limit := aktifAyar.RagLimit
		temiz := strings.ToLower(strings.TrimSpace(istek.Mesaj))
		if strings.Contains(temiz, "listele") || strings.Contains(temiz, "tümü") || strings.Contains(temiz, "hepsi") {
			limit = aktifAyar.RagLimit * 2
		} else if strings.Contains(temiz, "kaç") || strings.Contains(temiz, "toplam") {
			limit = (aktifAyar.RagLimit + 1) / 2
		}
		if superMi {
			sonuclar, _ = AraMetin(istek.Mesaj, limit, istek.VT)
		} else {
			// Yönetici olmayanlar yalnızca izinli vt'lerde arar (gizlilik sınırı)
			sonuclar, _ = AraMetinIzinli(istek.Mesaj, limit, istek.VT, herkeseAcikVtListesi())
		}
	} else {
		log.Printf("💬 Basit sohbet — RAG atlandı: %q", istek.Mesaj)
	}

	var baglam strings.Builder
	if sabitBaglam != "" {
		baglam.WriteString("=== SABİT SİSTEM DOKÜMANLARI ===\n")
		baglam.WriteString(sabitBaglam)
		baglam.WriteString("\n")
	}
	if sistemBaglam != "" {
		baglam.WriteString("=== SİSTEM İSTATİSTİKLERİ ===\n")
		baglam.WriteString(sistemBaglam)
	}
	if kisiselBaglam != "" {
		baglam.WriteString("\n=== KULLANICI BİLGİLERİ ===\n")
		baglam.WriteString(kisiselBaglam)
	}
	if len(sonuclar) > 0 {
		baglam.WriteString("\n=== VERİTABANI KAYITLARI ===\n")
		for i, s := range sonuclar {
			if metin, ok := s["metin"].(string); ok {
				if len(metin) > 500 {
					metin = guvenliKes(metin, 500) + "..."
				}
				baglam.WriteString(fmt.Sprintf("--- Kayıt %d ---\n%s\n", i+1, metin))
			}
		}
	}
	if dosyaBaglam.Len() > 0 {
		baglam.WriteString("\n=== KULLANICININ EKLEDİĞİ DOSYALAR ===\n")
		baglam.WriteString(dosyaBaglam.String())
	}
	if len(resimler) > 0 {
		baglam.WriteString(fmt.Sprintf("\n(Kullanıcı %d adet görsel ekledi — görselleri incele ve soruya göre yorumla.)\n", len(resimler)))
	}

	isim := fmt.Sprintf("%v", fk.AktifKullanici.Isim)
	soyIsim := fmt.Sprintf("%v", fk.AktifKullanici.SoyIsim)

	sistemPrompt := fmt.Sprintf(`Sen FikoYT üretim yönetim sisteminin yapay zeka asistanısın. Şu an seninle konuşan kullanıcı: %s %s.

KESİN KURALLAR:
1. HER ZAMAN TÜRKÇE CEVAP VER. Asla İngilizce kullanma.
2. DOĞAL DİL KULLAN — konuya tamamen hakimmiş gibi konuş. Asla 'kayıtlara göre', 'veritabanında şöyle yazıyor', 'burada böyle kaydedilmiş', 'dokümanda şöyle belirtilmiş' gibi ifadeler KULLANMA. Bilgiyi doğrudan ve özgüvenle aktar, sanki kendi bilginmiş gibi.
3. Kaynak belirtme: Kullanıcı açıkça 'nereden biliyorsun', 'kaynağın ne' diye sorarsa o zaman kaynağı söyle. Sorulmadıkça kaynak gösterme.
4. Kullanıcı 'benim', 'ben', 'amcam', 'babam', 'eşim' gibi kişisel sorular sorarsa soyağacı ve akrabalık verilerini kullan.
5. Verilen bağlamdaki bilgileri derinlemesine analiz et, doğrudan bilgi olmasa bile çıkarım yap.
6. Sayısal veriler varsa hesapla, listele, karşılaştır.
7. Kısa ve net cevaplar ver. Gereksiz açıklama yapma.
8. Emin olmadığın konularda 'muhtemelen' veya 'büyük ihtimalle' gibi yumuşak ifadeler kullan.

%s

AKRABALIK BAĞLARI KURALLARI:
- Akrabalık bağları kullanıcıya göre yönlendirilmiştir. Örneğin 'Babası: Mehmet' demek Mehmet kullanıcının babasıdır.
- aileBaglari kayıtlarında 'sahip' alanı kaydı oluşturan kişiyi belirtir, akrabalık ilişkisindeki kişiyi DEĞİL.
- Akrabalık yönü: kisi1'in kisi2'ye olan ilişkisi akrabalikTuru ile belirtilir. Örn: kisi1=A, kisi2=B, akrabalikTuru=COCUK demek A'nın çocuğu B'dir.
- Akrabalık soruları için SADECE kullanıcı bilgilerindeki bağları kullan.

TÜRKÇE AKRABALIK TERİMLERİ:
- AMCA = babanın erkek kardeşi
- DAYI = annenin erkek kardeşi
- HALA = babanın kız kardeşi
- TEYZE = annenin kız kardeşi
- YEGEN = kardeşin çocuğu
- KUZEN = amca/dayı/hala/teyze çocuğu
- KAYINVALIDE = eşin annesi
- KAYINPEDER = eşin babası
- BALDIZ = eşin kız kardeşi
- KAYINBIRADER = eşin erkek kardeşi
- GELIN = oğlun eşi
- DAMAT = kızın eşi
- ENISTE = kız kardeşin veya halanın/teyzenin eşi
- YENGE = erkek kardeşin veya amcanın/dayının eşi
- Bu terimleri doğru kullan, karıştırma.`, isim, soyIsim, bilesenBolumu())

	if !superMi {
		sistemPrompt += gizlilikPromptu()
	}

	if aktifAyar.SistemPromptEk != "" {
		sistemPrompt += "\n\nYÖNETİCİ TALİMATLARI:\n" + aktifAyar.SistemPromptEk
	}

	mesajlar := []map[string]string{
		{"role": "system", "content": sistemPrompt},
	}

	baslangic := 0
	if len(gecmisMesajlar) > aktifAyar.GecmisMesajSayisi {
		baslangic = len(gecmisMesajlar) - aktifAyar.GecmisMesajSayisi
	}
	mesajlar = append(mesajlar, gecmisMesajlar[baslangic:]...)

	mesajlar = append(mesajlar, map[string]string{
		"role":    "user",
		"content": fmt.Sprintf("Bağlam:\n%s\n\nSoru: %s", baglam.String(), istek.Mesaj),
	})

	var kaynakIdler []string
	for _, s := range sonuclar {
		if hid, ok := s["hareket_id"].(primitive.ObjectID); ok {
			kaynakIdler = append(kaynakIdler, hid.Hex())
		}
	}

	return &SohbetBaglam{
		KonusmaId:      konusmaId,
		Mesajlar:       mesajlar,
		RagSonuclar:    sonuclar,
		KaynakIdler:    kaynakIdler,
		KullaniciMesaj: kullaniciMesaj,
		Fk:             fk,
		KullaniciIdStr: kullaniciIdStr,
		YeniMi:         yeniMi,
		Resimler:       resimler,
	}, nil
}

// --- Streaming Agent Handler ---

func konusmaStreamHandler(c fiber.Ctx) error {
	baglam, err := sohbetBaglamiHazirla(c)
	if err != nil {
		return err
	}

	rateLimitAl(baglam.KullaniciIdStr)
	ChatBasladi()

	c.Set("Content-Type", "text/event-stream")
	c.Set("Cache-Control", "no-cache")
	c.Set("Connection", "keep-alive")
	c.Set("X-Accel-Buffering", "no")

	konusmaId := baglam.KonusmaId
	kullaniciMesaj := baglam.KullaniciMesaj
	kullaniciIdStr := baglam.KullaniciIdStr

	c.Context().SetBodyStreamWriter(func(w *bufio.Writer) {
		defer ChatBitti()
		defer rateLimitBirak(kullaniciIdStr)

		streamBaslangic := time.Now()

		streamYaz := func(tip string, veri map[string]interface{}) {
			veri["t"] = tip
			data, _ := json.Marshal(veri)
			fmt.Fprintf(w, "data: %s\n\n", data)
			w.Flush()
		}

		cevapMetin, dusunceMetin, adimlar := agentDongusu(baglam, streamYaz)

		if cevapMetin == "" {
			cevapMetin = "Yanıt üretilemedi."
		}

		toolSayisi := 0
		for _, a := range adimlar {
			if a.Tip == "tool_cagri" {
				toolSayisi++
			}
		}

		asistanMesaj := bson.M{
			"rol":     "asistan",
			"metin":   cevapMetin,
			"zaman":   time.Now(),
			"sure_ms": time.Since(streamBaslangic).Milliseconds(),
		}
		if dusunceMetin != "" {
			asistanMesaj["dusunce"] = dusunceMetin
		}
		if len(adimlar) > 0 {
			asistanMesaj["agent_adimlar"] = adimlarToBson(adimlar)
			asistanMesaj["tool_sayisi"] = toolSayisi
		}

		kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")
		kol.UpdateOne(context.TODO(),
			bson.M{"_id": konusmaId},
			bson.M{
				"$push": bson.M{
					"icerikler": bson.M{"$each": bson.A{kullaniciMesaj, asistanMesaj}},
				},
				"$set": bson.M{"guncelleme": time.Now()},
			},
		)

		data, _ := json.Marshal(map[string]interface{}{
			"t":           "bitti",
			"konusma_id":  konusmaId.Hex(),
			"tool_sayisi": toolSayisi,
			"sure_ms":     time.Since(streamBaslangic).Milliseconds(),
		})
		fmt.Fprintf(w, "data: %s\n\n", data)
		w.Flush()
	})

	return nil
}

// --- Feedback Handler ---

func feedbackHandler(c fiber.Ctx) error {
	fk, err := kullaniciAl(c)
	if err != nil {
		return err
	}

	var istek struct {
		KonusmaID  string `json:"konusma_id"`
		MesajIndex int    `json:"mesaj_index"`
		Tip        string `json:"tip"`
		Not        string `json:"not"`
	}
	json.Unmarshal(c.Body(), &istek)

	if istek.Tip != "begeni" && istek.Tip != "begenmeme" {
		return c.Status(400).JSON(fiber.Map{"hata": "tip begeni veya begenmeme olmalı"})
	}

	oid, err := primitive.ObjectIDFromHex(istek.KonusmaID)
	if err != nil {
		return c.Status(400).JSON(fiber.Map{"hata": "Geçersiz konuşma ID"})
	}

	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")
	kullaniciId := fk.AktifKullanici.IsleObjectId().Id

	alanYolu := fmt.Sprintf("icerikler.%d.feedback", istek.MesajIndex)
	_, err = kol.UpdateOne(context.TODO(),
		bson.M{
			"_id":               oid,
			"vt":                SohbetVT,
			"veri.kullanici_id": kullaniciId,
		},
		bson.M{
			"$set": bson.M{
				alanYolu: bson.M{
					"tip":   istek.Tip,
					"not":   istek.Not,
					"zaman": time.Now(),
				},
			},
		},
	)
	if err != nil {
		return c.Status(500).JSON(fiber.Map{"hata": err.Error()})
	}

	go feedbackLogla(istek.Tip, istek.Not, fmt.Sprintf("%v", kullaniciId))

	return c.JSON(fiber.Map{"basarili": true})
}

func feedbackLogla(tip string, not string, kullaniciId string) {
	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")
	kol.InsertOne(context.TODO(), bson.M{
		"vt": "FikoYT.sistem.rag.feedback",
		"veri": bson.M{
			"tip":          tip,
			"not":          not,
			"kullanici_id": kullaniciId,
		},
		"olusturma": time.Now(),
	})
}

// --- Feedback Analiz ---

func feedbackAnalizHandler(c fiber.Ctx) error {
	if ayarAdminKontrol(c) == nil {
		return c.Status(403).JSON(fiber.Map{"hata": "Yetkiniz yok"})
	}
	ctx := context.TODO()
	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")

	pipeline := []bson.M{
		{"$match": bson.M{"vt": "FikoYT.sistem.rag.feedback"}},
		{"$group": bson.M{
			"_id":    "$veri.tip",
			"toplam": bson.M{"$sum": 1},
		}},
	}

	cursor, err := kol.Aggregate(ctx, pipeline)
	if err != nil {
		return c.Status(500).JSON(fiber.Map{"hata": err.Error()})
	}

	var sonuclar []bson.M
	cursor.All(ctx, &sonuclar)

	sonFeedbackler, _ := kol.Find(ctx,
		bson.M{"vt": "FikoYT.sistem.rag.feedback", "veri.tip": "begenmeme"},
		options.Find().SetSort(bson.M{"olusturma": -1}).SetLimit(20),
	)
	var olumsuzlar []bson.M
	if sonFeedbackler != nil {
		sonFeedbackler.All(ctx, &olumsuzlar)
	}

	return c.JSON(fiber.Map{
		"ozet":              sonuclar,
		"son_olumsuzlar":    olumsuzlar,
	})
}

// --- Konuşma Özetleme (Sliding Window) ---

func konusmaOzetle(mevcutIcerikler bson.A) []map[string]string {
	if len(mevcutIcerikler) <= 12 {
		var mesajlar []map[string]string
		for _, ic := range mevcutIcerikler {
			if m, ok := ic.(bson.M); ok {
				rol, _ := m["rol"].(string)
				metin, _ := m["metin"].(string)
				if rol == "kullanici" {
					mesajlar = append(mesajlar, map[string]string{"role": "user", "content": metin})
				} else if rol == "asistan" {
					mesajlar = append(mesajlar, map[string]string{"role": "assistant", "content": metin})
				}
			}
		}
		return mesajlar
	}

	eskiSayi := len(mevcutIcerikler) - 6
	var eskiMesajlar strings.Builder
	for i := 0; i < eskiSayi; i++ {
		if m, ok := mevcutIcerikler[i].(bson.M); ok {
			rol, _ := m["rol"].(string)
			metin, _ := m["metin"].(string)
			if len(metin) > 200 {
				metin = guvenliKes(metin, 200) + "..."
			}
			if rol == "kullanici" {
				eskiMesajlar.WriteString(fmt.Sprintf("Kullanıcı: %s\n", metin))
			} else {
				eskiMesajlar.WriteString(fmt.Sprintf("Asistan: %s\n", metin))
			}
		}
	}

	ozet, err := ollamaChat([]map[string]string{
		{"role": "system", "content": "Aşağıdaki sohbet geçmişini 3-4 cümleyle özetle. Türkçe yaz. Sadece önemli konuları ve kararları belirt."},
		{"role": "user", "content": eskiMesajlar.String()},
	})
	if err != nil || ozet == "" {
		ozet = "Önceki konuşma özetlenemedi."
	}

	sonucMesajlar := []map[string]string{
		{"role": "assistant", "content": fmt.Sprintf("[Önceki sohbet özeti: %s]", ozet)},
	}

	for i := eskiSayi; i < len(mevcutIcerikler); i++ {
		if m, ok := mevcutIcerikler[i].(bson.M); ok {
			rol, _ := m["rol"].(string)
			metin, _ := m["metin"].(string)
			if rol == "kullanici" {
				sonucMesajlar = append(sonucMesajlar, map[string]string{"role": "user", "content": metin})
			} else if rol == "asistan" {
				sonucMesajlar = append(sonucMesajlar, map[string]string{"role": "assistant", "content": metin})
			}
		}
	}

	return sonucMesajlar
}
