package main

import (
	"reflect"
	"testing"
	"time"

	"github.com/kami/maven/internal/dialogue"
	"github.com/kami/maven/internal/router"
)

// TestSlotsParity — dialogue.Slots is a hand-kept copy of router.Slots
// (dialogue must not import router: import cycle). Drift is silent, so this
// test compares the two field sets by name and type. If it fails, add the new
// field to both structs AND to toDialogueSlots/applyDialogueSlots in
// followup.go — do not relax the test.
func TestSlotsParity(t *testing.T) {
	fields := func(v any) map[string]string {
		rt := reflect.TypeOf(v)
		out := make(map[string]string, rt.NumField())
		for i := 0; i < rt.NumField(); i++ {
			f := rt.Field(i)
			out[f.Name] = f.Type.String()
		}
		return out
	}
	rf, df := fields(router.Slots{}), fields(dialogue.Slots{})
	for name, typ := range rf {
		dt, ok := df[name]
		if !ok {
			t.Errorf("router.Slots.%s (%s) missing from dialogue.Slots", name, typ)
			continue
		}
		if dt != typ {
			t.Errorf("field %s: router has %s, dialogue has %s", name, typ, dt)
		}
	}
	for name, typ := range df {
		if _, ok := rf[name]; !ok {
			t.Errorf("dialogue.Slots.%s (%s) missing from router.Slots", name, typ)
		}
	}
}

// TestSlotsRoundTrip — the converters carry every field. A field the parity
// test accepts can still be dropped in transit, so round-trip a fully
// populated value and compare.
func TestSlotsRoundTrip(t *testing.T) {
	full := router.Slots{
		Time:    time.Date(2026, 8, 2, 11, 0, 0, 0, time.UTC),
		HasTime: true,
		Fn:      "restart",
		Args:    []string{"nginx"},
		HasFn:   true,
		Key:     "water",
		Value:   `"drank"`,
		HasKey:  true,
		Text:    "выпил воды",
	}
	// Every field must be non-zero, or the round-trip proves nothing.
	rv := reflect.ValueOf(full)
	for i := 0; i < rv.NumField(); i++ {
		if rv.Field(i).IsZero() {
			t.Fatalf("field %s is zero: extend this fixture so the round-trip covers it",
				rv.Type().Field(i).Name)
		}
	}
	if got := applyDialogueSlots(router.Slots{}, toDialogueSlots(full)); !reflect.DeepEqual(got, full) {
		t.Errorf("round-trip lost a slot:\n got %+v\nwant %+v", got, full)
	}
}
