package rag

import (
	"bufio"
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"sync"
	"time"

	fiko_mongo "server/sistem/fikoyt_mongo"

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

var mcpOturumlar sync.Map

type jsonRpcIstek struct {
	Jsonrpc string          `json:"jsonrpc"`
	ID      interface{}     `json:"id,omitempty"`
	Method  string          `json:"method"`
	Params  json.RawMessage `json:"params,omitempty"`
}

type jsonRpcCevap struct {
	Jsonrpc string       `json:"jsonrpc"`
	ID      interface{}  `json:"id,omitempty"`
	Result  interface{}  `json:"result,omitempty"`
	Error   *jsonRpcHata `json:"error,omitempty"`
}

type jsonRpcHata struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

// --- SSE Transport ---

func mcpSSEHandler(c fiber.Ctx) error {
	if !mcpErisimVarMi(c) {
		return c.Status(401).JSON(fiber.Map{"error": "MCP erişimi için anahtar gerekli (admin panelden ayarlanır)"})
	}
	c.Set("Content-Type", "text/event-stream")
	c.Set("Cache-Control", "no-cache")
	c.Set("Connection", "keep-alive")

	sessionId := uuid.New().String()
	ch := make(chan []byte, 100)
	mcpOturumlar.Store(sessionId, ch)

	c.Context().SetBodyStreamWriter(func(w *bufio.Writer) {
		defer mcpOturumlar.Delete(sessionId)

		fmt.Fprintf(w, "event: endpoint\ndata: /rag/mcp/messages?sessionId=%s\n\n", sessionId)
		w.Flush()

		ticker := time.NewTicker(30 * time.Second)
		defer ticker.Stop()

		for {
			select {
			case data, ok := <-ch:
				if !ok {
					return
				}
				fmt.Fprintf(w, "event: message\ndata: %s\n\n", data)
				w.Flush()
			case <-ticker.C:
				fmt.Fprintf(w, ": keepalive\n\n")
				w.Flush()
			}
		}
	})

	return nil
}

func mcpMesajHandler(c fiber.Ctx) error {
	if !mcpErisimVarMi(c) {
		return c.Status(401).JSON(fiber.Map{"error": "MCP erişimi için anahtar gerekli"})
	}
	sessionId := c.Query("sessionId")
	chI, ok := mcpOturumlar.Load(sessionId)
	if !ok {
		return c.Status(404).JSON(fiber.Map{"error": "Oturum bulunamadı"})
	}
	ch := chI.(chan []byte)

	var istek jsonRpcIstek
	if err := json.Unmarshal(c.Body(), &istek); err != nil {
		return c.Status(400).JSON(fiber.Map{"error": "Geçersiz JSON"})
	}

	cevap := mcpIsle(istek)

	if istek.ID == nil {
		return c.Status(202).Send(nil)
	}

	data, _ := json.Marshal(cevap)
	ch <- data

	return c.Status(202).Send(nil)
}

// --- Streamable HTTP Transport ---

func mcpStreamableHandler(c fiber.Ctx) error {
	if !mcpErisimVarMi(c) {
		return c.Status(401).JSON(fiber.Map{"error": "MCP erişimi için anahtar gerekli"})
	}
	var istek jsonRpcIstek
	if err := json.Unmarshal(c.Body(), &istek); err != nil {
		return c.JSON(jsonRpcCevap{
			Jsonrpc: "2.0",
			Error:   &jsonRpcHata{Code: -32700, Message: "Parse hatası"},
		})
	}

	cevap := mcpIsle(istek)

	if istek.ID == nil {
		return c.Status(204).Send(nil)
	}

	return c.JSON(cevap)
}

// --- MCP İşleme ---

func mcpIsle(istek jsonRpcIstek) jsonRpcCevap {
	switch istek.Method {
	case "initialize":
		return jsonRpcCevap{
			Jsonrpc: "2.0",
			ID:      istek.ID,
			Result: fiber.Map{
				"protocolVersion": "2024-11-05",
				"capabilities":    fiber.Map{"tools": fiber.Map{}},
				"serverInfo":      fiber.Map{"name": "FikoYT RAG", "version": "1.0.0"},
			},
		}
	case "tools/list":
		tumToollar := mcpToolTanimlari()
		tumToollar = append(tumToollar, customToolMCPTanimlari()...)
		return jsonRpcCevap{
			Jsonrpc: "2.0",
			ID:      istek.ID,
			Result:  fiber.Map{"tools": tumToollar},
		}
	case "tools/call":
		return mcpToolCagir(istek)
	default:
		return jsonRpcCevap{
			Jsonrpc: "2.0",
			ID:      istek.ID,
			Error:   &jsonRpcHata{Code: -32601, Message: "Bilinmeyen metod: " + istek.Method},
		}
	}
}

// --- Tool Tanımları ---

func mcpToolTanimlari() []fiber.Map {
	return []fiber.Map{
		{
			"name":        "hareketler_ara",
			"description": "FikoYT veritabanında semantik arama yapar. Tüm kayıtları (firma, personel, sipariş, üretim, bakım, mail vb.) doğal dille arayabilirsiniz.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"sorgu": fiber.Map{"type": "string", "description": "Aranacak metin (doğal dil)"},
					"limit": fiber.Map{"type": "number", "description": "Maksimum sonuç sayısı (varsayılan: 10)"},
					"vt":    fiber.Map{"type": "string", "description": "VT tipi filtresi (ör: FikoYT.sistem.firma.personeller)"},
				},
				"required": []string{"sorgu"},
			},
		},
		{
			"name":        "hareket_getir",
			"description": "Belirli bir kaydı ID ile getirir. Tüm alanları (veri, içerikler, ekler, dosyalar) döner.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"id": fiber.Map{"type": "string", "description": "Kayıt ID (MongoDB ObjectId hex string)"},
				},
				"required": []string{"id"},
			},
		},
		{
			"name":        "soru_sor",
			"description": "Veritabanındaki bilgileri kullanarak soruyu yanıtlar (RAG). Önce ilgili kayıtları bulur, sonra yapay zeka ile Türkçe cevap üretir.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"soru": fiber.Map{"type": "string", "description": "Sorulacak soru (Türkçe)"},
					"vt":   fiber.Map{"type": "string", "description": "Belirli bir VT tipinde arama (opsiyonel)"},
				},
				"required": []string{"soru"},
			},
		},
		{
			"name":        "vt_listele",
			"description": "Veritabanındaki tüm veri tiplerini (VT) ve her birinin kayıt sayısını listeler.",
			"inputSchema": fiber.Map{
				"type":       "object",
				"properties": fiber.Map{},
			},
		},
		{
			"name":        "istatistik",
			"description": "Veritabanı istatistiklerini gösterir: toplam kayıt, gömme (embedding) durumu, VT dağılımı.",
			"inputSchema": fiber.Map{
				"type":       "object",
				"properties": fiber.Map{},
			},
		},
		{
			"name":        "hareket_ekle",
			"description": "Yeni bir kayıt ekler. VT (veri tipi) ve veri alanları gereklidir.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"vt":   fiber.Map{"type": "string", "description": "Veri tipi (ör: FikoYT.sistem.firma.personeller)"},
					"veri": fiber.Map{"type": "object", "description": "Kayıt verileri"},
				},
				"required": []string{"vt", "veri"},
			},
		},
		{
			"name":        "hareket_guncelle",
			"description": "Mevcut bir kaydı günceller.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"id":   fiber.Map{"type": "string", "description": "Kayıt ID"},
					"veri": fiber.Map{"type": "object", "description": "Güncellenecek alanlar"},
				},
				"required": []string{"id", "veri"},
			},
		},
		{
			"name":        "soyagaci_akrabalar",
			"description": "Bir kişinin tüm akrabalarını getirir. Kişi ID veya isim ile arama yapabilir. Akrabalık türleri: ANNE, BABA, ES, COCUK, KARDES, AMCA, DAYI, HALA, TEYZE, KUZEN, DEDE, NINE, TORUN, GELIN, DAMAT, KAYINVALIDE, KAYINPEDER, ENISTE, BALDIZ, YENGE, GORUMCE, DUNUR vb.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"kisi_id": fiber.Map{"type": "string", "description": "Soyağacı kişi ID (ObjectId hex). Boş bırakılırsa isim ile aranır."},
					"isim":    fiber.Map{"type": "string", "description": "Kişi ismi ile arama (kisi_id yoksa kullanılır)"},
					"tur":     fiber.Map{"type": "string", "description": "Belirli akrabalık türü filtresi (ör: AMCA, ES, COCUK). Boş bırakılırsa tümü döner."},
				},
			},
		},
		{
			"name":        "akrabalik_bul",
			"description": "İki kişi arasındaki akrabalık ilişkisini bulur. BFS/DFS graf traversal ile en kısa yolu hesaplar ve Türkçe açıklama döner.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"kisi1_id":   fiber.Map{"type": "string", "description": "Birinci kişi ID (ObjectId hex)"},
					"kisi1_isim": fiber.Map{"type": "string", "description": "Birinci kişi ismi (kisi1_id yoksa kullanılır)"},
					"kisi2_id":   fiber.Map{"type": "string", "description": "İkinci kişi ID (ObjectId hex)"},
					"kisi2_isim": fiber.Map{"type": "string", "description": "İkinci kişi ismi (kisi2_id yoksa kullanılır)"},
				},
			},
		},
		{
			"name":        "soyagaci_kisi_bul",
			"description": "Soyağacında kişi arar. İsim, soyisim veya meslek ile arama yapabilir. Kişinin tüm bilgilerini döner: isim, soyisim, cinsiyet, doğum/ölüm tarihi, meslek, medeni durum, biyografi.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"arama": fiber.Map{"type": "string", "description": "Aranacak metin (isim, soyisim veya meslek)"},
					"limit": fiber.Map{"type": "number", "description": "Maksimum sonuç (varsayılan: 10)"},
				},
				"required": []string{"arama"},
			},
		},
		{
			"name":        "firma_sorgula",
			"description": "Firma, personel, departman bilgilerini sorgular. Firma adı, personel ismi, departman ile arama yapabilir.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"tip":   fiber.Map{"type": "string", "description": "Sorgu tipi: firma, personel, departman", "enum": []string{"firma", "personel", "departman"}},
					"arama": fiber.Map{"type": "string", "description": "Aranacak metin"},
					"limit": fiber.Map{"type": "number", "description": "Maksimum sonuç (varsayılan: 20)"},
				},
				"required": []string{"tip"},
			},
		},
		{
			"name":        "cihaz_sorgula",
			"description": "IoT cihazları sorgular. Cihaz listesi, durum bilgisi, son olaylar, telemetri verilerini getirir.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"tip":       fiber.Map{"type": "string", "description": "Sorgu tipi: liste, durum, olaylar", "enum": []string{"liste", "durum", "olaylar"}},
					"cihaz_id":  fiber.Map{"type": "string", "description": "Cihaz ID veya cihaz kimliği (tip=durum/olaylar için)"},
					"limit":     fiber.Map{"type": "number", "description": "Maksimum sonuç (varsayılan: 20)"},
				},
				"required": []string{"tip"},
			},
		},
		{
			"name":        "kullanici_sorgula",
			"description": "Platform kullanıcılarını sorgular. Kullanıcı listesi, detay bilgileri, aktif oturumlar.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"tip":   fiber.Map{"type": "string", "description": "Sorgu tipi: liste, detay, aktif", "enum": []string{"liste", "detay", "aktif"}},
					"arama": fiber.Map{"type": "string", "description": "İsim veya ID ile arama"},
				},
				"required": []string{"tip"},
			},
		},
		{
			"name":        "aggregate_sorgula",
			"description": "MongoDB aggregation pipeline çalıştırır. Gelişmiş sorgular, gruplama, sayma, istatistik çıkarma için kullanılır. Koleksiyon hareketler üzerinde çalışır.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"pipeline":   fiber.Map{"type": "array", "description": "MongoDB aggregation pipeline dizisi. Her eleman bir stage ($match, $group, $sort, $project, $lookup, $unwind, $limit, $count vb.)"},
					"koleksiyon": fiber.Map{"type": "string", "description": "Koleksiyon adı (varsayılan: hareketler). Diğer: goUyeler, goCihazlar, goSoketler"},
				},
				"required": []string{"pipeline"},
			},
		},
		{
			"name":        "kayit_say",
			"description": "Belirli filtreye uyan kayıt sayısını döner. Hızlı sayma işlemi.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"vt":     fiber.Map{"type": "string", "description": "VT filtresi (ör: FikoYT.sistem.firmalar)"},
					"filtre": fiber.Map{"type": "object", "description": "MongoDB filtre objesi (opsiyonel, ek filtre)"},
				},
				"required": []string{"vt"},
			},
		},
		{
			"name":        "hareket_sil",
			"description": "Bir kaydı siler. Dikkatli kullanılmalıdır.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"id": fiber.Map{"type": "string", "description": "Silinecek kayıt ID"},
				},
				"required": []string{"id"},
			},
		},
		{
			"name":        "mail_sorgula",
			"description": "Mail mesajlarını sorgular. Konu, gönderen, tarih ile arama. Mail hesaplarını listeler.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"tip":   fiber.Map{"type": "string", "description": "Sorgu tipi: mesajlar, hesaplar", "enum": []string{"mesajlar", "hesaplar"}},
					"arama": fiber.Map{"type": "string", "description": "Konu veya gönderen araması"},
					"limit": fiber.Map{"type": "number", "description": "Maksimum sonuç (varsayılan: 20)"},
				},
				"required": []string{"tip"},
			},
		},
		{
			"name":        "parametre_setleri",
			"description": "Sistemdeki parametre seti tanımlarını listeler. Her modülün hangi alanları (parametreleri) olduğunu gösterir.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"set_id": fiber.Map{"type": "string", "description": "Belirli bir set ID (ör: personel.kayit, firma.kayit). Boş bırakılırsa tüm setler listelenir."},
				},
			},
		},
		{
			"name":        "paylasim_ara",
			"description": "Paylaşım kartlarını arar. Sahip, gizlilik, etiket, tarih, VT, yol ile filtreleme. Veri, içerikler ve dosyalarda arama yapar.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"arama":    fiber.Map{"type": "string", "description": "Aranacak metin (veri, içerikler, dosya isimlerinde arar)"},
					"sahip":    fiber.Map{"type": "string", "description": "Sahip kullanıcı ID (ObjectId hex)"},
					"gizlilik": fiber.Map{"type": "string", "description": "Gizlilik seviyesi filtresi"},
					"etiketler": fiber.Map{"type": "array", "description": "Etiket filtresi (dizide herhangi biri eşleşir)", "items": fiber.Map{"type": "string"}},
					"vt":       fiber.Map{"type": "string", "description": "VT filtresi (ör: FikoYT.sistem.paylasim)"},
					"yol":      fiber.Map{"type": "string", "description": "Yol filtresi (regex)"},
					"tarih_baslangic": fiber.Map{"type": "string", "description": "Başlangıç tarihi (ISO 8601, ör: 2026-01-01)"},
					"tarih_bitis":     fiber.Map{"type": "string", "description": "Bitiş tarihi (ISO 8601)"},
					"limit":    fiber.Map{"type": "number", "description": "Maksimum sonuç (varsayılan: 20)"},
				},
			},
		},
		{
			"name":        "dinamik_bilesen_listele",
			"description": "Sistemde kayıtlı tüm dinamik bileşenleri (cam bileşenleri) listeler. Her bileşenin ID, kategori ve açıklaması döner.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"kategori": fiber.Map{"type": "string", "description": "Kategori filtresi (ör: cam-isleme, satis, uretim, yonetim, uyar, genel). Boş bırakılırsa tümü listelenir."},
				},
			},
		},
		{
			"name":        "cihaz_canli_durum",
			"description": "Cihazların anlık bağlantı durumunu gösterir. goSoketler (çevrimiçi) ve goCihazlar (kayıtlı) koleksiyonlarından karşılaştırmalı durum.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"sadece_cevrimici": fiber.Map{"type": "boolean", "description": "true ise sadece çevrimiçi cihazları döner (varsayılan: false)"},
				},
			},
		},
		{
			"name":        "aktif_kullanicilar",
			"description": "Şu an çevrimiçi olan kullanıcıları getirir. Cihaz bilgisi, bağlantı zamanı ve konum dahil.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"detayli": fiber.Map{"type": "boolean", "description": "true ise kullanıcı profil bilgilerini de ekler (varsayılan: false)"},
				},
			},
		},
		{
			"name":        "sistem_saglik",
			"description": "Sistem sağlık kontrolü: MongoDB durumu, Ollama durumu, embedding pipeline durumu, cache istatistikleri, toplam kayıt sayıları, çevrimiçi cihaz/kullanıcı sayısı.",
			"inputSchema": fiber.Map{
				"type":       "object",
				"properties": fiber.Map{},
			},
		},
		{
			"name":        "filitre_olustur",
			"description": "Doğal dil filtre açıklamasından MongoDB $match filtresi üretir. Alan adları ve koşulları alıp uygun pipeline döner.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"vt":        fiber.Map{"type": "string", "description": "VT filtresi (ör: FikoYT.sistem.firmalar)"},
					"kosullar":  fiber.Map{"type": "array", "description": "Filtre koşulları dizisi", "items": fiber.Map{
						"type": "object",
						"properties": fiber.Map{
							"alan":     fiber.Map{"type": "string", "description": "Alan adı (ör: veri.isim, veri.durum, olusturma)"},
							"operator": fiber.Map{"type": "string", "description": "Operatör: esit, esit_degil, icerir, baslar, biter, buyuk, kucuk, arasinda, var, yok, bos, dolu", "enum": []string{"esit", "esit_degil", "icerir", "baslar", "biter", "buyuk", "kucuk", "arasinda", "var", "yok", "bos", "dolu"}},
							"deger":    fiber.Map{"description": "Karşılaştırma değeri (arasinda için [min, max] dizisi)"},
						},
					}},
					"siralama": fiber.Map{"type": "object", "description": "Sıralama: {alan: 'olusturma', yon: -1}"},
					"limit":    fiber.Map{"type": "number", "description": "Sonuç limiti (varsayılan: 20)"},
				},
				"required": []string{"kosullar"},
			},
		},
		{
			"name":        "uye_bul",
			"description": "Platform kullanıcısını isim, soyisim veya e-posta ile arar. Tüm bilgileri döner (parola hariç).",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"arama": fiber.Map{"type": "string", "description": "İsim, soyisim veya e-posta"},
				},
				"required": []string{"arama"},
			},
		},
		{
			"name":        "kisi_detay",
			"description": "Soyağacı kişisinin TÜM bilgilerini getirir: kişi verileri, akrabalık bağları (isimlerle birlikte), yaşam olayları, adresler, fotoğraflar.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"kisi_id": fiber.Map{"type": "string", "description": "Kişi ID (ObjectId hex)"},
					"isim":    fiber.Map{"type": "string", "description": "İsim ile arama (kisi_id yoksa)"},
				},
			},
		},
		{
			"name":        "hareket_toplu_islem",
			"description": "Toplu istatistik işlemleri: VT bazında sayım, alan bazında gruplama, tarih aralığı istatistikleri, bir alana göre en çok N kayıt.",
			"inputSchema": fiber.Map{
				"type": "object",
				"properties": fiber.Map{
					"islem": fiber.Map{"type": "string", "description": "İşlem tipi", "enum": []string{"vt_sayim", "gruplama", "tarih_istatistik", "top_n"}},
					"vt":    fiber.Map{"type": "string", "description": "VT filtresi (opsiyonel)"},
					"alan":  fiber.Map{"type": "string", "description": "Gruplama/sıralama alanı (ör: veri.durum, veri.firmaAdi)"},
					"tarih_baslangic": fiber.Map{"type": "string", "description": "Başlangıç tarihi (ISO 8601)"},
					"tarih_bitis":     fiber.Map{"type": "string", "description": "Bitiş tarihi (ISO 8601)"},
					"limit": fiber.Map{"type": "number", "description": "Top N için limit (varsayılan: 10)"},
				},
				"required": []string{"islem"},
			},
		},
	}
}

