package rag

import (
	"context"
	"fmt"
	"strings"

	fiko_mongo "server/sistem/fikoyt_mongo"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
)

const (
	AkrANNE          = "ANNE"
	AkrBABA          = "BABA"
	AkrES            = "ES"
	AkrCOCUK         = "COCUK"
	AkrKARDES        = "KARDES"
	AkrAMCA          = "AMCA"
	AkrDAYI          = "DAYI"
	AkrHALA          = "HALA"
	AkrTEYZE         = "TEYZE"
	AkrKUZEN         = "KUZEN"
	AkrDEDE_BABA     = "DEDE_BABA"
	AkrDEDE_ANNE     = "DEDE_ANNE"
	AkrNINE_BABA     = "NINE_BABA"
	AkrNINE_ANNE     = "NINE_ANNE"
	AkrTORUN         = "TORUN"
	AkrGELIN         = "GELIN"
	AkrDAMAT         = "DAMAT"
	AkrKAYINVALIDE   = "KAYINVALIDE"
	AkrKAYINPEDER    = "KAYINPEDER"
	AkrYEGEN         = "YEGEN"
	AkrENISTE        = "ENISTE"
	AkrBALDIZ        = "BALDIZ"
	AkrKAYINBIRADER  = "KAYINBIRADER"
	AkrGORUMCE       = "GORUMCE"
	AkrBUYUK_BABA    = "BUYUK_BABA"
	AkrBUYUK_ANNE    = "BUYUK_ANNE"
	AkrYENGE         = "YENGE"
	AkrELTI          = "ELTI"
	AkrBACANAK       = "BACANAK"
	AkrKUZENISTE     = "KUZENISTE"
	AkrKUZENGE       = "KUZENGE"
	AkrKUZENCO       = "KUZENCO"
	AkrYEGENCO       = "YEGENCO"
	AkrTORUCO        = "TORUCO"
	AkrTORUGEL       = "TORUGEL"
	AkrTORUDAM       = "TORUDAM"
	AkrKAYINENISTE   = "KAYINENISTE"
	AkrDUNUR         = "DUNUR"
	AkrDIGER         = "DIGER"
)

type akrabalikBilgi struct {
	isim      string
	cinsiyet  string // "E", "K", ""
	tersi     string
	sahipSiz  string
	sahipO    string
	tamlayanO string
}

