package main

import (
	"context"
	"log/slog"

	"fiko-ai/config"
	"fiko-ai/internal/agent"
	"fiko-ai/internal/claim"
	"fiko-ai/internal/llm"
	"fiko-ai/internal/user"
)

// setupClaimReader sohbetin ekip ortak hafızasını OKUMASINI kurar (Faz 4).
// FIKO_CLAIMS_READ=false ise nil döner (hiçbir şey bağlanmaz).
//
// Okuma da YALNIZCA gerçek oturum kimliğiyle çalışır (yazma ile aynı kural): üyelik kapalıyken
// X-Fiko-User başlığı güvenilmez olduğundan ekip verisi hiç okunmaz ve açılışta bu açıkça söylenir.
func setupClaimReader(repo claim.Repository, audit claim.AuditRepository, p llm.Provider, emb llm.Embedder,
	userSvc *user.Service, cfg config.Config, log *slog.Logger) agent.ClaimReader {
	if !cfg.Claims.Read {
		log.Info("Iddia Hafızası okuma KAPALI (FIKO_CLAIMS_READ=false): ekip hafızası cevaplara girmez")
		return nil
	}
	if repo == nil || p == nil {
		log.Warn("Iddia Hafızası okuma açık ama depo/sağlayıcı yok; kapalı kalıyor")
		return nil
	}
	if audit == nil {
		// Kişisel veri (personel, pdks) okumaları denetlenmek ZORUNDA (KVKK): denetimsiz okuma kurulmaz.
		log.Warn("Iddia Hafızası okuma açık ama denetim deposu yok; kapalı kalıyor")
		return nil
	}
	if !cfg.Users.Enabled || userSvc == nil {
		log.Warn("Iddia Hafızası okuma açık ama üyelik sistemi KAPALI (FIKO_USERS_ENABLED=false): " +
			"gerçek oturum kimliği olmadan ekip hafızası okunmayacak")
	}
	if cfg.Ollama.EmbedModel == "" {
		emb = nil
		log.Warn("Iddia Hafızası okuma embedding olmadan çalışıyor (OLLAMA_EMBED_MODEL boş): yalnızca liste soruları cevaplanır")
	}
	rd := claim.NewReader(repo, p, emb, claim.ReadConfig{Model: cfg.Ollama.Model, EmbedModel: cfg.Ollama.EmbedModel}).WithAudit(audit)
	log.Info("Iddia Hafızası okuma ETKİN", "üyelik", cfg.Users.Enabled, "embedding", cfg.Ollama.EmbedModel != "")
	return claimReader{reader: rd, id: newClaimIdentity(userSvc, cfg), log: log}
}

// claimReader agent.ClaimReader'ı claim.Reader'a bağlar: önce kimliği doğrular, sonra hazırlar.
type claimReader struct {
	reader *claim.Reader
	id     *claim.Identity
	log    *slog.Logger
}

// Read hata döndürmez (sözleşme): kimlik doğrulanamazsa ya da hazırlık başarısız olursa sıfır değer
// döner ve sohbet hafızasız sürer. Mesaj içeriği (kişisel veri olabilir) log'a YAZILMAZ; yalnızca sayılar.
func (c claimReader) Read(ctx context.Context, req agent.ClaimReadRequest) agent.ClaimContext {
	if c.reader == nil || c.id == nil {
		return agent.ClaimContext{}
	}
	actor, err := c.id.Actor(ctx, req.UserID)
	if err != nil {
		c.log.Debug("ekip hafızası okunmadı: kimlik doğrulanamadı", "neden", err.Error(), "conversation", req.ConversationID)
		return agent.ClaimContext{}
	}
	// Tür bazlı görünürlük (Faz 8): okuyan kişi (rol + kimlik) okuyucuya iletilir; özel türler
	// (personel, pdks) yalnızca patrona ve ilgili kişiye görünür, arama ÖNCESİ süzülür.
	prep, err := c.reader.Prepare(ctx, req.Text, actor)
	if err != nil {
		c.log.Warn("ekip hafızası hazırlanamadı", "err", err, "conversation", req.ConversationID)
		return agent.ClaimContext{}
	}
	attrs := []any{"niyet", string(prep.Intent.Type), "isabet", len(prep.Hits), "degraded", prep.Degraded, "conversation", req.ConversationID}
	if prep.List != nil {
		attrs = append(attrs, "tür", prep.List.Kind, "toplam", prep.List.Total, "yetkisiz", prep.List.Denied)
	}
	if prep.Report != nil {
		attrs = append(attrs, "rapor", string(prep.Report.Type), "bulunamadi", prep.Report.NotFound)
	}
	c.log.Info("ekip hafızası hazırlandı", attrs...)
	// Liste ve rapor istekleri yeni bilgi taşımaz: yazma yakalaması (ek çıkarım LLM çağrısı) atlanır.
	return agent.ClaimContext{Prompt: prep.Prompt, Append: prep.Append, List: prep.List != nil || prep.Report != nil}
}
