package handlers

import (
	"encoding/json"
	"testing"

	"go.starlark.net/starlark"
)

// ── parseOnAdvanceResult ────────────────────

func TestParseOnAdvanceResult_None(t *testing.T) {
	result := parseOnAdvanceResult(starlark.None)
	if result != nil {
		t.Errorf("expected nil for None, got %+v", result)
	}
}

func TestParseOnAdvanceResult_Nil(t *testing.T) {
	result := parseOnAdvanceResult(nil)
	if result != nil {
		t.Errorf("expected nil for nil, got %+v", result)
	}
}

func TestParseOnAdvanceResult_Error(t *testing.T) {
	d := starlark.NewDict(1)
	_ = d.SetKey(starlark.String("error"), starlark.String("hook rejected"))
	result := parseOnAdvanceResult(d)
	if result == nil {
		t.Fatal("expected non-nil result")
	}
	if result.Error != "hook rejected" {
		t.Errorf("expected error='hook rejected', got %q", result.Error)
	}
}

func TestParseOnAdvanceResult_EnrichedStageData(t *testing.T) {
	inner := starlark.NewDict(2)
	_ = inner.SetKey(starlark.String("title"), starlark.String("Bug Triage"))
	_ = inner.SetKey(starlark.String("conversation_id"), starlark.String("conv-123"))

	d := starlark.NewDict(1)
	_ = d.SetKey(starlark.String("stage_data"), inner)

	result := parseOnAdvanceResult(d)
	if result == nil {
		t.Fatal("expected non-nil result")
	}
	if result.Error != "" {
		t.Errorf("unexpected error: %q", result.Error)
	}
	if result.EnrichedData == nil {
		t.Fatal("expected enriched data")
	}

	var data map[string]any
	if err := json.Unmarshal(result.EnrichedData, &data); err != nil {
		t.Fatalf("unmarshal enriched data: %v", err)
	}

	if data["title"] != "Bug Triage" {
		t.Errorf("expected title='Bug Triage', got %v", data["title"])
	}
	if data["conversation_id"] != "conv-123" {
		t.Errorf("expected conversation_id='conv-123', got %v", data["conversation_id"])
	}
}

func TestParseOnAdvanceResult_NonDict(t *testing.T) {
	result := parseOnAdvanceResult(starlark.String("unexpected"))
	if result != nil {
		t.Errorf("expected nil for non-dict, got %+v", result)
	}
}

func TestParseOnAdvanceResult_EmptyDict(t *testing.T) {
	d := starlark.NewDict(0)
	result := parseOnAdvanceResult(d)
	if result != nil {
		t.Errorf("expected nil for empty dict, got %+v", result)
	}
}

// ── starlarkDictToMap ───────────────────────

func TestStarlarkDictToMap_NestedStructure(t *testing.T) {
	inner := starlark.NewDict(1)
	_ = inner.SetKey(starlark.String("key"), starlark.String("value"))

	members := starlark.NewList([]starlark.Value{
		starlark.String("alice"),
		starlark.String("bob"),
	})

	outer := starlark.NewDict(3)
	_ = outer.SetKey(starlark.String("title"), starlark.String("Test"))
	_ = outer.SetKey(starlark.String("nested"), inner)
	_ = outer.SetKey(starlark.String("members"), members)

	m := starlarkDictToMap(outer)

	if m["title"] != "Test" {
		t.Errorf("expected title='Test', got %v", m["title"])
	}
	nested, ok := m["nested"].(map[string]any)
	if !ok {
		t.Fatalf("expected nested to be map, got %T", m["nested"])
	}
	if nested["key"] != "value" {
		t.Errorf("expected nested.key='value', got %v", nested["key"])
	}
	membersList, ok := m["members"].([]any)
	if !ok {
		t.Fatalf("expected members to be []any, got %T", m["members"])
	}
	if len(membersList) != 2 {
		t.Errorf("expected 2 members, got %d", len(membersList))
	}
}