var akrabalikBilgiMap = map[string]akrabalikBilgi{
	AkrANNE:         {isim: "Anne", cinsiyet: "K", tersi: AkrCOCUK, sahipSiz: "Anneniz", sahipO: "Annesi", tamlayanO: "Annesinin"},
	AkrBABA:         {isim: "Baba", cinsiyet: "E", tersi: AkrCOCUK, sahipSiz: "Babanız", sahipO: "Babası", tamlayanO: "Babasının"},
	AkrES:           {isim: "Eş", cinsiyet: "", tersi: AkrES, sahipSiz: "Eşiniz", sahipO: "Eşi", tamlayanO: "Eşinin"},
	AkrCOCUK:        {isim: "Çocuk", cinsiyet: "", tersi: AkrBABA, sahipSiz: "Çocuğunuz", sahipO: "Çocuğu", tamlayanO: "Çocuğunun"},
	AkrKARDES:       {isim: "Kardeş", cinsiyet: "", tersi: AkrKARDES, sahipSiz: "Kardeşiniz", sahipO: "Kardeşi", tamlayanO: "Kardeşinin"},
	AkrAMCA:         {isim: "Amca", cinsiyet: "E", tersi: AkrYEGEN, sahipSiz: "Amcanız", sahipO: "Amcası", tamlayanO: "Amcasının"},
	AkrDAYI:         {isim: "Dayı", cinsiyet: "E", tersi: AkrYEGEN, sahipSiz: "Dayınız", sahipO: "Dayısı", tamlayanO: "Dayısının"},
	AkrHALA:         {isim: "Hala", cinsiyet: "K", tersi: AkrYEGEN, sahipSiz: "Halanız", sahipO: "Halası", tamlayanO: "Halasının"},
	AkrTEYZE:        {isim: "Teyze", cinsiyet: "K", tersi: AkrYEGEN, sahipSiz: "Teyzeniz", sahipO: "Teyzesi", tamlayanO: "Teyzesinin"},
	AkrKUZEN:        {isim: "Kuzen", cinsiyet: "", tersi: AkrKUZEN, sahipSiz: "Kuzeniniz", sahipO: "Kuzeni", tamlayanO: "Kuzeninin"},
	AkrDEDE_BABA:    {isim: "Dede", cinsiyet: "E", tersi: AkrTORUN, sahipSiz: "Dedeniz", sahipO: "Dedesi", tamlayanO: "Dedesinin"},
	AkrDEDE_ANNE:    {isim: "Dede", cinsiyet: "E", tersi: AkrTORUN, sahipSiz: "Dedeniz", sahipO: "Dedesi", tamlayanO: "Dedesinin"},
	AkrNINE_BABA:    {isim: "Babaanne", cinsiyet: "K", tersi: AkrTORUN, sahipSiz: "Babaanneniz", sahipO: "Babaannesi", tamlayanO: "Babaannesinin"},
	AkrNINE_ANNE:    {isim: "Anneanne", cinsiyet: "K", tersi: AkrTORUN, sahipSiz: "Anneanneniz", sahipO: "Anneannesi", tamlayanO: "Anneannesinin"},
	AkrTORUN:        {isim: "Torun", cinsiyet: "", tersi: AkrDEDE_BABA, sahipSiz: "Torununuz", sahipO: "Torunu", tamlayanO: "Torununun"},
	AkrGELIN:        {isim: "Gelin", cinsiyet: "K", tersi: AkrKAYINVALIDE, sahipSiz: "Gelininiz", sahipO: "Gelini", tamlayanO: "Gelininin"},
	AkrDAMAT:        {isim: "Damat", cinsiyet: "E", tersi: AkrKAYINPEDER, sahipSiz: "Damadınız", sahipO: "Damadı", tamlayanO: "Damadının"},
	AkrKAYINVALIDE:  {isim: "Kayınvalide", cinsiyet: "K", tersi: AkrGELIN, sahipSiz: "Kayınvalideniz", sahipO: "Kayınvalidesi", tamlayanO: "Kayınvalidesinin"},
	AkrKAYINPEDER:   {isim: "Kayınpeder", cinsiyet: "E", tersi: AkrDAMAT, sahipSiz: "Kayınpederiniz", sahipO: "Kayınpederi", tamlayanO: "Kayınpederinin"},
	AkrYEGEN:        {isim: "Yeğen", cinsiyet: "", tersi: AkrAMCA, sahipSiz: "Yeğeniniz", sahipO: "Yeğeni", tamlayanO: "Yeğeninin"},
	AkrENISTE:       {isim: "Enişte", cinsiyet: "E", tersi: AkrBALDIZ, sahipSiz: "Enişteniz", sahipO: "Eniştesi", tamlayanO: "Eniştesinin"},
	AkrBALDIZ:       {isim: "Baldız", cinsiyet: "K", tersi: AkrENISTE, sahipSiz: "Baldızınız", sahipO: "Baldızı", tamlayanO: "Baldızının"},
	AkrKAYINBIRADER: {isim: "Kayınbirader", cinsiyet: "E", tersi: AkrENISTE, sahipSiz: "Kayınbiraderiniz", sahipO: "Kayınbiraderi", tamlayanO: "Kayınbiraderinin"},
	AkrGORUMCE:      {isim: "Görümce", cinsiyet: "K", tersi: AkrYENGE, sahipSiz: "Görümceniz", sahipO: "Görümcesi", tamlayanO: "Görümcesinin"},
	AkrBUYUK_BABA:   {isim: "Büyük Dede", cinsiyet: "E", tersi: AkrTORUCO, sahipSiz: "Büyük Dedeniz", sahipO: "Büyük Dedesi", tamlayanO: "Büyük Dedesinin"},
	AkrBUYUK_ANNE:   {isim: "Büyük Nine", cinsiyet: "K", tersi: AkrTORUCO, sahipSiz: "Büyük Nineniz", sahipO: "Büyük Ninesi", tamlayanO: "Büyük Ninesinin"},
	AkrYENGE:        {isim: "Yenge", cinsiyet: "K", tersi: AkrGORUMCE, sahipSiz: "Yengeniz", sahipO: "Yengesi", tamlayanO: "Yengesinin"},
	AkrELTI:         {isim: "Elti", cinsiyet: "K", tersi: AkrELTI, sahipSiz: "Eltiniz", sahipO: "Eltisi", tamlayanO: "Eltisinin"},
	AkrBACANAK:      {isim: "Bacanak", cinsiyet: "E", tersi: AkrBACANAK, sahipSiz: "Bacanağınız", sahipO: "Bacanağı", tamlayanO: "Bacanağının"},
	AkrKUZENISTE:    {isim: "Kuzenişte", cinsiyet: "E", tersi: AkrKUZENISTE, sahipSiz: "Kuzenişteniz", sahipO: "Kuzeniştesi", tamlayanO: "Kuzeniştesinin"},
	AkrKUZENGE:      {isim: "Kuzenge", cinsiyet: "K", tersi: AkrKUZENGE, sahipSiz: "Kuzengeniz", sahipO: "Kuzengesi", tamlayanO: "Kuzengesinin"},
	AkrKUZENCO:      {isim: "Kuzenço", cinsiyet: "", tersi: AkrKUZEN, sahipSiz: "Kuzençonuz", sahipO: "Kuzençosu", tamlayanO: "Kuzençosunun"},
	AkrYEGENCO:      {isim: "Yeğenço", cinsiyet: "", tersi: AkrAMCA, sahipSiz: "Yeğençonuz", sahipO: "Yeğençosu", tamlayanO: "Yeğençosunun"},
	AkrTORUCO:       {isim: "Toruço", cinsiyet: "", tersi: AkrBUYUK_BABA, sahipSiz: "Toruçonuz", sahipO: "Toruçosu", tamlayanO: "Toruçosunun"},
	AkrTORUGEL:      {isim: "Torugel", cinsiyet: "K", tersi: AkrKAYINVALIDE, sahipSiz: "Torugeliniz", sahipO: "Torugeli", tamlayanO: "Torugelinin"},
	AkrTORUDAM:      {isim: "Torudam", cinsiyet: "E", tersi: AkrKAYINPEDER, sahipSiz: "Torudamınız", sahipO: "Torudamı", tamlayanO: "Torudamının"},
	AkrKAYINENISTE:  {isim: "Kayın Enişte", cinsiyet: "E", tersi: AkrKAYINBIRADER, sahipSiz: "Kayın Enişteniz", sahipO: "Kayın Eniştesi", tamlayanO: "Kayın Eniştesinin"},
	AkrDUNUR:        {isim: "Dünür", cinsiyet: "", tersi: AkrDUNUR, sahipSiz: "Dünürünüz", sahipO: "Dünürü", tamlayanO: "Dünürünün"},
	AkrDIGER:        {isim: "Diğer", cinsiyet: "", tersi: AkrDIGER, sahipSiz: "Akrabanız", sahipO: "Akrabası", tamlayanO: "Akrabasının"},
}