// --- Tool Çağırma ---

func mcpToolCagir(istek jsonRpcIstek) jsonRpcCevap {
	var params struct {
		Name      string          `json:"name"`
		Arguments json.RawMessage `json:"arguments"`
	}
	json.Unmarshal(istek.Params, &params)

	var args map[string]interface{}
	json.Unmarshal(params.Arguments, &args)

	baslangic := time.Now()
	defer func() {
		go toolKullanimLogla(params.Name, "", time.Since(baslangic).Milliseconds(), true, "")
	}()

	switch params.Name {
	case "hareketler_ara":
		return mcpHareketlerAra(istek.ID, args)
	case "hareket_getir":
		return mcpHareketGetir(istek.ID, args)
	case "soru_sor":
		return mcpSoruSor(istek.ID, args)
	case "vt_listele":
		return mcpVTListele(istek.ID)
	case "istatistik":
		return mcpIstatistik(istek.ID)
	case "hareket_ekle":
		return mcpHareketEkle(istek.ID, args)
	case "hareket_guncelle":
		return mcpHareketGuncelle(istek.ID, args)
	case "soyagaci_akrabalar":
		return mcpSoyagaciAkrabalar(istek.ID, args)
	case "akrabalik_bul":
		return mcpAkrabalikBul(istek.ID, args)
	case "soyagaci_kisi_bul":
		return mcpSoyagaciKisiBul(istek.ID, args)
	case "firma_sorgula":
		return mcpFirmaSorgula(istek.ID, args)
	case "cihaz_sorgula":
		return mcpCihazSorgula(istek.ID, args)
	case "kullanici_sorgula":
		return mcpKullaniciSorgula(istek.ID, args)
	case "aggregate_sorgula":
		return mcpAggregateSorgula(istek.ID, args)
	case "kayit_say":
		return mcpKayitSay(istek.ID, args)
	case "hareket_sil":
		return mcpHareketSil(istek.ID, args)
	case "mail_sorgula":
		return mcpMailSorgula(istek.ID, args)
	case "parametre_setleri":
		return mcpParametreSetleri(istek.ID, args)
	case "paylasim_ara":
		return mcpPaylasimAra(istek.ID, args)
	case "dinamik_bilesen_listele":
		return mcpDinamikBilesenListele(istek.ID, args)
	case "cihaz_canli_durum":
		return mcpCihazCanliDurum(istek.ID, args)
	case "aktif_kullanicilar":
		return mcpAktifKullanicilar(istek.ID, args)
	case "sistem_saglik":
		return mcpSistemSaglik(istek.ID)
	case "filitre_olustur":
		return mcpFilitreOlustur(istek.ID, args)
	case "hareket_toplu_islem":
		return mcpHareketTopluIslem(istek.ID, args)
	case "uye_bul":
		return mcpUyeBul(istek.ID, args)
	case "kisi_detay":
		return mcpKisiDetay(istek.ID, args)
	default:
		if customToolVarMi(params.Name) {
			return customToolCagirMCP(istek.ID, params.Name, args)
		}
		return jsonRpcCevap{
			Jsonrpc: "2.0",
			ID:      istek.ID,
			Error:   &jsonRpcHata{Code: -32602, Message: "Bilinmeyen tool: " + params.Name},
		}
	}
}

