package builtin

import (
	"fmt"
	"sort"
	"strings"
)

// confirm.go, yazma/silme işlemlerini kullanıcı ONAYINA bağlayan form üreticisidir.
//
// CANLI HATA (04.10.2026): kullanıcı "proje silme aracı yok" dedi. Araç kodda VARDIR
// (biz.delete) ama HIGH risk + delete izni istediği için modele hiç gösterilmiyordu.
// Modele araçları açmak, geri alınamaz işlemleri modele emanet etmek demektir; o yüzden
// bunun yerine kararı KULLANICIYA verdik: araç çalışmak yerine bir ONAY FORMU döner,
// kullanıcı Onayla'ya basınca işlem gerçekten yapılır.
//
// Tasarım kararı: formu araç ÜRETİR, ajan İLETİR, arayüz GÖSTERİR, kullanıcı DÖNDÜRÜR.
// Böylece "onay" bir metin cevabı değil, yapılandırılmış bir etkileşimdir; eksik alan
// kullanıcıya form üstünde sorulur (konuşma tek turda bozulmaz).
//
// Politika (settings.ConfirmMode) her işlemde uygulanır:
//   - always  : her yazma/silme onay ister
//   - risky   : yalnızca geri alınamaz işlemler (silme, arşiv) onay ister   [varsayılan]
//   - missing : yalnızca eksik/şüpheli veri varsa sorar (doğrulama)
//   - never   : onay istemez

// Onay modu sabitleri. Bunlar settings paketindeki değerlerle BİREBİR aynıdır;
// tek yerden yönetilmesi için burada da konur ve settings.ValidConfirmMode ile eşleşir.
const (
	ConfirmAlways  = "always"
	ConfirmRisky   = "risky"
	ConfirmMissing = "missing"
	ConfirmNever   = "never"
)

// ConfirmField, form üzerinde gösterilen tek bir alandır.
type ConfirmField struct {
	Key      string `json:"key"`
	Label    string `json:"label"`
	Value    string `json:"value"`
	Editable bool   `json:"editable"` // kullanıcı değiştirebilir mi
	Required bool   `json:"required"` // boş bırakılırsa işlem yapılmaz
	Missing  bool   `json:"missing"`  // henüz doldurulmadı (vurgulanır)
	Hint     string `json:"hint,omitempty"`
	Options  []any  `json:"options,omitempty"` // enum alanları için seçenekler
	Type     string `json:"type,omitempty"`    // text | number | date | enum
}

// ConfirmForm, arayüze gönderilen onay formudur. `kind` alanı ayırıcıdır:
// sunucu çıktısında kind=confirm varsa arayüz interaktif form açar.
type ConfirmForm struct {
	Kind          string         `json:"kind"` // "confirm"
	Action        string         `json:"action"`
	Tool          string         `json:"tool"`
	Title         string         `json:"title"`
	Message       string         `json:"message,omitempty"`
	Fields        []ConfirmField `json:"fields"`
	MissingFields []string       `json:"missingFields,omitempty"`
	ConfirmLabel  string         `json:"confirmLabel"`
	CancelLabel   string         `json:"cancelLabel"`
	Destructive   bool           `json:"destructive"` // geri alınamaz işlem
	// Payload onaylandığında aracın HANGİ GİRDİYLE çalıştırılacağıdır.
	// Kullanıcı formu düzenlediyse arayüz bunu günceller.
	Payload map[string]any `json:"payload"`
	// Risky, işlemin geri alınamaz olup olmadığını bildirir (politika uygulaması için).
	Risky bool `json:"risky"`
}

// needsConfirm, verilen işlemin kullanıcı onayı gerektirip gerektirmediğini söyler.
//
// Kural: geri alınamaz işlem (risky) her zaman onay ister; diğerleri mod'a bağlıdır.
//   - always  → her şey
//   - risky   → yalnızca geri alınamazlar (silme, arşiv)
//   - missing → yalnızca eksik alan varsa
//   - never   → hiçbiri
func needsConfirm(mode, action string, risky bool, missing int) bool {
	switch mode {
	case ConfirmNever:
		return false
	case ConfirmAlways:
		return true
	case ConfirmMissing:
		return missing > 0
	default: // ConfirmRisky (varsayılan)
		return risky
	}
}