type AkrabalikAdim struct {
	KisiId        string
	AkrabalikTuru string
}

type AkrabalikYolu struct {
	Yol      []AkrabalikAdim
	Mesafe   int
	Aciklama string
}

type komsuEdge struct {
	komsu string
	tur   string
}

func cinsiyetleTersCevir(tur string, cinsiyet string) string {
	kadin := cinsiyet == "F" || cinsiyet == "K"
	switch tur {
	case AkrCOCUK:
		if kadin {
			return AkrANNE
		}
		return AkrBABA
	case AkrTORUN:
		if kadin {
			return AkrNINE_BABA
		}
		return AkrDEDE_BABA
	case AkrYEGEN:
		if kadin {
			return AkrTEYZE
		}
		return AkrAMCA
	case AkrGELIN:
		return AkrCOCUK
	case AkrDAMAT:
		return AkrCOCUK
	case AkrKUZENCO:
		return AkrKUZEN
	}
	return ""
}

func bagdanTurCozumleGo(kisiId string, bag bson.M, karsiCinsiyet string) string {
	v, _ := bag["veri"].(bson.M)
	if v == nil {
		v = bag
	}
	if v == nil {
		return AkrDIGER
	}

	k1 := toHex(v["kisi1"])
	k2 := toHex(v["kisi2"])

	if k1 == kisiId {
		tur, _ := v["akrabalikTuru"].(string)
		if tur == "" {
			return AkrDIGER
		}
		return tur
	}

	if k2 == kisiId {
		tur, _ := v["akrabalikTuru"].(string)
		if karsiCinsiyet != "" {
			ct := cinsiyetleTersCevir(tur, karsiCinsiyet)
			if ct != "" {
				return ct
			}
		}
		tersTur, _ := v["tersAkrabalikTuru"].(string)
		if tersTur != "" {
			return tersTur
		}
		if bilgi, ok := akrabalikBilgiMap[tur]; ok && bilgi.tersi != "" {
			return bilgi.tersi
		}
	}

	tur, _ := v["akrabalikTuru"].(string)
	if tur != "" {
		return tur
	}
	return AkrDIGER
}

func komsuListeOlustur(baglar []bson.M, cinsiyetMap map[string]string) map[string][]komsuEdge {
	komsuListe := map[string][]komsuEdge{}

	for _, bag := range baglar {
		v, _ := bag["veri"].(bson.M)
		if v == nil {
			continue
		}
		k1 := toHex(v["kisi1"])
		k2 := toHex(v["kisi2"])
		if k1 == "" || k2 == "" {
			continue
		}

		tur, _ := v["akrabalikTuru"].(string)
		if tur == "" {
			continue
		}

		komsuListe[k1] = append(komsuListe[k1], komsuEdge{komsu: k2, tur: tur})

		ct := cinsiyetleTersCevir(tur, cinsiyetMap[k1])
		tersTur, _ := v["tersAkrabalikTuru"].(string)

		var tercihTur string
		if ct != "" {
			tercihTur = ct
		} else if tersTur != "" {
			tercihTur = tersTur
		} else if bilgi, ok := akrabalikBilgiMap[tur]; ok && bilgi.tersi != "" {
			tercihTur = bilgi.tersi
		}

		if tercihTur != "" {
			komsuListe[k2] = append(komsuListe[k2], komsuEdge{komsu: k1, tur: tercihTur})
		}
	}

	return komsuListe
}