func mcpSonuc(id interface{}, metin string) jsonRpcCevap {
	return jsonRpcCevap{
		Jsonrpc: "2.0",
		ID:      id,
		Result: fiber.Map{
			"content": []fiber.Map{{"type": "text", "text": metin}},
		},
	}
}

func mcpSonucJSON(id interface{}, baslik string, sonuclar []bson.M) jsonRpcCevap {
	zengin := sonuclarZenginlestir(sonuclar)
	data, _ := json.MarshalIndent(zengin, "", "  ")
	return mcpSonuc(id, fmt.Sprintf("%d %s:\n%s", len(zengin), baslik, string(data)))
}

func mcpSonucTekJSON(id interface{}, doc bson.M) jsonRpcCevap {
	zengin := sonucZenginlestir(doc)
	data, _ := json.MarshalIndent(zengin, "", "  ")
	return mcpSonuc(id, string(data))
}

func mcpHata(id interface{}, mesaj string) jsonRpcCevap {
	return jsonRpcCevap{
		Jsonrpc: "2.0",
		ID:      id,
		Result: fiber.Map{
			"content": []fiber.Map{{"type": "text", "text": "Hata: " + mesaj}},
			"isError": true,
		},
	}
}

// --- Tool İşlemleri ---

func mcpHareketlerAra(id interface{}, args map[string]interface{}) jsonRpcCevap {
	sorgu, _ := args["sorgu"].(string)
	if sorgu == "" {
		return mcpHata(id, "sorgu parametresi gerekli")
	}

	limit := 10
	if l, ok := args["limit"].(float64); ok && l > 0 {
		limit = int(l)
	}
	vtFiltre, _ := args["vt"].(string)

	sonuclar, err := AraMetin(sorgu, limit, vtFiltre)
	if err != nil {
		return mcpHata(id, err.Error())
	}

	return mcpSonucJSON(id, "sonuç", sonuclar)
}

func mcpHareketGetir(id interface{}, args map[string]interface{}) jsonRpcCevap {
	idStr, _ := args["id"].(string)
	if idStr == "" {
		return mcpHata(id, "id parametresi gerekli")
	}

	oid, err := primitive.ObjectIDFromHex(idStr)
	if err != nil {
		return mcpHata(id, "Geçersiz ObjectId")
	}

	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")
	var hareket bson.M
	err = kol.FindOne(context.TODO(), bson.M{"_id": oid}).Decode(&hareket)
	if err != nil {
		return mcpHata(id, "Kayıt bulunamadı")
	}

	return mcpSonucTekJSON(id, hareket)
}

func mcpSoruSor(id interface{}, args map[string]interface{}) jsonRpcCevap {
	soru, _ := args["soru"].(string)
	if soru == "" {
		return mcpHata(id, "soru parametresi gerekli")
	}
	vtFiltre, _ := args["vt"].(string)

	cevap, kaynaklar, err := SoruSor(soru, vtFiltre)
	if err != nil {
		return mcpHata(id, err.Error())
	}

	sonuc := fmt.Sprintf("%s\n\n---\nKaynaklar: %d kayıt kullanıldı", cevap, len(kaynaklar))
	return mcpSonuc(id, sonuc)
}

func mcpVTListele(id interface{}) jsonRpcCevap {
	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")

	pipeline := mongo.Pipeline{
		{{Key: "$group", Value: bson.M{"_id": "$vt", "sayi": bson.M{"$sum": 1}}}},
		{{Key: "$sort", Value: bson.M{"sayi": -1}}},
	}

	cursor, err := kol.Aggregate(context.TODO(), pipeline)
	if err != nil {
		return mcpHata(id, err.Error())
	}

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

	data, _ := json.MarshalIndent(sonuclar, "", "  ")
	return mcpSonuc(id, string(data))
}

