// Package skill dinamik Skill sisteminin alan modelini, doğrulamasını, depo arayüzünü
// ve iş kurallarını (Registry) içerir.
//
// Skill ile Tool ayrıdır (PROJE.MD): Skill "yapay zekânın NE yapabildiğini" tanımlar,
// Tool gerçek işi yapar. Skill bir tool'a executorType=tool + executorConfig{"tool": "..."} ile bağlanır.
// Skill kod içine gömülmez; MongoDB'de tutulur ve Angular arayüzünden yönetilir.
package skill

import "time"

// Status skill'in yaşam döngüsü durumudur.
type Status string

const (
	// StatusDraft yarım/test edilmemiş skill; retrieval'a girmez, eksik alanlara izin verilir.
	StatusDraft Status = "draft"
	// StatusActive kullanıma hazır skill; executor tanımı zorunludur.
	StatusActive Status = "active"
	// StatusDisabled kapatılmış skill; silinmeden devre dışı bırakılır.
	StatusDisabled Status = "disabled"
)

// Valid bilinen bir durum mu?
func (s Status) Valid() bool {
	return s == StatusDraft || s == StatusActive || s == StatusDisabled
}

// ExecutorType skill'in nasıl yürütüleceğini belirler.
type ExecutorType string

const (
	// ExecutorTool gerçek bir Tool'u çağırır. executorConfig: {"tool": "catia.create_plane"}.
	ExecutorTool ExecutorType = "tool"
	// ExecutorLLM yalnızca LLM ile yürütülür. executorConfig: {"prompt": "..."}.
	ExecutorLLM ExecutorType = "llm"
)

// Valid bilinen bir yürütücü tipi mi?
func (e ExecutorType) Valid() bool { return e == ExecutorTool || e == ExecutorLLM }

// ParamType parametre tipleridir (JSON Schema tipleriyle uyumlu).
type ParamType string

const (
	ParamString  ParamType = "string"
	ParamNumber  ParamType = "number"
	ParamInteger ParamType = "integer"
	ParamBoolean ParamType = "boolean"
	ParamArray   ParamType = "array"
	ParamObject  ParamType = "object"
)

// Valid bilinen bir parametre tipi mi?
func (p ParamType) Valid() bool {
	switch p {
	case ParamString, ParamNumber, ParamInteger, ParamBoolean, ParamArray, ParamObject:
		return true
	}
	return false
}

// Parameter skill'in tek bir girdisidir (ör. offset: number).
type Parameter struct {
	Name        string    `bson:"name" json:"name"`
	Type        ParamType `bson:"type" json:"type"`
	Description string    `bson:"description,omitempty" json:"description,omitempty"`
	Required    bool      `bson:"required,omitempty" json:"required,omitempty"`
	Default     any       `bson:"default,omitempty" json:"default,omitempty"`
}

// Example örnek bir kullanıcı cümlesi ve ondan beklenen argümanlardır.
// Örnekler hem embedding'e girer (arama kalitesi) hem de LLM'e few-shot olarak verilebilir.
type Example struct {
	Input     string         `bson:"input" json:"input"`
	Arguments map[string]any `bson:"arguments,omitempty" json:"arguments,omitempty"`
}

// Skill PROJE.MD "SKILL SYSTEM" bölümündeki alanların tamamını taşır.
type Skill struct {
	ID          string `bson:"_id" json:"id"`
	Name        string `bson:"name" json:"name"`
	Description string `bson:"description" json:"description"`
	Version     string `bson:"version" json:"version"`
	Status      Status `bson:"status" json:"status"`

	Parameters   []Parameter    `bson:"parameters" json:"parameters"`
	InputSchema  map[string]any `bson:"inputSchema,omitempty" json:"inputSchema,omitempty"`
	OutputSchema map[string]any `bson:"outputSchema,omitempty" json:"outputSchema,omitempty"`

	ExecutorType   ExecutorType   `bson:"executorType" json:"executorType"`
	ExecutorConfig map[string]any `bson:"executorConfig,omitempty" json:"executorConfig,omitempty"`

	Examples    []Example `bson:"examples" json:"examples"`
	Permissions []string  `bson:"permissions" json:"permissions"`
	Tags        []string  `bson:"tags" json:"tags"`

	// Embedding vektör aramada kullanılır (Faz 3b'de doldurulur). API'de dönmez: büyük ve işe yaramaz.
	Embedding []float32 `bson:"embedding,omitempty" json:"-"`

	CreatedAt time.Time `bson:"createdAt" json:"createdAt"`
	UpdatedAt time.Time `bson:"updatedAt" json:"updatedAt"`
}

// Clone derin bir kopya döndürür; depolar ve çağıranlar birbirinin verisini değiştiremesin.
func (s Skill) Clone() Skill {
	c := s
	if s.Parameters != nil {
		c.Parameters = make([]Parameter, len(s.Parameters))
		for i, p := range s.Parameters {
			p.Default = cloneAny(p.Default)
			c.Parameters[i] = p
		}
	}
	c.InputSchema = cloneMap(s.InputSchema)
	c.OutputSchema = cloneMap(s.OutputSchema)
	c.ExecutorConfig = cloneMap(s.ExecutorConfig)
	if s.Examples != nil {
		c.Examples = make([]Example, len(s.Examples))
		for i, e := range s.Examples {
			e.Arguments = cloneMap(e.Arguments)
			c.Examples[i] = e
		}
	}
	c.Permissions = cloneSlice(s.Permissions)
	c.Tags = cloneSlice(s.Tags)
	c.Embedding = cloneSlice(s.Embedding)
	return c
}

// cloneSlice nil'i nil, boşu boş korur (JSON'da null ile [] farkı korunur).
func cloneSlice[T any](in []T) []T {
	if in == nil {
		return nil
	}
	out := make([]T, len(in))
	copy(out, in)
	return out
}

func cloneMap(m map[string]any) map[string]any {
	if m == nil {
		return nil
	}
	out := make(map[string]any, len(m))
	for k, v := range m {
		out[k] = cloneAny(v)
	}
	return out
}

func cloneAny(v any) any {
	switch t := v.(type) {
	case map[string]any:
		return cloneMap(t)
	case []any:
		out := make([]any, len(t))
		for i, x := range t {
			out[i] = cloneAny(x)
		}
		return out
	default:
		return v
	}
}