func bfsEnKisaYol(komsuListe map[string][]komsuEdge, kisi1Id, kisi2Id string) []AkrabalikAdim {
	type kuyrukOge struct {
		id  string
		yol []AkrabalikAdim
	}

	kuyruk := []kuyrukOge{{id: kisi1Id, yol: nil}}
	ziyaretEdilen := map[string]bool{kisi1Id: true}

	for len(kuyruk) > 0 {
		mevcut := kuyruk[0]
		kuyruk = kuyruk[1:]

		if mevcut.id == kisi2Id {
			return mevcut.yol
		}

		for _, komsuluk := range komsuListe[mevcut.id] {
			if !ziyaretEdilen[komsuluk.komsu] {
				ziyaretEdilen[komsuluk.komsu] = true
				yeniYol := make([]AkrabalikAdim, len(mevcut.yol)+1)
				copy(yeniYol, mevcut.yol)
				yeniYol[len(mevcut.yol)] = AkrabalikAdim{KisiId: komsuluk.komsu, AkrabalikTuru: komsuluk.tur}
				kuyruk = append(kuyruk, kuyrukOge{id: komsuluk.komsu, yol: yeniYol})
			}
		}
	}

	return nil
}

func tumAkrabalikYollariBul(baglar []bson.M, kisi1Id, kisi2Id string, cinsiyetMap map[string]string) []AkrabalikYolu {
	komsuListe := komsuListeOlustur(baglar, cinsiyetMap)

	enKisa := bfsEnKisaYol(komsuListe, kisi1Id, kisi2Id)
	if enKisa == nil {
		return nil
	}

	maxDerinlik := len(enKisa) + 2
	if maxDerinlik > 8 {
		maxDerinlik = 8
	}

	tumYollar := [][]AkrabalikAdim{}
	ziyaretEdilen := map[string]bool{kisi1Id: true}

	var dfs func(mevcutId string, yol []AkrabalikAdim)
	dfs = func(mevcutId string, yol []AkrabalikAdim) {
		if len(yol) > maxDerinlik {
			return
		}
		if len(tumYollar) >= 10 {
			return
		}
		if mevcutId == kisi2Id {
			kopya := make([]AkrabalikAdim, len(yol))
			copy(kopya, yol)
			tumYollar = append(tumYollar, kopya)
			return
		}
		for _, komsuluk := range komsuListe[mevcutId] {
			if !ziyaretEdilen[komsuluk.komsu] {
				ziyaretEdilen[komsuluk.komsu] = true
				yol = append(yol, AkrabalikAdim{KisiId: komsuluk.komsu, AkrabalikTuru: komsuluk.tur})
				dfs(komsuluk.komsu, yol)
				yol = yol[:len(yol)-1]
				delete(ziyaretEdilen, komsuluk.komsu)
			}
		}
	}

	dfs(kisi1Id, nil)

	gorulen := map[string]bool{}
	var sonuclar []AkrabalikYolu

	for i := range tumYollar {
		for j := i + 1; j < len(tumYollar); j++ {
			if len(tumYollar[i]) > len(tumYollar[j]) {
				tumYollar[i], tumYollar[j] = tumYollar[j], tumYollar[i]
			}
		}
	}

	for _, yol := range tumYollar {
		aciklama := yoluTurkceAcikla(yol, cinsiyetMap)
		if gorulen[aciklama] {
			continue
		}
		gorulen[aciklama] = true
		sonuclar = append(sonuclar, AkrabalikYolu{
			Yol:      yol,
			Mesafe:   len(yol),
			Aciklama: aciklama,
		})
		if len(sonuclar) >= 5 {
			break
		}
	}

	return sonuclar
}

func yoluTurkceAcikla(yol []AkrabalikAdim, cinsiyetMap map[string]string) string {
	if len(yol) == 0 {
		return ""
	}

	if len(yol) == 1 {
		ilkTur := yol[0].AkrabalikTuru
		ilkCinsiyet := cinsiyetMap[yol[0].KisiId]
		if ilkTur == AkrKARDES {
			if ilkCinsiyet == "F" || ilkCinsiyet == "K" {
				return "Kız Kardeşiniz"
			}
			return "Erkek Kardeşiniz"
		}
		if bilgi, ok := akrabalikBilgiMap[ilkTur]; ok {
			if bilgi.sahipSiz != "" {
				return bilgi.sahipSiz
			}
			return bilgi.isim
		}
		return ilkTur
	}

	signature := make([]string, len(yol))
	for i, a := range yol {
		signature[i] = a.AkrabalikTuru
	}
	sig := strings.Join(signature, "+")

	sonKisiCinsiyet := cinsiyetMap[yol[len(yol)-1].KisiId]

	kisaIsim := pathSignaturdenKisaIsim(sig, sonKisiCinsiyet)
	if kisaIsim != "" {
		return kisaIsim
	}

	parcalar := []string{}

	ilkBilgi := akrabalikBilgiMap[yol[0].AkrabalikTuru]
	ilkSahip := ilkBilgi.sahipSiz
	if ilkSahip == "" {
		ilkSahip = ilkBilgi.isim
	}
	parcalar = append(parcalar, sahipSizTamlayanEkle(ilkSahip))

	for i := 1; i < len(yol)-1; i++ {
		bilgi := akrabalikBilgiMap[yol[i].AkrabalikTuru]
		if bilgi.tamlayanO != "" {
			parcalar = append(parcalar, bilgi.tamlayanO)
		} else {
			parcalar = append(parcalar, bilgi.isim)
		}
	}

	sonBilgi := akrabalikBilgiMap[yol[len(yol)-1].AkrabalikTuru]
	if sonBilgi.sahipO != "" {
		parcalar = append(parcalar, sonBilgi.sahipO)
	} else {
		parcalar = append(parcalar, sonBilgi.isim)
	}

	return strings.Join(parcalar, " ")
}