func mcpIstatistik(id interface{}) jsonRpcCevap {
	ctx := context.TODO()
	db := fiko_mongo.GetMongoDBClient().Database("fikoyt")

	hareketSayi, _ := db.Collection("hareketler").CountDocuments(ctx, bson.M{})
	gommeSayi, _ := db.Collection(GommeKoleksiyon).CountDocuments(ctx, bson.M{})

	oran := float64(0)
	if hareketSayi > 0 {
		oran = float64(gommeSayi) / float64(hareketSayi) * 100
	}

	istatistik := fiber.Map{
		"toplam_hareket": hareketSayi,
		"toplam_gomme":   gommeSayi,
		"gomme_orani":    fmt.Sprintf("%.1f%%", oran),
		"gomme_durum":    gommeDurum,
	}

	data, _ := json.MarshalIndent(istatistik, "", "  ")
	return mcpSonuc(id, string(data))
}

func mcpHareketEkle(id interface{}, args map[string]interface{}) jsonRpcCevap {
	vt, _ := args["vt"].(string)
	veri, _ := args["veri"].(map[string]interface{})
	if vt == "" || veri == nil {
		return mcpHata(id, "vt ve veri parametreleri gerekli")
	}

	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")
	doc := bson.M{
		"vt":        vt,
		"veri":      veri,
		"olusturma": time.Now(),
	}

	result, err := kol.InsertOne(context.TODO(), doc)
	if err != nil {
		return mcpHata(id, err.Error())
	}

	return mcpSonuc(id, fmt.Sprintf("Kayıt eklendi. ID: %v", result.InsertedID))
}

func mcpHareketGuncelle(id interface{}, args map[string]interface{}) jsonRpcCevap {
	idStr, _ := args["id"].(string)
	veri, _ := args["veri"].(map[string]interface{})
	if idStr == "" || veri == nil {
		return mcpHata(id, "id ve veri parametreleri gerekli")
	}

	oid, err := primitive.ObjectIDFromHex(idStr)
	if err != nil {
		return mcpHata(id, "Geçersiz ObjectId")
	}

	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")
	update := bson.M{"$set": bson.M{"veri": veri, "guncelleme": time.Now()}}

	result, err := kol.UpdateOne(context.TODO(), bson.M{"_id": oid}, update)
	if err != nil {
		return mcpHata(id, err.Error())
	}

	return mcpSonuc(id, fmt.Sprintf("Güncellendi. Eşleşen: %d, Değiştirilen: %d", result.MatchedCount, result.ModifiedCount))
}

// --- Soyağacı Tool'ları ---

func mcpSoyagaciAkrabalar(id interface{}, args map[string]interface{}) jsonRpcCevap {
	ctx := context.TODO()
	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")

	kisiId, _ := args["kisi_id"].(string)
	isim, _ := args["isim"].(string)
	turFiltre, _ := args["tur"].(string)

	if kisiId == "" && isim != "" {
		var kisi bson.M
		kol.FindOne(ctx, bson.M{
			"vt": "FikoYT.sistem.soyAgaciKisiler",
			"$or": bson.A{
				bson.M{"veri.isim": bson.M{"$regex": isim, "$options": "i"}},
				bson.M{"veri.soyIsim": bson.M{"$regex": isim, "$options": "i"}},
			},
		}).Decode(&kisi)
		if kisi != nil {
			if oid, ok := kisi["_id"].(primitive.ObjectID); ok {
				kisiId = oid.Hex()
			}
		}
	}

	if kisiId == "" {
		return mcpHata(id, "Kişi bulunamadı. kisi_id veya isim gerekli.")
	}

	cursor, err := kol.Find(ctx, bson.M{
		"vt": "FikoYT.sistem.aileBaglari",
		"$or": bson.A{
			bson.M{"veri.kisi1": kisiId},
			bson.M{"veri.kisi2": kisiId},
		},
	})
	if err != nil {
		return mcpHata(id, err.Error())
	}
	defer cursor.Close(ctx)

	type akraba struct {
		Tur    string      `json:"tur"`
		Isim   string      `json:"isim"`
		ID     string      `json:"id"`
		Detay  interface{} `json:"detay,omitempty"`
	}
	var sonuclar []akraba

	for cursor.Next(ctx) {
		var bag bson.M
		cursor.Decode(&bag)
		veri, _ := bag["veri"].(bson.M)
		if veri == nil {
			continue
		}

		kisi1, _ := veri["kisi1"].(string)
		kisi2, _ := veri["kisi2"].(string)
		tur, _ := veri["akrabalikTuru"].(string)
		tersTur, _ := veri["tersAkrabalikTuru"].(string)

		var akrabaId, akrabaTur string
		if kisi1 == kisiId {
			akrabaId = kisi2
			akrabaTur = tur
		} else {
			akrabaId = kisi1
			if tersTur != "" {
				akrabaTur = tersTur
			} else {
				akrabaTur = tur
			}
		}

		if turFiltre != "" && akrabaTur != turFiltre {
			continue
		}

		oid, _ := primitive.ObjectIDFromHex(akrabaId)
		var akrabaKisi bson.M
		kol.FindOne(ctx, bson.M{"_id": oid}).Decode(&akrabaKisi)

		isimStr := akrabaId
		var detay interface{}
		if akrabaKisi != nil {
			if v, ok := akrabaKisi["veri"].(bson.M); ok {
				i, _ := v["isim"].(string)
				s, _ := v["soyIsim"].(string)
				isimStr = i + " " + s
				detay = v
			}
		}

		sonuclar = append(sonuclar, akraba{Tur: akrabaTur, Isim: isimStr, ID: akrabaId, Detay: detay})
	}

	sonucBson := make([]bson.M, 0, len(sonuclar))
	for _, a := range sonuclar {
		sonucBson = append(sonucBson, bson.M{"tur": a.Tur, "isim": a.Isim, "id": a.ID, "detay": a.Detay})
	}
	return mcpSonucJSON(id, "akraba", sonucBson)
}

func mcpSoyagaciKisiBul(id interface{}, args map[string]interface{}) jsonRpcCevap {
	arama, _ := args["arama"].(string)
	if arama == "" {
		return mcpHata(id, "arama parametresi gerekli")
	}
	limit := 10
	if l, ok := args["limit"].(float64); ok && l > 0 {
		limit = int(l)
	}

	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")
	opts := options.Find().SetLimit(int64(limit))

	cursor, err := kol.Find(context.TODO(), bson.M{
		"vt": "FikoYT.sistem.soyAgaciKisiler",
		"$or": bson.A{
			bson.M{"veri.isim": bson.M{"$regex": arama, "$options": "i"}},
			bson.M{"veri.soyIsim": bson.M{"$regex": arama, "$options": "i"}},
			bson.M{"veri.meslek": bson.M{"$regex": arama, "$options": "i"}},
		},
	}, opts)
	if err != nil {
		return mcpHata(id, err.Error())
	}

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

	return mcpSonucJSON(id, "kişi", sonuclar)
}

// --- Firma Tool'ları ---

func mcpFirmaSorgula(id interface{}, args map[string]interface{}) jsonRpcCevap {
	tip, _ := args["tip"].(string)
	arama, _ := args["arama"].(string)
	limit := 20
	if l, ok := args["limit"].(float64); ok && l > 0 {
		limit = int(l)
	}

	vtMap := map[string]string{
		"firma":     "FikoYT.sistem.firmalar",
		"personel":  "FikoYT.sistem.firma.personeller",
		"departman": "FikoYT.sistem.firma.departmanlar",
	}

	vt, ok := vtMap[tip]
	if !ok {
		return mcpHata(id, "Geçersiz tip. firma, personel veya departman olmalı.")
	}

	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")
	filtre := bson.M{"vt": vt}

	if arama != "" {
		filtre["$or"] = bson.A{
			bson.M{"veri.isim": bson.M{"$regex": arama, "$options": "i"}},
			bson.M{"veri.soyIsim": bson.M{"$regex": arama, "$options": "i"}},
			bson.M{"veri.firmaAdi": bson.M{"$regex": arama, "$options": "i"}},
			bson.M{"veri.ad": bson.M{"$regex": arama, "$options": "i"}},
		}
	}

	opts := options.Find().SetLimit(int64(limit)).SetSort(bson.M{"guncelleme": -1})
	cursor, err := kol.Find(context.TODO(), filtre, opts)
	if err != nil {
		return mcpHata(id, err.Error())
	}

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

	return mcpSonucJSON(id, tip, sonuclar)
}

// --- Cihaz Tool'ları ---

