package agent

import (
	"context"
	"testing"

	"fiko-ai/internal/protocol"
)

// askOut, ui.form aracının ürettiği çıktıya benzeyen bir bilgi formu çıktısıdır.
func askOut() map[string]any {
	return map[string]any{"confirm": map[string]any{
		"action": "ask", "title": "Bilgiler", "tool": "ui.form",
		"confirmLabel": "Gönder", "cancelLabel": "Vazgeç",
		"fields": []any{
			map[string]any{"key": "phone", "label": "Telefon", "value": "", "editable": true, "type": "text"},
			map[string]any{"key": "city", "label": "Şehir", "value": "Bursa", "editable": true, "type": "enum",
				"options": []any{"Bursa", "İstanbul"}},
			map[string]any{"key": "vip", "label": "VIP", "value": "false", "editable": true, "type": "bool"},
		},
	}}
}

// Politika "never" olsa bile bilgi formu GİZLENEMEZ: form istenen çıktının kendisidir.
func TestAskForm_AlwaysSentEvenWhenPolicyIsNever(t *testing.T) {
	for _, mode := range []string{"never", "risky", "missing", "always"} {
		a, _, sent := newConfirmAgent(t, mode)
		openRun(a, "c1", sent)
		id, ok := a.handleConfirmForm(Input{ConversationID: "c1"}, "tc", "ui.form", askOut())
		if !ok || id == "" {
			t.Errorf("mode=%s: bilgi formu gönderilmeliydi", mode)
			continue
		}
		if len(*sent) != 1 || (*sent)[0].Type != protocol.ServerToolConfirm {
			t.Errorf("mode=%s: tool.confirm olayı yok: %+v", mode, *sent)
		}
	}
}

// Bilgi formu cevaplanınca ARAÇ ÇALIŞMAZ; cevaplar çözüm olayında döner.
func TestAskForm_AnswerReturnsValuesAndRunsNoTool(t *testing.T) {
	a, r, sent := newConfirmAgent(t, "risky")
	openRun(a, "c1", sent)
	cid, _ := a.handleConfirmForm(Input{ConversationID: "c1"}, "tc", "ui.form", askOut())

	a.ConfirmAnswer(context.Background(), "c1", "u1", protocol.ToolConfirmAnswerPayload{
		ConfirmID: cid, Confirmed: true,
		Values: map[string]string{"phone": " 0532 111 22 33 ", "vip": "true", "olmayan": "yok say"},
	})

	if len(r.calls) != 0 {
		t.Fatalf("bilgi formu araç çalıştırmamalı: %v", r.calls)
	}
	last := (*sent)[len(*sent)-1]
	if last.Type != protocol.ServerToolConfirmResolved {
		t.Fatalf("çözüm olayı bekleniyordu: %+v", last)
	}
	p, _ := last.Payload.(protocol.ToolConfirmResolvedPayload)
	if !p.Confirmed || p.Action != "ask" {
		t.Errorf("confirmed=true ve action=ask beklenir: %+v", p)
	}
	if p.Values["phone"] != "0532 111 22 33" {
		t.Errorf("değer kırpılmalı: %q", p.Values["phone"])
	}
	if p.Values["city"] != "Bursa" {
		t.Errorf("düzenlenmeyen alan varsayılanını korumalı: %q", p.Values["city"])
	}
	if p.Values["vip"] != "true" {
		t.Errorf("onay kutusu true olmalı: %q", p.Values["vip"])
	}
	if _, bad := p.Values["olmayan"]; bad {
		t.Error("formda olmayan anahtar cevaba sızmamalı")
	}
}

func TestAskForm_EnumOutsideOptionsIsCleared(t *testing.T) {
	a, _, sent := newConfirmAgent(t, "risky")
	openRun(a, "c1", sent)
	cid, _ := a.handleConfirmForm(Input{ConversationID: "c1"}, "tc", "ui.form", askOut())

	a.ConfirmAnswer(context.Background(), "c1", "u1", protocol.ToolConfirmAnswerPayload{
		ConfirmID: cid, Confirmed: true, Values: map[string]string{"city": "Ankara"},
	})
	p, _ := (*sent)[len(*sent)-1].Payload.(protocol.ToolConfirmResolvedPayload)
	if p.Values["city"] != "" {
		t.Errorf("seçenek dışı değer boşaltılmalı: %q", p.Values["city"])
	}
}

func TestAskForm_CancelReturnsNoValues(t *testing.T) {
	a, r, sent := newConfirmAgent(t, "risky")
	openRun(a, "c1", sent)
	cid, _ := a.handleConfirmForm(Input{ConversationID: "c1"}, "tc", "ui.form", askOut())

	a.ConfirmAnswer(context.Background(), "c1", "u1",
		protocol.ToolConfirmAnswerPayload{ConfirmID: cid, Confirmed: false, Cancelled: true})

	p, _ := (*sent)[len(*sent)-1].Payload.(protocol.ToolConfirmResolvedPayload)
	if p.Confirmed || len(p.Values) != 0 {
		t.Errorf("vazgeçilen formda cevap dönmemeli: %+v", p)
	}
	if len(r.calls) != 0 {
		t.Error("vazgeçilince araç çalışmamalı")
	}
}

// Aynı bilgi formu iki kez cevaplanamaz (cevap iki kez sohbete düşmesin).
func TestAskForm_SingleUse(t *testing.T) {
	a, _, sent := newConfirmAgent(t, "risky")
	openRun(a, "c1", sent)
	cid, _ := a.handleConfirmForm(Input{ConversationID: "c1"}, "tc", "ui.form", askOut())
	ans := protocol.ToolConfirmAnswerPayload{ConfirmID: cid, Confirmed: true}
	a.ConfirmAnswer(context.Background(), "c1", "u1", ans)
	a.ConfirmAnswer(context.Background(), "c1", "u1", ans)

	p, _ := (*sent)[len(*sent)-1].Payload.(protocol.ToolConfirmResolvedPayload)
	if p.Confirmed || len(p.Values) != 0 {
		t.Errorf("ikinci cevap geçersiz olmalı: %+v", p)
	}
}

func TestAskForm_HintTellsModelToWait(t *testing.T) {
	if h := confirmHint(askOut()); h == "" || h == "onay bekleniyor." {
		t.Errorf("bilgi formu için özel ipucu beklenir: %q", h)
	}
}

func TestToolRank_FormIntent(t *testing.T) {
	for _, msg := range []string{"bana bir form göster", "müşteri bilgilerini formda sor", "bana soru sor"} {
		if intentScores(msg)["ui.form"] == 0 {
			t.Errorf("%q → ui.form puanı 0", msg)
		}
	}
	for _, msg := range []string{"dosya formatı nedir", "formül hesapla"} {
		if intentScores(msg)["ui.form"] != 0 {
			t.Errorf("%q yanlışlıkla ui.form'a eşleşti", msg)
		}
	}
}