func pathSignaturdenKisaIsim(signature string, sonKisiCinsiyet string) string {
	kadin := sonKisiCinsiyet == "F" || sonKisiCinsiyet == "K"

	switch signature {
	// 2-Adimli Yollar
	case AkrBABA + "+" + AkrANNE:
		return "Babaanneniz"
	case AkrANNE + "+" + AkrBABA:
		return "Dedeniz (anne tarafından)"
	case AkrANNE + "+" + AkrANNE:
		return "Anneanneniz"
	case AkrBABA + "+" + AkrBABA:
		return "Dedeniz (baba tarafından)"

	case AkrBABA + "+" + AkrKARDES:
		if kadin {
			return "Halanız"
		}
		return "Amcanız"
	case AkrANNE + "+" + AkrKARDES:
		if kadin {
			return "Teyzeniz"
		}
		return "Dayınız"

	case AkrES + "+" + AkrANNE:
		return "Kayınvalideniz"
	case AkrES + "+" + AkrBABA:
		return "Kayınpederiniz"
	case AkrES + "+" + AkrKARDES:
		if kadin {
			return "Baldızınız"
		}
		return "Kayınbiraderiniz"

	case AkrCOCUK + "+" + AkrCOCUK:
		return "Torununuz"
	case AkrCOCUK + "+" + AkrES:
		if kadin {
			return "Gelininiz"
		}
		return "Damadınız"

	case AkrKARDES + "+" + AkrCOCUK:
		return "Yeğeniniz"
	case AkrKARDES + "+" + AkrES:
		if kadin {
			return "Yengeniz"
		}
		return "Enişteniz"

	case AkrAMCA + "+" + AkrCOCUK:
		return "Kuzeniniz"
	case AkrDAYI + "+" + AkrCOCUK:
		return "Kuzeniniz"
	case AkrHALA + "+" + AkrCOCUK:
		return "Kuzeniniz"
	case AkrTEYZE + "+" + AkrCOCUK:
		return "Kuzeniniz"

	case AkrDEDE_BABA + "+" + AkrCOCUK:
		if kadin {
			return "Büyük Halanız"
		}
		return "Büyük Amcanız"
	case AkrNINE_BABA + "+" + AkrCOCUK:
		if kadin {
			return "Büyük Teyzeniz"
		}
		return "Büyük Dayınız"
	case AkrDEDE_ANNE + "+" + AkrCOCUK:
		if kadin {
			return "Büyük Halanız"
		}
		return "Büyük Amcanız"
	case AkrNINE_ANNE + "+" + AkrCOCUK:
		if kadin {
			return "Büyük Teyzeniz"
		}
		return "Büyük Dayınız"

	// 3-Adimli Yollar
	case AkrBABA + "+" + AkrKARDES + "+" + AkrCOCUK:
		return "Kuzeniniz"
	case AkrANNE + "+" + AkrKARDES + "+" + AkrCOCUK:
		return "Kuzeniniz"

	case AkrKUZEN + "+" + AkrCOCUK:
		return "Kuzenço"
	case AkrYEGEN + "+" + AkrCOCUK:
		return "Yeğenço"
	case AkrTORUN + "+" + AkrCOCUK:
		return "Torunço"

	case AkrCOCUK + "+" + AkrCOCUK + "+" + AkrCOCUK:
		return "Torunço"

	case AkrES + "+" + AkrKARDES + "+" + AkrCOCUK:
		if kadin {
			return "Eşinizin Yeğeni (Kadın)"
		}
		return "Eşinizin Yeğeni (Erkek)"

	case AkrBABA + "+" + AkrANNE + "+" + AkrKARDES:
		if kadin {
			return "Babaannenizin Kız Kardeşi"
		}
		return "Babaannenizin Erkek Kardeşi"
	case AkrANNE + "+" + AkrBABA + "+" + AkrKARDES:
		if kadin {
			return "Dedenizin Kız Kardeşi (anne tarafından)"
		}
		return "Dedenizin Erkek Kardeşi (anne tarafından)"

	// Es Akrabaliklari
	case AkrAMCA + "+" + AkrES:
		return "Yengeniz"
	case AkrDAYI + "+" + AkrES:
		return "Yengeniz"
	case AkrHALA + "+" + AkrES:
		return "Enişteniz"
	case AkrTEYZE + "+" + AkrES:
		return "Enişteniz"

	case AkrKUZEN + "+" + AkrES:
		if kadin {
			return "Kuzeninizin Eşi (Kadın)"
		}
		return "Kuzeninizin Eşi (Erkek)"
	case AkrYEGEN + "+" + AkrES:
		if kadin {
			return "Yeğeninizin Eşi (Kadın)"
		}
		return "Yeğeninizin Eşi (Erkek)"
	case AkrTORUN + "+" + AkrES:
		if kadin {
			return "Torununuzun Gelini"
		}
		return "Torununuzun Damadı"

	// 4+ Adimli Yollar
	case AkrBABA + "+" + AkrKARDES + "+" + AkrCOCUK + "+" + AkrCOCUK:
		return "Kuzeninizin Çocuğu (baba tarafından)"
	case AkrANNE + "+" + AkrKARDES + "+" + AkrCOCUK + "+" + AkrCOCUK:
		return "Kuzeninizin Çocuğu (anne tarafından)"
	case AkrBABA + "+" + AkrBABA + "+" + AkrKARDES + "+" + AkrCOCUK:
		return "Büyük Kuzeniniz (baba tarafından)"
	case AkrANNE + "+" + AkrANNE + "+" + AkrKARDES + "+" + AkrCOCUK:
		return "Büyük Kuzeniniz (anne tarafından)"
	case AkrES + "+" + AkrKARDES + "+" + AkrCOCUK + "+" + AkrCOCUK:
		return "Eşinizin Yeğeninin Çocuğu"

	// Dolayli torunlar
	case AkrBABA + "+" + AkrCOCUK + "+" + AkrCOCUK:
		return "Torununuz"
	case AkrANNE + "+" + AkrCOCUK + "+" + AkrCOCUK:
		return "Torununuz"

	// Cocuk+Es+Cocuk
	case AkrCOCUK + "+" + AkrES + "+" + AkrCOCUK:
		if kadin {
			return "Gelininizin Çocuğu"
		}
		return "Damadınızın Çocuğu"

	// Dede/Nine kardes
	case AkrDEDE_BABA + "+" + AkrKARDES:
		if kadin {
			return "Büyük Halanız"
		}
		return "Büyük Amcanız"
	case AkrNINE_BABA + "+" + AkrKARDES:
		if kadin {
			return "Büyük Teyzeniz"
		}
		return "Büyük Dayınız"
	case AkrDEDE_ANNE + "+" + AkrKARDES:
		if kadin {
			return "Büyük Halanız"
		}
		return "Büyük Amcanız"
	case AkrNINE_ANNE + "+" + AkrKARDES:
		if kadin {
			return "Büyük Teyzeniz"
		}
		return "Büyük Dayınız"

	// Ebeveyn uzerinden kardes
	case AkrBABA + "+" + AkrANNE + "+" + AkrCOCUK:
		if kadin {
			return "Halanız"
		}
		return "Amcanız"
	case AkrANNE + "+" + AkrCOCUK:
		if kadin {
			return "Kız Kardeşiniz"
		}
		return "Erkek Kardeşiniz"
	case AkrBABA + "+" + AkrCOCUK:
		if kadin {
			return "Kız Kardeşiniz"
		}
		return "Erkek Kardeşiniz"

	// Uzun zincirler
	case AkrBABA + "+" + AkrANNE + "+" + AkrCOCUK + "+" + AkrCOCUK + "+" + AkrCOCUK:
		return "Kuzenço"
	case AkrANNE + "+" + AkrBABA + "+" + AkrCOCUK + "+" + AkrCOCUK + "+" + AkrCOCUK:
		return "Kuzenço"
	}

	return ""
}