func mcpCihazSorgula(id interface{}, args map[string]interface{}) jsonRpcCevap {
	tip, _ := args["tip"].(string)
	cihazId, _ := args["cihaz_id"].(string)
	limit := 20
	if l, ok := args["limit"].(float64); ok && l > 0 {
		limit = int(l)
	}

	ctx := context.TODO()
	db := fiko_mongo.GetMongoDBClient().Database("fikoyt")

	switch tip {
	case "liste":
		kol := db.Collection("hareketler")
		opts := options.Find().SetLimit(int64(limit)).SetSort(bson.M{"guncelleme": -1})
		cursor, err := kol.Find(ctx, bson.M{"vt": "FikoYT.sistem.cihazlar"}, opts)
		if err != nil {
			return mcpHata(id, err.Error())
		}
		var sonuclar []bson.M
		cursor.All(ctx, &sonuclar)
		return mcpSonucJSON(id, "cihaz", sonuclar)

	case "durum":
		if cihazId == "" {
			return mcpHata(id, "cihaz_id gerekli")
		}
		kol := db.Collection("goCihazlar")
		var cihaz bson.M
		kol.FindOne(ctx, bson.M{"$or": bson.A{
			bson.M{"kimlik": cihazId},
			bson.M{"_id": func() interface{} { oid, err := primitive.ObjectIDFromHex(cihazId); if err == nil { return oid }; return nil }()},
		}}).Decode(&cihaz)
		if cihaz == nil {
			return mcpHata(id, "Cihaz bulunamadı")
		}
		return mcpSonucTekJSON(id, cihaz)

	case "olaylar":
		kol := db.Collection("hareketler")
		filtre := bson.M{"vt": "FikoYT.sistem.cihaz.olaylar"}
		if cihazId != "" {
			filtre["veri.cihaz_kimlik"] = cihazId
		}
		opts := options.Find().SetLimit(int64(limit)).SetSort(bson.M{"olusturma": -1})
		cursor, err := kol.Find(ctx, filtre, opts)
		if err != nil {
			return mcpHata(id, err.Error())
		}
		var sonuclar []bson.M
		cursor.All(ctx, &sonuclar)
		return mcpSonucJSON(id, "olay", sonuclar)

	default:
		return mcpHata(id, "Geçersiz tip: liste, durum veya olaylar")
	}
}

// --- Kullanıcı Tool'ları ---

func mcpKullaniciSorgula(id interface{}, args map[string]interface{}) jsonRpcCevap {
	tip, _ := args["tip"].(string)
	arama, _ := args["arama"].(string)

	ctx := context.TODO()
	db := fiko_mongo.GetMongoDBClient().Database("fikoyt")

	switch tip {
	case "liste":
		kol := db.Collection("goUyeler")
		filtre := bson.M{}
		if arama != "" {
			filtre["$or"] = bson.A{
				bson.M{"isim": bson.M{"$regex": arama, "$options": "i"}},
				bson.M{"soyIsim": bson.M{"$regex": arama, "$options": "i"}},
				bson.M{"eposta": bson.M{"$regex": arama, "$options": "i"}},
			}
		}
		opts := options.Find().SetProjection(bson.M{"parola": 0, "epostaOnayKodu": 0}).SetLimit(50)
		cursor, err := kol.Find(ctx, filtre, opts)
		if err != nil {
			return mcpHata(id, err.Error())
		}
		var sonuclar []bson.M
		cursor.All(ctx, &sonuclar)
		return mcpSonucJSON(id, "kullanıcı", sonuclar)

	case "detay":
		if arama == "" {
			return mcpHata(id, "arama (kullanıcı ID veya isim) gerekli")
		}
		kol := db.Collection("goUyeler")
		var kullanici bson.M
		if oid, err := primitive.ObjectIDFromHex(arama); err == nil {
			kol.FindOne(ctx, bson.M{"_id": oid}, options.FindOne().SetProjection(bson.M{"parola": 0})).Decode(&kullanici)
		} else {
			kol.FindOne(ctx, bson.M{"$or": bson.A{
				bson.M{"isim": bson.M{"$regex": arama, "$options": "i"}},
				bson.M{"eposta": arama},
			}}, options.FindOne().SetProjection(bson.M{"parola": 0})).Decode(&kullanici)
		}
		if kullanici == nil {
			return mcpHata(id, "Kullanıcı bulunamadı")
		}
		return mcpSonucTekJSON(id, kullanici)

	case "aktif":
		kol := db.Collection("goSoketler")
		cursor, err := kol.Find(ctx, bson.M{})
		if err != nil {
			return mcpHata(id, err.Error())
		}
		var sonuclar []bson.M
		cursor.All(ctx, &sonuclar)
		return mcpSonucJSON(id, "aktif bağlantı", sonuclar)

	default:
		return mcpHata(id, "Geçersiz tip: liste, detay veya aktif")
	}
}

// --- Aggregate Tool ---

func mcpAggregateSorgula(id interface{}, args map[string]interface{}) jsonRpcCevap {
	pipelineRaw, _ := args["pipeline"].([]interface{})
	if len(pipelineRaw) == 0 {
		return mcpHata(id, "pipeline dizisi gerekli")
	}

	kolIsim := "hareketler"
	if k, ok := args["koleksiyon"].(string); ok && k != "" {
		izinliKoleksiyonlar := map[string]bool{
			"hareketler": true, "goUyeler": true, "goCihazlar": true, "goSoketler": true,
			"go_sessions": true, "rag_gomme": true, "yuz_kuyruk": true, "yuz_tespit": true,
		}
		if izinliKoleksiyonlar[k] {
			kolIsim = k
		} else {
			return mcpHata(id, "İzin verilmeyen koleksiyon: "+k)
		}
	}

	pipeline := mongo.Pipeline{}
	for _, stage := range pipelineRaw {
		if stageMap, ok := stage.(map[string]interface{}); ok {
			doc := bson.D{}
			for k, v := range stageMap {
				doc = append(doc, bson.E{Key: k, Value: v})
			}
			pipeline = append(pipeline, doc)
		}
	}

	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection(kolIsim)
	cursor, err := kol.Aggregate(context.TODO(), pipeline)
	if err != nil {
		return mcpHata(id, "Aggregate hatası: "+err.Error())
	}

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

	if len(sonuclar) > 100 {
		sonuclar = sonuclar[:100]
	}

	return mcpSonucJSON(id, "sonuç", sonuclar)
}

// --- Kayıt Sayma ---

func mcpKayitSay(id interface{}, args map[string]interface{}) jsonRpcCevap {
	vt, _ := args["vt"].(string)
	if vt == "" {
		return mcpHata(id, "vt parametresi gerekli")
	}

	filtre := bson.M{"vt": vt}
	if ekFiltre, ok := args["filtre"].(map[string]interface{}); ok {
		for k, v := range ekFiltre {
			filtre[k] = v
		}
	}

	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")
	sayi, err := kol.CountDocuments(context.TODO(), filtre)
	if err != nil {
		return mcpHata(id, err.Error())
	}

	return mcpSonuc(id, fmt.Sprintf("VT: %s → %d kayıt", vt, sayi))
}

// --- Kayıt Silme ---

func mcpHareketSil(id interface{}, args map[string]interface{}) jsonRpcCevap {
	idStr, _ := args["id"].(string)
	if idStr == "" {
		return mcpHata(id, "id parametresi gerekli")
	}

	oid, err := primitive.ObjectIDFromHex(idStr)
	if err != nil {
		return mcpHata(id, "Geçersiz ObjectId")
	}

	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")
	result, err := kol.DeleteOne(context.TODO(), bson.M{"_id": oid})
	if err != nil {
		return mcpHata(id, err.Error())
	}

	return mcpSonuc(id, fmt.Sprintf("Silindi: %d kayıt", result.DeletedCount))
}

// --- Mail Tool ---

func mcpMailSorgula(id interface{}, args map[string]interface{}) jsonRpcCevap {
	tip, _ := args["tip"].(string)
	arama, _ := args["arama"].(string)
	limit := 20
	if l, ok := args["limit"].(float64); ok && l > 0 {
		limit = int(l)
	}

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

	switch tip {
	case "mesajlar":
		filtre := bson.M{"vt": "FikoYT.sistem.mail.mesajlar"}
		if arama != "" {
			filtre["$or"] = bson.A{
				bson.M{"veri.konu": bson.M{"$regex": arama, "$options": "i"}},
				bson.M{"veri.kimden": bson.M{"$regex": arama, "$options": "i"}},
			}
		}
		opts := options.Find().SetLimit(int64(limit)).SetSort(bson.M{"olusturma": -1})
		cursor, err := kol.Find(ctx, filtre, opts)
		if err != nil {
			return mcpHata(id, err.Error())
		}
		var sonuclar []bson.M
		cursor.All(ctx, &sonuclar)
		return mcpSonucJSON(id, "mail", sonuclar)

	case "hesaplar":
		cursor, err := kol.Find(ctx, bson.M{"vt": "FikoYT.sistem.mail.hesaplar"})
		if err != nil {
			return mcpHata(id, err.Error())
		}
		var sonuclar []bson.M
		cursor.All(ctx, &sonuclar)
		return mcpSonucJSON(id, "hesap", sonuclar)

	default:
		return mcpHata(id, "Geçersiz tip: mesajlar veya hesaplar")
	}
}

// --- Parametre Setleri Tool ---

func mcpParametreSetleri(id interface{}, args map[string]interface{}) jsonRpcCevap {
	setId, _ := args["set_id"].(string)

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

	if setId != "" {
		var set bson.M
		kol.FindOne(ctx, bson.M{
			"vt":        "FikoYT.sistem.parametreSetleri",
			"veri.setId": setId,
		}).Decode(&set)
		if set == nil {
			return mcpHata(id, "Parametre seti bulunamadı: "+setId)
		}
		return mcpSonucTekJSON(id, set)
	}

	cursor, err := kol.Find(ctx, bson.M{"vt": "FikoYT.sistem.parametreSetleri"})
	if err != nil {
		return mcpHata(id, err.Error())
	}
	var sonuclar []bson.M
	cursor.All(ctx, &sonuclar)

	if len(sonuclar) == 0 {
		return mcpSonuc(id, "Henüz parametre seti tanımlı değil. Parametre setleri kod tarafında (sistem-parametre-setleri.ts) tanımlıdır: firma.kayit, personel.kayit, cihaz.kayit, ticaret.siparis, ticaret.teklif, denetim.kayit, sistem.ajan, sistem.gorev, iletisim.mesaj, mail.hesap, mail.mesaj vb.")
	}

	return mcpSonucJSON(id, "parametre seti", sonuclar)
}

