package knowledge

import (
	"context"
	"errors"
)

var (
	// ErrNotFound istenen belge ya da parça yoksa döner.
	ErrNotFound = errors.New("knowledge: kayıt bulunamadı")
	// ErrDuplicate aynı kullanıcının aynı içeriği (hash) ya da aynı kimliği tekrar eklemesidir.
	ErrDuplicate = errors.New("knowledge: aynı içerikli belge zaten var")
)

// Repository kalıcı depolama sözleşmesidir. Uygulamalar: MongoDB (mongostore) ve bellek içi (MemoryRepo).
// Tek doğrulama yolu RepositoryContract'tır; iki uygulama da aynı testten geçmelidir.
//
// KULLANICI İZOLASYONU: liste/sayım/arama süzgeçlerinde UserID boşsa SONUÇ BOŞTUR
// (hiçbir belge boş kullanıcıya ait değildir); asla "herkes" anlamına gelmez.
type Repository interface {
	// CreateDocument belgeyi ekler. Aynı (userId, hash) ya da aynı kimlik için ErrDuplicate.
	CreateDocument(ctx context.Context, d *Document) error
	// GetDocument yoksa ErrNotFound. Sahiplik denetimi Service'tedir.
	GetDocument(ctx context.Context, id string) (*Document, error)
	// GetDocumentByHash kullanıcının aynı içerikli belgesini döndürür; yoksa ErrNotFound.
	GetDocumentByHash(ctx context.Context, userID, hash string) (*Document, error)
	// UpdateDocument kaydı kimliğe göre TAMAMEN değiştirir; yoksa ErrNotFound.
	UpdateDocument(ctx context.Context, d *Document) error
	// DeleteDocument belgeyi VE tüm parçalarını siler; belge yoksa ErrNotFound.
	// Sıra: önce parçalar, sonra belge — yarıda kalırsa belge görünür kalır ve yeniden silinebilir
	// (tersi, aranabilir ama sahipsiz parçalar bırakırdı).
	DeleteDocument(ctx context.Context, id string) error
	// ListDocuments en yeni önce (createdAt azalan, eşitlikte kimlik artan) döner; limit<=0: hepsi.
	// Sonuç asla nil değildir.
	ListDocuments(ctx context.Context, f DocumentFilter, limit, offset int) ([]Document, error)
	// CountDocuments süzgece uyan belge sayısıdır (ListDocuments ile aynı süzgeç anlamı).
	CountDocuments(ctx context.Context, f DocumentFilter) (int, error)
	// PendingDocuments, KULLANICIDAN BAĞIMSIZ olarak durumu "indexing" olan belgeleri döndürür.
	// Yalnızca açılışta yarım kalan embedding işlerini sürdürmek içindir (sunucu işi kapatılırken
	// ya da çökerken yarıda kalmış olabilir); kullanıcıya dönük hiçbir uç bunu kullanmaz.
	PendingDocuments(ctx context.Context) ([]Document, error)

	// AddChunks parçaları ekler. Belgenin varlığını denetlemez.
	AddChunks(ctx context.Context, chunks []Chunk) error
	// ChunksOfDocument belgenin parçalarını index'e göre artan döndürür; limit<=0: hepsi.
	// Embedding dahildir. Sonuç asla nil değildir.
	ChunksOfDocument(ctx context.Context, documentID string, limit, offset int) ([]Chunk, error)
	// SearchableChunks arama adaylarını (embedding dahil) döndürür. Sıra belirsizdir.
	SearchableChunks(ctx context.Context, f ChunkFilter) ([]Chunk, error)
	// SetChunkEmbedding tek parçanın vektörünü yazar; parça yoksa (belge silinmiş olabilir) ErrNotFound.
	SetChunkEmbedding(ctx context.Context, chunkID string, vec []float32, model string) error
	// DeleteChunks belgenin tüm parçalarını siler; parça yoksa hata DEĞİLDİR (idempotent).
	DeleteChunks(ctx context.Context, documentID string) error
}