func sahipSizTamlayanEkle(sahipSiz string) string {
	if strings.HasSuffix(sahipSiz, "nız") {
		return sahipSiz + "ın"
	}
	if strings.HasSuffix(sahipSiz, "niz") {
		return sahipSiz + "in"
	}
	if strings.HasSuffix(sahipSiz, "nuz") {
		return sahipSiz + "un"
	}
	if strings.HasSuffix(sahipSiz, "nüz") {
		return sahipSiz + "ün"
	}
	if strings.Contains(sahipSiz, "Yengeniz") || strings.Contains(sahipSiz, "Enişteniz") || strings.Contains(sahipSiz, "Kuzeniniz") {
		return sahipSiz
	}
	return sahipSiz + "ın"
}

func tumBaglarGetir(ctx context.Context, kol *mongo.Collection) []bson.M {
	cursor, err := kol.Find(ctx, bson.M{"vt": "FikoYT.sistem.aileBaglari"})
	if err != nil {
		return nil
	}
	defer cursor.Close(ctx)

	var sonuclar []bson.M
	for cursor.Next(ctx) {
		var bag bson.M
		cursor.Decode(&bag)
		sonuclar = append(sonuclar, bag)
	}
	return sonuclar
}

func tumKisilerGetir(ctx context.Context, kol *mongo.Collection) []bson.M {
	cursor, err := kol.Find(ctx, bson.M{"vt": "FikoYT.sistem.soyAgaciKisiler"})
	if err != nil {
		return nil
	}
	defer cursor.Close(ctx)

	var sonuclar []bson.M
	for cursor.Next(ctx) {
		var kisi bson.M
		cursor.Decode(&kisi)
		sonuclar = append(sonuclar, kisi)
	}
	return sonuclar
}