// --- Paylaşım Arama Tool ---

func mcpPaylasimAra(id interface{}, args map[string]interface{}) jsonRpcCevap {
	arama, _ := args["arama"].(string)
	sahip, _ := args["sahip"].(string)
	gizlilik, _ := args["gizlilik"].(string)
	vt, _ := args["vt"].(string)
	yol, _ := args["yol"].(string)
	tarihBaslangic, _ := args["tarih_baslangic"].(string)
	tarihBitis, _ := args["tarih_bitis"].(string)
	limit := 20
	if l, ok := args["limit"].(float64); ok && l > 0 {
		limit = int(l)
	}

	filtre := bson.M{}

	if vt != "" {
		filtre["vt"] = vt
	}

	if sahip != "" {
		if oid, err := primitive.ObjectIDFromHex(sahip); err == nil {
			filtre["sahip"] = oid
		} else {
			filtre["sahip"] = sahip
		}
	}

	if gizlilik != "" {
		filtre["veri.gizlilik"] = gizlilik
	}

	if etiketlerRaw, ok := args["etiketler"].([]interface{}); ok && len(etiketlerRaw) > 0 {
		etiketler := make([]string, 0, len(etiketlerRaw))
		for _, e := range etiketlerRaw {
			if s, ok := e.(string); ok {
				etiketler = append(etiketler, s)
			}
		}
		filtre["veri.etiketler"] = bson.M{"$in": etiketler}
	}

	if yol != "" {
		filtre["yol"] = bson.M{"$regex": yol, "$options": "i"}
	}

	if tarihBaslangic != "" || tarihBitis != "" {
		tarihFiltre := bson.M{}
		if tarihBaslangic != "" {
			if t, err := time.Parse("2006-01-02", tarihBaslangic); err == nil {
				tarihFiltre["$gte"] = t
			}
		}
		if tarihBitis != "" {
			if t, err := time.Parse("2006-01-02", tarihBitis); err == nil {
				tarihFiltre["$lte"] = t.Add(24*time.Hour - time.Millisecond)
			}
		}
		if len(tarihFiltre) > 0 {
			filtre["olusturma"] = tarihFiltre
		}
	}

	if arama != "" {
		filtre["$or"] = bson.A{
			bson.M{"veri.baslik": bson.M{"$regex": arama, "$options": "i"}},
			bson.M{"veri.aciklama": bson.M{"$regex": arama, "$options": "i"}},
			bson.M{"veri.metin": bson.M{"$regex": arama, "$options": "i"}},
			bson.M{"icerikler.metin": bson.M{"$regex": arama, "$options": "i"}},
			bson.M{"icerikler.html": bson.M{"$regex": arama, "$options": "i"}},
			bson.M{"dosyalar.ismi": bson.M{"$regex": arama, "$options": "i"}},
		}
	}

	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")
	opts := options.Find().SetLimit(int64(limit)).SetSort(bson.M{"olusturma": -1})
	cursor, err := kol.Find(context.TODO(), filtre, opts)
	if err != nil {
		return mcpHata(id, err.Error())
	}

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

	return mcpSonucJSON(id, "paylaşım kartı", sonuclar)
}

// --- Dinamik Bileşen Listele Tool ---

func mcpDinamikBilesenListele(id interface{}, args map[string]interface{}) jsonRpcCevap {
	kategoriFiltre, _ := args["kategori"].(string)

	type dinamikBilesen struct {
		ID       string `json:"id"`
		Kategori string `json:"kategori"`
		Aciklama string `json:"aciklama"`
	}

	tumu := []dinamikBilesen{
		{ID: "cam-andon", Kategori: "cam-isleme", Aciklama: "Andon sistemi - üretim hattı durum takibi ve uyarılar"},
		{ID: "cam-bakim", Kategori: "cam-isleme", Aciklama: "Bakım takip - ekipman bakım planlaması ve kayıtları"},
		{ID: "cam-cnc-islem", Kategori: "cam-isleme", Aciklama: "CNC işlem takibi - makine operasyonları ve iş emirleri"},
		{ID: "cam-enerji", Kategori: "cam-isleme", Aciklama: "Enerji tüketim izleme ve raporlama"},
		{ID: "cam-kalite", Kategori: "cam-isleme", Aciklama: "Kalite kontrol - ölçüm ve test sonuçları"},
		{ID: "cam-kutuk", Kategori: "cam-isleme", Aciklama: "Kütük takibi - hammadde girişi ve stok yönetimi"},
		{ID: "cam-malzeme-tanimi", Kategori: "cam-isleme", Aciklama: "Malzeme tanımlama - ürün ve hammadde kartları"},
		{ID: "cam-parca", Kategori: "cam-isleme", Aciklama: "Parça takibi - üretilen parçaların kayıt ve izlemesi"},
		{ID: "cam-vardiya", Kategori: "cam-isleme", Aciklama: "Vardiya yönetimi - çalışma planı ve devir teslim"},

		{ID: "musteri", Kategori: "satis", Aciklama: "Müşteri kartı - müşteri bilgileri ve iletişim"},
		{ID: "siparis", Kategori: "satis", Aciklama: "Sipariş yönetimi - sipariş oluşturma ve takibi"},
		{ID: "teklif", Kategori: "satis", Aciklama: "Teklif hazırlama ve yönetimi"},

		{ID: "makine-tanimi", Kategori: "uretim", Aciklama: "Makine tanımları - ekipman envanter kartları"},
		{ID: "uretim-sayac", Kategori: "uretim", Aciklama: "Üretim sayacı - üretim adetleri ve verimlilik"},
		{ID: "vardiya-devir", Kategori: "uretim", Aciklama: "Vardiya devir teslim kayıtları"},

		{ID: "bakim-talebi", Kategori: "yonetim", Aciklama: "Bakım talepleri - arıza/bakım iş emirleri"},
		{ID: "departman", Kategori: "yonetim", Aciklama: "Departman tanımları ve yapılandırması"},
		{ID: "personel", Kategori: "yonetim", Aciklama: "Personel kartı - çalışan bilgileri"},
		{ID: "tedarikci", Kategori: "yonetim", Aciklama: "Tedarikçi kartı - tedarikçi bilgileri"},
		{ID: "is-emri", Kategori: "yonetim", Aciklama: "İş emri oluşturma ve takibi"},
		{ID: "kalite", Kategori: "yonetim", Aciklama: "Kalite kayıtları ve denetim"},

		{ID: "projeler", Kategori: "uyar", Aciklama: "Proje kartları ve görev yönetimi"},

		{ID: "kart-okuyucu", Kategori: "genel", Aciklama: "RFID kart okuyucu bileşeni"},
		{ID: "basit-not", Kategori: "genel", Aciklama: "Basit not kartı - serbest metin girişi"},
	}

	var sonuc []dinamikBilesen
	if kategoriFiltre != "" {
		for _, b := range tumu {
			if b.Kategori == kategoriFiltre {
				sonuc = append(sonuc, b)
			}
		}
	} else {
		sonuc = tumu
	}

	data, _ := json.MarshalIndent(sonuc, "", "  ")
	return mcpSonuc(id, fmt.Sprintf("%d dinamik bileşen:\n%s", len(sonuc), string(data)))
}

// --- Cihaz Canlı Durum Tool ---

