package claim

import (
	"context"
	"time"
)

// Action bir claim üzerinde yapılan işlemdir.
type Action string

const (
	ActionCreate Action = "create" // yeni kayıt (After dolu)
	ActionUpdate Action = "update" // metin/anahtar değişti (Before + After)
	ActionStatus Action = "status" // durum değişti: guncellendi / celiskili / gecersiz (Before + After)
	ActionDelete Action = "delete" // kayıt silindi (Before dolu: silinen değer burada yaşamaya devam eder)
	ActionView   Action = "view"   // kişisel veri içeren kayda erişim (KVKK; Faz 8-10)
	ActionExport Action = "export" // toplu dışa aktarma (yalnız patron; Faz 10)
)

// Valid bilinen bir işlem mi?
func (a Action) Valid() bool {
	switch a {
	case ActionCreate, ActionUpdate, ActionStatus, ActionDelete, ActionView, ActionExport:
		return true
	}
	return false
}

// AuditEntry `audit` koleksiyonundaki tek denetim kaydıdır: kim, ne zaman, neyi, önceki/sonraki değer.
//
// Not: internal/audit paketi (JSON satır günlüğü) ile KARIŞTIRILMAMALI; bu, kayıt başına değişiklik
// geçmişidir ve veritabanında yaşar. ClaimID bir yabancı anahtar DEĞİLDİR: claim silinse de geçmişi kalır.
type AuditEntry struct {
	ID      string    `json:"id" bson:"_id"`
	ClaimID string    `json:"claimId" bson:"claimId"`
	Action  Action    `json:"action" bson:"action"`
	By      string    `json:"by" bson:"by"` // işlemi yapan kullanıcı kimliği
	ByName  string    `json:"byName,omitempty" bson:"byName,omitempty"`
	At      time.Time `json:"at" bson:"at"`
	// Before/After kaydın VEKTÖRSÜZ anlık görüntüleridir (Claim.Snapshot); depo vektörü her
	// durumda atar, çağıranın unutması geçmişi şişirmesin.
	Before *Claim `json:"before,omitempty" bson:"before,omitempty"`
	After  *Claim `json:"after,omitempty" bson:"after,omitempty"`
}

// Clone derin kopya döndürür; Before/After vektörsüzdür.
func (e AuditEntry) Clone() AuditEntry {
	cp := e
	if e.Before != nil {
		cp.Before = e.Before.Snapshot()
	}
	if e.After != nil {
		cp.After = e.After.Snapshot()
	}
	return cp
}

// AuditRepository denetim deposudur. YALNIZCA EKLEME: Update/Delete bilerek YOKTUR; denetim
// geçmişi değiştirilemez ve silinemez (spec: kural 2, KVKK madde 4).
type AuditRepository interface {
	// Append kaydı ekler. ID/ClaimID/By boşsa ya da Action geçersizse hata; aynı kimlik ErrDuplicate.
	Append(ctx context.Context, e *AuditEntry) error
	// ListByClaim bir kaydın geçmişi, yeni önce (eşitlikte ID). limit<=0: hepsi. Asla nil değil.
	// Claim silinmiş olsa da çalışır.
	ListByClaim(ctx context.Context, claimID string, limit, offset int) ([]AuditEntry, error)
	// ListByActor bir kullanıcının yaptığı işlemler, yeni önce. Erişim denetimi (kim neye baktı) için.
	ListByActor(ctx context.Context, by string, limit, offset int) ([]AuditEntry, error)
}

// Validate kaydın yazılabilir olup olmadığını denetler (her AuditRepository uygulaması çağırır:
// geçmişe eksik/anlamsız kayıt girmesin).
func (e *AuditEntry) Validate() error {
	var errs []FieldError
	add := func(field, msg string) { errs = append(errs, FieldError{Field: field, Message: msg}) }
	if e.ID == "" {
		add("id", "boş olamaz")
	}
	if e.ClaimID == "" {
		add("claimId", "boş olamaz")
	}
	if e.By == "" {
		add("by", "boş olamaz")
	}
	if !e.Action.Valid() {
		add("action", "bilinmeyen işlem")
	}
	if e.At.IsZero() {
		add("at", "boş olamaz")
	}
	if len(errs) > 0 {
		return &ValidationError{Errors: errs}
	}
	return nil
}