func cinsiyetMapOlustur(kisiler []bson.M) map[string]string {
	cinsiyetMap := map[string]string{}
	for _, kisi := range kisiler {
		id := toHex(kisi["_id"])
		if id == "" {
			continue
		}
		if veri, ok := kisi["veri"].(bson.M); ok {
			cinsiyet, _ := veri["cinsiyet"].(string)
			if cinsiyet != "" {
				cinsiyetMap[id] = cinsiyet
			}
		}
	}
	return cinsiyetMap
}

func kisiIsimGetir(kisiler []bson.M, kisiId string) string {
	for _, kisi := range kisiler {
		id := toHex(kisi["_id"])
		if id == kisiId {
			if veri, ok := kisi["veri"].(bson.M); ok {
				isim, _ := veri["isim"].(string)
				soyIsim, _ := veri["soyIsim"].(string)
				return strings.TrimSpace(isim + " " + soyIsim)
			}
		}
	}
	return kisiId
}

func kisiIdBulIsimle(ctx context.Context, kol *mongo.Collection, isim string) string {
	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 {
		return ""
	}
	return toHex(kisi["_id"])
}

func akrabalikBul(ctx context.Context, kol *mongo.Collection, kisi1Id, kisi2Id string) ([]AkrabalikYolu, error) {
	baglar := tumBaglarGetir(ctx, kol)
	if len(baglar) == 0 {
		return nil, fmt.Errorf("aile bağı bulunamadı")
	}

	kisiler := tumKisilerGetir(ctx, kol)
	cinsiyetMap := cinsiyetMapOlustur(kisiler)

	yollar := tumAkrabalikYollariBul(baglar, kisi1Id, kisi2Id, cinsiyetMap)
	if len(yollar) == 0 {
		return nil, fmt.Errorf("iki kişi arasında akrabalık bağı bulunamadı")
	}

	return yollar, nil
}

func akrabalikBulDetayli(ctx context.Context, kol *mongo.Collection, kisi1Id, kisi2Id string) string {
	yollar, err := akrabalikBul(ctx, kol, kisi1Id, kisi2Id)
	if err != nil {
		return ""
	}

	var sb strings.Builder
	for i, yol := range yollar {
		if i == 0 {
			sb.WriteString(yol.Aciklama)
		} else {
			sb.WriteString(fmt.Sprintf(" (alternatif: %s)", yol.Aciklama))
		}
	}
	return sb.String()
}