func mcpCihazCanliDurum(id interface{}, args map[string]interface{}) jsonRpcCevap {
	sadeceCevrimici, _ := args["sadece_cevrimici"].(bool)

	ctx := context.TODO()
	db := fiko_mongo.GetMongoDBClient().Database("fikoyt")

	soketKol := db.Collection("goSoketler")
	cursor, err := soketKol.Find(ctx, bson.M{"$or": bson.A{
		bson.M{"cihaz_kimlik": bson.M{"$exists": true, "$ne": ""}},
		bson.M{"tip": "cihaz"},
	}})
	if err != nil {
		return mcpHata(id, err.Error())
	}
	var cevrimiciSoketler []bson.M
	cursor.All(ctx, &cevrimiciSoketler)

	cevrimiciKimlikler := map[string]bson.M{}
	for _, s := range cevrimiciSoketler {
		if kimlik, ok := s["cihaz_kimlik"].(string); ok && kimlik != "" {
			cevrimiciKimlikler[kimlik] = s
		}
	}

	type cihazDurum struct {
		CihazKimlik string      `json:"cihaz_kimlik"`
		Isim        string      `json:"isim,omitempty"`
		Cevrimici   bool        `json:"cevrimici"`
		SoketBilgi  interface{} `json:"soket_bilgi,omitempty"`
		CihazBilgi  interface{} `json:"cihaz_bilgi,omitempty"`
	}

	var sonuclar []cihazDurum

	if sadeceCevrimici {
		for kimlik, soket := range cevrimiciKimlikler {
			sonuclar = append(sonuclar, cihazDurum{
				CihazKimlik: kimlik,
				Cevrimici:   true,
				SoketBilgi:  soket,
			})
		}
	} else {
		cihazKol := db.Collection("goCihazlar")
		cihazCursor, err := cihazKol.Find(ctx, bson.M{})
		if err != nil {
			return mcpHata(id, err.Error())
		}
		var cihazlar []bson.M
		cihazCursor.All(ctx, &cihazlar)

		for _, c := range cihazlar {
			kimlik, _ := c["kimlik"].(string)
			isim, _ := c["isim"].(string)
			durum := cihazDurum{
				CihazKimlik: kimlik,
				Isim:        isim,
				CihazBilgi:  c,
			}
			if soket, ok := cevrimiciKimlikler[kimlik]; ok {
				durum.Cevrimici = true
				durum.SoketBilgi = soket
			}
			sonuclar = append(sonuclar, durum)
		}
	}

	sonucBson := make([]bson.M, 0, len(sonuclar))
	for _, d := range sonuclar {
		sonucBson = append(sonucBson, bson.M{
			"cihaz_kimlik": d.CihazKimlik,
			"isim":         d.Isim,
			"cevrimici":    d.Cevrimici,
			"soket_bilgi":  d.SoketBilgi,
			"cihaz_bilgi":  d.CihazBilgi,
		})
	}
	return mcpSonucJSON(id, "cihaz durumu", sonucBson)
}

// --- Aktif Kullanıcılar Tool ---

func mcpAktifKullanicilar(id interface{}, args map[string]interface{}) jsonRpcCevap {
	detayli, _ := args["detayli"].(bool)

	ctx := context.TODO()
	db := fiko_mongo.GetMongoDBClient().Database("fikoyt")

	soketKol := db.Collection("goSoketler")
	cursor, err := soketKol.Find(ctx, bson.M{})
	if err != nil {
		return mcpHata(id, err.Error())
	}
	var soketler []bson.M
	cursor.All(ctx, &soketler)

	if !detayli {
		return mcpSonucJSON(id, "aktif bağlantı", soketler)
	}

	type aktifKullanici struct {
		Soket   bson.M `json:"soket"`
		Profil  bson.M `json:"profil,omitempty"`
	}

	uyeKol := db.Collection("goUyeler")
	var sonuclar []aktifKullanici

	for _, s := range soketler {
		ak := aktifKullanici{Soket: s}
		if uyeIdStr, ok := s["uyeId"].(string); ok && uyeIdStr != "" {
			if oid, err := primitive.ObjectIDFromHex(uyeIdStr); err == nil {
				var uye bson.M
				uyeKol.FindOne(ctx, bson.M{"_id": oid}, options.FindOne().SetProjection(bson.M{"parola": 0, "epostaOnayKodu": 0})).Decode(&uye)
				if uye != nil {
					ak.Profil = uye
				}
			}
		} else if uyeId, ok := s["uyeId"].(primitive.ObjectID); ok {
			var uye bson.M
			uyeKol.FindOne(ctx, bson.M{"_id": uyeId}, options.FindOne().SetProjection(bson.M{"parola": 0, "epostaOnayKodu": 0})).Decode(&uye)
			if uye != nil {
				ak.Profil = uye
			}
		}
		sonuclar = append(sonuclar, ak)
	}

	sonucBson := make([]bson.M, 0, len(sonuclar))
	for _, ak := range sonuclar {
		sonucBson = append(sonucBson, bson.M{"soket": ak.Soket, "profil": ak.Profil})
	}
	return mcpSonucJSON(id, "aktif kullanıcı", sonucBson)
}

// --- Sistem Sağlık Tool ---

func mcpSistemSaglik(id interface{}) jsonRpcCevap {
	ctx := context.TODO()
	db := fiko_mongo.GetMongoDBClient().Database("fikoyt")

	mongoDurum := "bağlı"
	if err := db.Client().Ping(ctx, nil); err != nil {
		mongoDurum = "bağlantı hatası: " + err.Error()
	}

	ollamaDurum := "erişilebilir"
	ollamaClient := &http.Client{Timeout: 5 * time.Second}
	resp, err := ollamaClient.Get(OllamaURL + "/api/tags")
	if err != nil {
		ollamaDurum = "erişilemiyor: " + err.Error()
	} else {
		resp.Body.Close()
		if resp.StatusCode != 200 {
			ollamaDurum = fmt.Sprintf("hata kodu: %d", resp.StatusCode)
		}
	}

	hareketSayi, _ := db.Collection("hareketler").CountDocuments(ctx, bson.M{})
	gommeSayi, _ := db.Collection(GommeKoleksiyon).CountDocuments(ctx, bson.M{})
	uyeSayi, _ := db.Collection("goUyeler").CountDocuments(ctx, bson.M{})
	soketSayi, _ := db.Collection("goSoketler").CountDocuments(ctx, bson.M{})
	cihazSayi, _ := db.Collection("goCihazlar").CountDocuments(ctx, bson.M{})

	gommeOran := float64(0)
	if hareketSayi > 0 {
		gommeOran = float64(gommeSayi) / float64(hareketSayi) * 100
	}

	saglik := bson.M{
		"mongodb":         mongoDurum,
		"ollama":          ollamaDurum,
		"ollama_url":      OllamaURL,
		"embed_model":     ragAyar().EmbedModel,
		"chat_model":      ragAyar().ChatModel,
		"embedding_pipeline": bson.M{
			"calisiyor":   gommeDurum.Calisiyor,
			"toplam":      gommeDurum.Toplam,
			"islenen":     gommeDurum.Islenen,
			"hata":        gommeDurum.Hata,
			"gomme_sayisi": gommeSayi,
			"gomme_orani":  fmt.Sprintf("%.1f%%", gommeOran),
		},
		"kayit_sayilari": bson.M{
			"hareketler": hareketSayi,
			"uyeler":     uyeSayi,
			"cihazlar":   cihazSayi,
		},
		"cevrimici": bson.M{
			"soketler": soketSayi,
		},
		"zaman": time.Now().Format(time.RFC3339),
	}

	return mcpSonucTekJSON(id, saglik)
}

// --- Filtre Oluştur Tool ---

func mcpFilitreOlustur(id interface{}, args map[string]interface{}) jsonRpcCevap {
	kosullarRaw, _ := args["kosullar"].([]interface{})
	if len(kosullarRaw) == 0 {
		return mcpHata(id, "kosullar dizisi gerekli")
	}

	vt, _ := args["vt"].(string)
	limit := 20
	if l, ok := args["limit"].(float64); ok && l > 0 {
		limit = int(l)
	}

	filtre := bson.M{}
	if vt != "" {
		filtre["vt"] = vt
	}

	for _, kosulRaw := range kosullarRaw {
		kosul, ok := kosulRaw.(map[string]interface{})
		if !ok {
			continue
		}
		alan, _ := kosul["alan"].(string)
		operator, _ := kosul["operator"].(string)
		deger := kosul["deger"]

		if alan == "" || operator == "" {
			continue
		}

		switch operator {
		case "esit":
			filtre[alan] = deger
		case "esit_degil":
			filtre[alan] = bson.M{"$ne": deger}
		case "icerir":
			if s, ok := deger.(string); ok {
				filtre[alan] = bson.M{"$regex": s, "$options": "i"}
			}
		case "baslar":
			if s, ok := deger.(string); ok {
				filtre[alan] = bson.M{"$regex": "^" + s, "$options": "i"}
			}
		case "biter":
			if s, ok := deger.(string); ok {
				filtre[alan] = bson.M{"$regex": s + "$", "$options": "i"}
			}
		case "buyuk":
			filtre[alan] = bson.M{"$gt": deger}
		case "kucuk":
			filtre[alan] = bson.M{"$lt": deger}
		case "arasinda":
			if arr, ok := deger.([]interface{}); ok && len(arr) == 2 {
				filtre[alan] = bson.M{"$gte": arr[0], "$lte": arr[1]}
			}
		case "var":
			filtre[alan] = bson.M{"$exists": true, "$ne": nil}
		case "yok":
			filtre[alan] = bson.M{"$exists": false}
		case "bos":
			filtre[alan] = bson.M{"$in": bson.A{"", nil}}
		case "dolu":
			filtre[alan] = bson.M{"$nin": bson.A{"", nil}, "$exists": true}
		}
	}

	pipeline := mongo.Pipeline{
		{{Key: "$match", Value: filtre}},
	}

	if siralamaRaw, ok := args["siralama"].(map[string]interface{}); ok {
		siraAlan, _ := siralamaRaw["alan"].(string)
		siraYon := -1
		if y, ok := siralamaRaw["yon"].(float64); ok {
			siraYon = int(y)
		}
		if siraAlan != "" {
			pipeline = append(pipeline, bson.D{{Key: "$sort", Value: bson.M{siraAlan: siraYon}}})
		}
	} else {
		pipeline = append(pipeline, bson.D{{Key: "$sort", Value: bson.M{"olusturma": -1}}})
	}

	pipeline = append(pipeline, bson.D{{Key: "$limit", Value: limit}})

	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")
	cursor, err := kol.Aggregate(context.TODO(), pipeline)
	if err != nil {
		return mcpHata(id, "Filtre hatası: "+err.Error())
	}

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

	return mcpSonucJSON(id, "sonuç", sonuclar)
}