// confirmResult, onay gerektiğinde tool'ın döndürdüğü çıktıdır.
// İçinde `ok:false` vardır: model de "işlem henüz yapılmadı" bilgisini alır.
func confirmResult(f ConfirmForm) map[string]any {
	f.Kind = "confirm"
	return map[string]any{
		"confirm": f,
		"ok":      false,
		"pending": true,
		"note":    "İŞLEM HENÜZ YAPILMADI. Kullanıcı onay formunu göndermeden tekrar çağırma.",
	}
}

// onayFormu, verilen alan listesinden bir ConfirmForm kurar.
func onayFormu(tool, action, title, message string, fields []ConfirmField, payload map[string]any,
	risky bool, confirmLabel, cancelLabel string) map[string]any {
	missing := make([]string, 0, len(fields))
	for _, f := range fields {
		if f.Required && strings.TrimSpace(f.Value) == "" {
			missing = append(missing, f.Key)
		}
	}
	if payload == nil {
		payload = map[string]any{}
	}
	if confirmLabel == "" {
		confirmLabel = "Onayla"
	}
	if cancelLabel == "" {
		cancelLabel = "Vazgeç"
	}
	return confirmResult(ConfirmForm{
		Action:        action,
		Tool:          tool,
		Title:         title,
		Message:       message,
		Fields:        sortFields(fields),
		MissingFields: missing,
		ConfirmLabel:  confirmLabel,
		CancelLabel:   cancelLabel,
		Destructive:   risky,
		Payload:       payload,
		Risky:         risky,
	})
}

// ---- alan yardımcıları ----

// fMetin düz metin alanı üretir.
func fMetin(key, label, value string) ConfirmField {
	return ConfirmField{Key: key, Label: label, Value: value, Type: "text", Editable: true}
}

// fZorunlu zorunlu metin alanı üretir.
func fZorunlu(key, label, value string) ConfirmField {
	return ConfirmField{Key: key, Label: label, Value: value, Type: "text", Editable: true, Required: true}
}

// fSayı sayısal alan üretir.
func fSayi(key, label string, value any) ConfirmField {
	return ConfirmField{Key: key, Label: label, Value: fmt.Sprint(value), Type: "number", Editable: true}
}

// fZorunluSayı zorunlu sayısal alan üretir.
func fZorunluSayi(key, label string, value any) ConfirmField {
	return ConfirmField{Key: key, Label: label, Value: fmt.Sprint(value), Type: "number", Editable: true, Required: true}
}

// fTarih tarih alanı üretir (YYYY-MM-DD).
func fTarih(key, label, value string) ConfirmField {
	return ConfirmField{Key: key, Label: label, Value: value, Type: "date", Editable: true, Hint: "YYYY-MM-DD"}
}

// fSecim seçenekli (enum) alan üretir.
func fSecim(key, label, value string, options []string) ConfirmField {
	opts := make([]any, 0, len(options))
	for _, o := range options {
		opts = append(opts, o)
	}
	return ConfirmField{Key: key, Label: label, Value: value, Type: "enum", Editable: true, Options: opts}
}

// fSabit değiştirilemez alan üretir (kayıt kimliği gibi): kullanıcı yanlışlıkla değiştiremez.
func fSabit(key, label, value string) ConfirmField {
	return ConfirmField{Key: key, Label: label, Value: value, Type: "text", Editable: false}
}

// sortFields alanları sabit sırayla döndürür: eksik zorunlu alanlar en önce, seçim/tarih/
// sayı sonra, serbest metin en son, değiştirilemez alanlar en sonda.
//
// Neden? Kullanıcının gözü önce neyi dolduracağını bilmeli; sıralama rastgele olursa form
// her seferinde farklı görünür ve hangi alanın eksik olduğu bulunamaz.
func sortFields(in []ConfirmField) []ConfirmField {
	rank := func(f ConfirmField) int {
		switch {
		case f.Required && f.Missing:
			return 0 // en önce eksik zorunlu alanlar
		case f.Required:
			return 1
		case f.Type == "enum":
			return 2
		case f.Type == "date":
			return 3
		case f.Type == "number":
			return 4
		case !f.Editable:
			return 6
		default:
			return 5
		}
	}
	out := append([]ConfirmField(nil), in...)
	sort.SliceStable(out, func(i, j int) bool { return rank(out[i]) < rank(out[j]) })
	return out
}