func kullaniciBaglamiGrafOlustur(kisiIdStr string, kullaniciIdHex string, ctx context.Context, kol *mongo.Collection) string {
	baglar := tumBaglarGetir(ctx, kol)
	if len(baglar) == 0 {
		return ""
	}

	kisiler := tumKisilerGetir(ctx, kol)
	cinsiyetMap := cinsiyetMapOlustur(kisiler)

	komsuListe := komsuListeOlustur(baglar, cinsiyetMap)

	type akrabaInfo struct {
		id       string
		aciklama string
	}
	var akrabalar []akrabaInfo

	ziyaretEdilen := map[string]bool{}
	ziyaretEdilen[kisiIdStr] = true
	if kullaniciIdHex != "" && kullaniciIdHex != kisiIdStr {
		ziyaretEdilen[kullaniciIdHex] = true
	}

	type bfsOge struct {
		id  string
		yol []AkrabalikAdim
	}
	kuyruk := []bfsOge{{id: kisiIdStr, yol: nil}}

	maxDerinlik := 6

	for len(kuyruk) > 0 {
		mevcut := kuyruk[0]
		kuyruk = kuyruk[1:]

		if len(mevcut.yol) > maxDerinlik {
			continue
		}

		if mevcut.id != kisiIdStr {
			aciklama := yoluTurkceAcikla(mevcut.yol, cinsiyetMap)
			if aciklama != "" {
				akrabalar = append(akrabalar, akrabaInfo{id: mevcut.id, aciklama: aciklama})
			}
		}

		if len(mevcut.yol) >= maxDerinlik {
			continue
		}

		for _, komsuluk := range komsuListe[mevcut.id] {
			if !ziyaretEdilen[komsuluk.komsu] {
				ziyaretEdilen[komsuluk.komsu] = true
				yeniYol := make([]AkrabalikAdim, len(mevcut.yol)+1)
				copy(yeniYol, mevcut.yol)
				yeniYol[len(mevcut.yol)] = AkrabalikAdim{KisiId: komsuluk.komsu, AkrabalikTuru: komsuluk.tur}
				kuyruk = append(kuyruk, bfsOge{id: komsuluk.komsu, yol: yeniYol})
			}
		}
	}

	if len(akrabalar) == 0 {
		return ""
	}

	var sb strings.Builder
	sb.WriteString("\nAkrabalık bağları (yön: kullanıcıya göre):\n")

	for _, a := range akrabalar {
		detay := kisiDetayGetir(ctx, kol, a.id)
		if detay == nil {
			continue
		}
		if veri, ok := detay["veri"].(bson.M); ok {
			aIsim, _ := veri["isim"].(string)
			aSoyIsim, _ := veri["soyIsim"].(string)
			aCinsiyet, _ := veri["cinsiyet"].(string)
			aDogum, _ := veri["dogumTarihi"].(string)
			aVefat, _ := veri["vefatEtti"].(bool)
			aMeslek, _ := veri["meslek"].(string)
			aKizlik, _ := veri["kizlikSoyadi"].(string)

			satir := fmt.Sprintf("- %s: %s %s", a.aciklama, aIsim, aSoyIsim)
			if aKizlik != "" {
				satir += fmt.Sprintf(" (kızlık soyadı: %s)", aKizlik)
			}
			if aCinsiyet != "" {
				satir += fmt.Sprintf(" (cinsiyet: %s)", aCinsiyet)
			}
			if aDogum != "" {
				satir += fmt.Sprintf(" (doğum: %s)", aDogum)
			}
			if aMeslek != "" {
				satir += fmt.Sprintf(" (meslek: %s)", aMeslek)
			}
			if aVefat {
				satir += " (vefat etmiş)"
			}
			sb.WriteString(satir + "\n")
		}
	}

	return sb.String()
}

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

	kisi1Id, _ := args["kisi1_id"].(string)
	kisi1Isim, _ := args["kisi1_isim"].(string)
	kisi2Id, _ := args["kisi2_id"].(string)
	kisi2Isim, _ := args["kisi2_isim"].(string)

	if kisi1Id == "" && kisi1Isim != "" {
		kisi1Id = kisiIdBulIsimle(ctx, kol, kisi1Isim)
	}
	if kisi2Id == "" && kisi2Isim != "" {
		kisi2Id = kisiIdBulIsimle(ctx, kol, kisi2Isim)
	}

	if kisi1Id == "" {
		return mcpHata(id, "Birinci kişi bulunamadı. kisi1_id veya kisi1_isim gerekli.")
	}
	if kisi2Id == "" {
		return mcpHata(id, "İkinci kişi bulunamadı. kisi2_id veya kisi2_isim gerekli.")
	}

	if oid, err := primitive.ObjectIDFromHex(kisi1Id); err == nil {
		kisi1Id = oid.Hex()
	}
	if oid, err := primitive.ObjectIDFromHex(kisi2Id); err == nil {
		kisi2Id = oid.Hex()
	}

	yollar, err := akrabalikBul(ctx, kol, kisi1Id, kisi2Id)
	if err != nil {
		return mcpHata(id, err.Error())
	}

	kisiler := tumKisilerGetir(ctx, kol)
	kisi1Isim = kisiIsimGetir(kisiler, kisi1Id)
	kisi2Isim = kisiIsimGetir(kisiler, kisi2Id)

	var sb strings.Builder
	sb.WriteString(fmt.Sprintf("%s ile %s arasındaki akrabalık:\n\n", kisi1Isim, kisi2Isim))

	for i, yol := range yollar {
		if i == 0 {
			sb.WriteString(fmt.Sprintf("Ana ilişki: %s\n", yol.Aciklama))
		} else {
			sb.WriteString(fmt.Sprintf("Alternatif yol %d: %s (mesafe: %d adım)\n", i, yol.Aciklama, yol.Mesafe))
		}

		sb.WriteString("Yol: ")
		sb.WriteString(kisi1Isim)
		for _, adim := range yol.Yol {
			adimIsim := kisiIsimGetir(kisiler, adim.KisiId)
			turIsim := adim.AkrabalikTuru
			if bilgi, ok := akrabalikBilgiMap[adim.AkrabalikTuru]; ok {
				turIsim = bilgi.isim
			}
			sb.WriteString(fmt.Sprintf(" → [%s] → %s", turIsim, adimIsim))
		}
		sb.WriteString("\n\n")
	}

	return mcpSonuc(id, sb.String())
}
