package builtin

import (
	"context"
	"fmt"
	"testing"

	"fiko-ai/internal/tool"
)

func runForm(t *testing.T, in map[string]any) (map[string]any, error) {
	t.Helper()
	return uiFormHandler(context.Background(), &tool.Tool{Name: "ui.form"}, in)
}

func formOf(t *testing.T, out map[string]any) ConfirmForm {
	t.Helper()
	f, ok := out["confirm"].(ConfirmForm)
	if !ok {
		t.Fatalf("çıktıda confirm formu yok: %+v", out)
	}
	return f
}

func TestUIForm_BuildsFormKeepingOrder(t *testing.T) {
	out, err := runForm(t, map[string]any{
		"title": "Yeni müşteri",
		"fields": []any{
			map[string]any{"key": "phone", "label": "Telefon", "required": true},
			map[string]any{"key": "city", "type": "select", "options": []any{"İstanbul", "Bursa"}, "value": "Bursa"},
			map[string]any{"key": "vip", "type": "checkbox", "value": "evet"},
			map[string]any{"key": "note", "type": "multiline"},
		},
	})
	if err != nil {
		t.Fatalf("hata: %v", err)
	}
	f := formOf(t, out)
	if f.Action != ConfirmActionAsk || f.Destructive || f.Risky {
		t.Errorf("bilgi formu yıkıcı olmamalı ve eylemi ask olmalı: %+v", f)
	}
	wantKeys := []string{"phone", "city", "vip", "note"}
	wantTypes := []string{"text", "enum", "bool", "textarea"}
	for i, fld := range f.Fields {
		if fld.Key != wantKeys[i] || fld.Type != wantTypes[i] {
			t.Errorf("alan %d = %s/%s, beklenen %s/%s (sıra korunmalı)", i, fld.Key, fld.Type, wantKeys[i], wantTypes[i])
		}
	}
	if f.Fields[1].Value != "Bursa" || len(f.Fields[1].Options) != 2 {
		t.Errorf("seçim alanı bozuk: %+v", f.Fields[1])
	}
	if f.Fields[2].Value != "true" {
		t.Errorf("onay kutusu 'evet' → true olmalı: %q", f.Fields[2].Value)
	}
	if !f.Fields[0].Missing || len(f.MissingFields) != 1 || f.MissingFields[0] != "phone" {
		t.Errorf("zorunlu boş alan eksik sayılmalı: %+v", f.MissingFields)
	}
	if f.ConfirmLabel != "Gönder" || f.CancelLabel != "Vazgeç" {
		t.Errorf("varsayılan düğme yazıları yanlış: %q / %q", f.ConfirmLabel, f.CancelLabel)
	}
	if out["pending"] != true || out["ok"] != false {
		t.Errorf("model 'henüz yapılmadı' bilgisini almalı: %+v", out)
	}
}

func TestUIForm_EnumNeedsTwoOptions(t *testing.T) {
	out, err := runForm(t, map[string]any{"title": "x", "fields": []any{
		map[string]any{"key": "a", "type": "enum", "options": []any{"tek"}},
	}})
	if err != nil {
		t.Fatal(err)
	}
	if got := formOf(t, out).Fields[0]; got.Type != "text" || len(got.Options) != 0 {
		t.Errorf("tek seçenekli liste serbest metne düşmeli: %+v", got)
	}
}

func TestUIForm_EnumValueOutsideOptionsIsCleared(t *testing.T) {
	out, _ := runForm(t, map[string]any{"title": "x", "fields": []any{
		map[string]any{"key": "a", "type": "enum", "options": []any{"x", "y"}, "value": "z"},
	}})
	if v := formOf(t, out).Fields[0].Value; v != "" {
		t.Errorf("seçenek dışı değer boşaltılmalı, gelen %q", v)
	}
}

func TestUIForm_SkipsBadAndDuplicateKeys(t *testing.T) {
	out, err := runForm(t, map[string]any{"title": "x", "fields": []any{
		map[string]any{"key": "1abc"},
		map[string]any{"key": ""},
		map[string]any{"key": "tamam"},
		map[string]any{"key": "tamam", "label": "tekrar"},
		"bir metin", // harita değil
	}})
	if err != nil {
		t.Fatal(err)
	}
	if n := len(formOf(t, out).Fields); n != 1 {
		t.Errorf("yalnızca 1 geçerli alan kalmalı, kalan %d", n)
	}
}

func TestUIForm_NoValidFieldsIsError(t *testing.T) {
	for _, in := range []map[string]any{
		{"title": "x"},
		{"title": "x", "fields": []any{}},
		{"title": "x", "fields": []any{map[string]any{"key": "1bozuk"}}},
	} {
		if _, err := runForm(t, in); err == nil {
			t.Errorf("geçerli alan yokken hata beklenirdi: %+v", in)
		}
	}
}

func TestUIForm_AcceptsFieldsAsJSONString(t *testing.T) {
	out, err := runForm(t, map[string]any{
		"title":  "x",
		"fields": `[{"key":"ad","label":"Ad","required":"true"}]`,
	})
	if err != nil {
		t.Fatalf("JSON metni kabul edilmeliydi: %v", err)
	}
	f := formOf(t, out)
	if len(f.Fields) != 1 || !f.Fields[0].Required {
		t.Errorf("JSON metninden alan okunamadı: %+v", f.Fields)
	}
}

func TestUIForm_LimitsFieldCount(t *testing.T) {
	var raw []any
	for i := 0; i < 30; i++ {
		raw = append(raw, map[string]any{"key": fmt.Sprintf("f%d", i)})
	}
	out, _ := runForm(t, map[string]any{"title": "x", "fields": raw})
	if n := len(formOf(t, out).Fields); n != formMaxFields {
		t.Errorf("alan sayısı %d ile sınırlanmalı, gelen %d", formMaxFields, n)
	}
}

func TestUIForm_DefaultTitle(t *testing.T) {
	out, _ := runForm(t, map[string]any{"fields": []any{map[string]any{"key": "a"}}})
	if got := formOf(t, out).Title; got == "" {
		t.Error("başlık verilmezse varsayılan kullanılmalı")
	}
}

func TestUIForm_RegisteredAndValid(t *testing.T) {
	defs, err := allDefinitions(Options{})
	if err != nil {
		t.Fatal(err)
	}
	for _, d := range defs {
		if d.Tool.Name != "ui.form" {
			continue
		}
		tl := d.Tool
		tool.Normalize(&tl)
		if errs := tool.Validate(&tl); len(errs) != 0 {
			t.Fatalf("ui.form tanımı geçersiz: %+v", errs)
		}
		if tl.Risk != tool.RiskLow || len(tl.Permissions) != 1 || tl.Permissions[0] != "execute" {
			t.Errorf("ui.form düşük riskli ve yalnızca execute izinli olmalı: %+v", tl)
		}
		if !d.Enabled {
			t.Error("ui.form varsayılan açık olmalı")
		}
		return
	}
	t.Fatal("ui.form kayıtlı araçlar arasında yok")
}