// --- Hareket Toplu İşlem Tool ---

func mcpHareketTopluIslem(id interface{}, args map[string]interface{}) jsonRpcCevap {
	islem, _ := args["islem"].(string)
	vt, _ := args["vt"].(string)
	alan, _ := args["alan"].(string)
	tarihBaslangic, _ := args["tarih_baslangic"].(string)
	tarihBitis, _ := args["tarih_bitis"].(string)
	limit := 10
	if l, ok := args["limit"].(float64); ok && l > 0 {
		limit = int(l)
	}

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

	matchStage := bson.M{}
	if vt != "" {
		matchStage["vt"] = vt
	}
	if tarihBaslangic != "" || tarihBitis != "" {
		tarihFiltre := bson.M{}
		if tarihBaslangic != "" {
			if t, err := time.Parse("2006-01-02", tarihBaslangic); err == nil {
				tarihFiltre["$gte"] = t
			}
		}
		if tarihBitis != "" {
			if t, err := time.Parse("2006-01-02", tarihBitis); err == nil {
				tarihFiltre["$lte"] = t.Add(24*time.Hour - time.Millisecond)
			}
		}
		if len(tarihFiltre) > 0 {
			matchStage["olusturma"] = tarihFiltre
		}
	}

	switch islem {
	case "vt_sayim":
		pipeline := mongo.Pipeline{}
		if len(matchStage) > 0 {
			pipeline = append(pipeline, bson.D{{Key: "$match", Value: matchStage}})
		}
		pipeline = append(pipeline,
			bson.D{{Key: "$group", Value: bson.M{"_id": "$vt", "sayi": bson.M{"$sum": 1}}}},
			bson.D{{Key: "$sort", Value: bson.M{"sayi": -1}}},
		)
		cursor, err := kol.Aggregate(ctx, pipeline)
		if err != nil {
			return mcpHata(id, err.Error())
		}
		var sonuclar []bson.M
		cursor.All(ctx, &sonuclar)
		return mcpSonucJSON(id, "VT grubu", sonuclar)

	case "gruplama":
		if alan == "" {
			return mcpHata(id, "alan parametresi gerekli (ör: veri.durum, veri.firmaAdi)")
		}
		pipeline := mongo.Pipeline{}
		if len(matchStage) > 0 {
			pipeline = append(pipeline, bson.D{{Key: "$match", Value: matchStage}})
		}
		pipeline = append(pipeline,
			bson.D{{Key: "$group", Value: bson.M{"_id": "$" + alan, "sayi": bson.M{"$sum": 1}}}},
			bson.D{{Key: "$sort", Value: bson.M{"sayi": -1}}},
			bson.D{{Key: "$limit", Value: limit}},
		)
		cursor, err := kol.Aggregate(ctx, pipeline)
		if err != nil {
			return mcpHata(id, err.Error())
		}
		var sonuclar []bson.M
		cursor.All(ctx, &sonuclar)
		return mcpSonucJSON(id, "grup", sonuclar)

	case "tarih_istatistik":
		pipeline := mongo.Pipeline{}
		if len(matchStage) > 0 {
			pipeline = append(pipeline, bson.D{{Key: "$match", Value: matchStage}})
		}
		pipeline = append(pipeline,
			bson.D{{Key: "$group", Value: bson.M{
				"_id": bson.M{
					"yil": bson.M{"$year": "$olusturma"},
					"ay":  bson.M{"$month": "$olusturma"},
				},
				"sayi": bson.M{"$sum": 1},
				"ilk":  bson.M{"$min": "$olusturma"},
				"son":  bson.M{"$max": "$olusturma"},
			}}},
			bson.D{{Key: "$sort", Value: bson.M{"_id.yil": -1, "_id.ay": -1}}},
			bson.D{{Key: "$limit", Value: limit}},
		)
		cursor, err := kol.Aggregate(ctx, pipeline)
		if err != nil {
			return mcpHata(id, err.Error())
		}
		var sonuclar []bson.M
		cursor.All(ctx, &sonuclar)
		return mcpSonucJSON(id, "dönem", sonuclar)

	case "top_n":
		if alan == "" {
			return mcpHata(id, "alan parametresi gerekli (ör: veri.isim, veri.firmaAdi)")
		}
		pipeline := mongo.Pipeline{}
		if len(matchStage) > 0 {
			pipeline = append(pipeline, bson.D{{Key: "$match", Value: matchStage}})
		}
		pipeline = append(pipeline,
			bson.D{{Key: "$match", Value: bson.M{alan: bson.M{"$exists": true, "$ne": nil}}}},
			bson.D{{Key: "$group", Value: bson.M{
				"_id": "$" + alan,
				"sayi": bson.M{"$sum": 1},
			}}},
			bson.D{{Key: "$sort", Value: bson.M{"sayi": -1}}},
			bson.D{{Key: "$limit", Value: limit}},
		)
		cursor, err := kol.Aggregate(ctx, pipeline)
		if err != nil {
			return mcpHata(id, err.Error())
		}
		var sonuclar []bson.M
		cursor.All(ctx, &sonuclar)
		return mcpSonucJSON(id, "kayıt", sonuclar)

	default:
		return mcpHata(id, "Geçersiz işlem. vt_sayim, gruplama, tarih_istatistik veya top_n olmalı.")
	}
}

// --- Üye Bul Tool ---

func mcpUyeBul(id interface{}, args map[string]interface{}) jsonRpcCevap {
	arama, _ := args["arama"].(string)
	if arama == "" {
		return mcpHata(id, "arama parametresi gerekli")
	}

	kol := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("goUyeler")
	opts := options.Find().SetProjection(bson.M{"parola": 0, "epostaOnayKodu": 0}).SetLimit(20)

	cursor, err := kol.Find(context.TODO(), bson.M{
		"$or": bson.A{
			bson.M{"isim": bson.M{"$regex": arama, "$options": "i"}},
			bson.M{"soyIsim": bson.M{"$regex": arama, "$options": "i"}},
			bson.M{"eposta": bson.M{"$regex": arama, "$options": "i"}},
		},
	}, opts)
	if err != nil {
		return mcpHata(id, err.Error())
	}
	var sonuclar []bson.M
	cursor.All(context.TODO(), &sonuclar)
	return mcpSonucJSON(id, "kullanıcı", sonuclar)
}

// --- Kişi Detay Tool ---

func mcpKisiDetay(id interface{}, args map[string]interface{}) jsonRpcCevap {
	kisiId, _ := args["kisi_id"].(string)
	isim, _ := args["isim"].(string)

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

	var kisi bson.M
	if kisiId != "" {
		oid, err := primitive.ObjectIDFromHex(kisiId)
		if err != nil {
			return mcpHata(id, "Geçersiz ID")
		}
		kol.FindOne(ctx, bson.M{"_id": oid, "vt": "FikoYT.sistem.soyAgaciKisiler"}).Decode(&kisi)
	} else if isim != "" {
		kol.FindOne(ctx, bson.M{
			"vt": "FikoYT.sistem.soyAgaciKisiler",
			"$or": bson.A{
				bson.M{"veri.isim": bson.M{"$regex": isim, "$options": "i"}},
				bson.M{"veri.soyIsim": bson.M{"$regex": isim, "$options": "i"}},
			},
		}).Decode(&kisi)
	}

	if kisi == nil {
		return mcpHata(id, "Kişi bulunamadı")
	}

	kisiOid := kisi["_id"]
	kisiHex := ""
	if oid, ok := kisiOid.(primitive.ObjectID); ok {
		kisiHex = oid.Hex()
	}

	var baglar []bson.M
	aramaIdler := bson.A{
		bson.M{"veri.kisi1": kisiHex},
		bson.M{"veri.kisi2": kisiHex},
	}
	if oid, err := primitive.ObjectIDFromHex(kisiHex); err == nil {
		aramaIdler = append(aramaIdler,
			bson.M{"veri.kisi1": oid},
			bson.M{"veri.kisi2": oid},
		)
	}
	if veri, ok := kisi["veri"].(bson.M); ok {
		if puid, ok := veri["platformKullaniciId"].(string); ok && puid != "" {
			aramaIdler = append(aramaIdler,
				bson.M{"veri.kisi1": puid},
				bson.M{"veri.kisi2": puid},
			)
			if poid, err := primitive.ObjectIDFromHex(puid); err == nil {
				aramaIdler = append(aramaIdler,
					bson.M{"veri.kisi1": poid},
					bson.M{"veri.kisi2": poid},
				)
			}
		}
	}

	cursor, err := kol.Find(ctx, bson.M{"vt": "FikoYT.sistem.aileBaglari", "$or": aramaIdler})
	if err == nil {
		cursor.All(ctx, &baglar)
	}

	sonuc := sonucZenginlestir(kisi)
	sonuc["akrabaliklar"] = sonuclarZenginlestir(baglar)

	return mcpSonucTekJSON(id, sonuc)
}
