package workflow

import (
	"context"
	"errors"
	"time"
)

var (
	// ErrNotFound akış ya da yürütme yoksa (ya da başka kullanıcıya aitse) döner.
	// Başkasının kaydı VARLIĞI sızdırılmadan aynı hatayı verir.
	ErrNotFound = errors.New("workflow: bulunamadı")
	// ErrBusy eşzamanlı yürütme sınırına ulaşıldı.
	ErrBusy = errors.New("workflow: çok fazla eşzamanlı yürütme var, biraz sonra tekrar dene")
	// ErrClosed servis kapanırken yeni yürütme başlatılamaz.
	ErrClosed = errors.New("workflow: servis kapanıyor")
	// ErrAlreadyFinished biten yürütme iptal edilemez.
	ErrAlreadyFinished = errors.New("workflow: yürütme zaten bitmiş")
)

// ListFilter akış listesini daraltır; sıfır değer "filtre yok" demektir.
type ListFilter struct {
	Query string // ad ya da açıklamada büyük/küçük harf duyarsız alt dize
}

// ExecutionFilter yürütme listesini daraltır.
type ExecutionFilter struct {
	WorkflowID string
	Status     RunStatus
}

// Repository akışların kalıcı depolama sözleşmesidir. Her işlem kullanıcıya göre kapsamlıdır:
// başkasının akışı ErrNotFound'dır. Uygulamalar: MongoDB (mongostore) ve bellek içi (MemoryRepo);
// ikisi de RepositoryContract'tan geçmelidir.
type Repository interface {
	Create(ctx context.Context, w *Workflow) error
	Get(ctx context.Context, userID, id string) (*Workflow, error)
	// Update kaydı TAMAMEN değiştirir (userId + id ile eşleşir). Yoksa ErrNotFound.
	Update(ctx context.Context, w *Workflow) error
	Delete(ctx context.Context, userID, id string) error
	// List en son güncellenen önce döner (limit<=0: hepsi). Sonuç asla nil değildir.
	List(ctx context.Context, userID string, f ListFilter, limit, offset int) ([]Workflow, error)
}

// ExecutionRepository yürütme kayıtlarının depolama sözleşmesidir.
type ExecutionRepository interface {
	CreateExecution(ctx context.Context, e *Execution) error
	GetExecution(ctx context.Context, userID, id string) (*Execution, error)
	// UpdateExecution kaydı TAMAMEN değiştirir. Yoksa ErrNotFound.
	UpdateExecution(ctx context.Context, e *Execution) error
	// ListExecutions en yeni önce döner (limit<=0: hepsi). Sonuç asla nil değildir.
	ListExecutions(ctx context.Context, userID string, f ExecutionFilter, limit, offset int) ([]Execution, error)
	// DeleteExecutionsByWorkflow bir akışın tüm yürütmelerini siler ve sayısını döndürür.
	DeleteExecutionsByWorkflow(ctx context.Context, userID, workflowID string) (int, error)
	// FailRunning "running" kalmış TÜM yürütmeleri (sunucu çöktü/yeniden başladı) failed yapar.
	FailRunning(ctx context.Context, reason string, at time.Time) (int, error)
}

// Store servisin ihtiyaç duyduğu iki depoyu birleştirir.
type Store interface {
	Repository
	ExecutionRepository
}
