package models

import (
	"encoding/json"
	"reflect"
	"testing"
)

// Legacy wire format — bare string array — must still unmarshal into
// value==label options with nil Tags. This guarantees that fixtures and
// tenant specs authored before picklist tags existed keep working.
func TestPicklistOptions_UnmarshalLegacyStringArray_TagsNil(t *testing.T) {
	input := []byte(`["Open","Working","Disqualified"]`)

	var opts PicklistOptions
	if err := opts.UnmarshalJSON(input); err != nil {
		t.Fatalf("UnmarshalJSON: %v", err)
	}
	if len(opts) != 3 {
		t.Fatalf("expected 3 options, got %d", len(opts))
	}
	for i, opt := range opts {
		if opt.Value != opt.Label {
			t.Errorf("opts[%d]: legacy form must have value==label, got %+v", i, opt)
		}
		if opt.Tags != nil {
			t.Errorf("opts[%d]: legacy form must not carry tags, got %v", i, opt.Tags)
		}
	}
}

// Structured form without tags must preserve empty Tags slice — new
// field must not break the most common authoring path.
func TestPicklistOptions_UnmarshalStructured_NoTags(t *testing.T) {
	input := []byte(`[{"value":"Open","label":"Open"},{"value":"Working","label":"Working"}]`)

	var opts PicklistOptions
	if err := opts.UnmarshalJSON(input); err != nil {
		t.Fatalf("UnmarshalJSON: %v", err)
	}
	if len(opts) != 2 {
		t.Fatalf("expected 2 options, got %d", len(opts))
	}
	for i, opt := range opts {
		if opt.Tags != nil {
			t.Errorf("opts[%d]: expected nil Tags, got %v", i, opt.Tags)
		}
	}
}

// Structured form with tags must roundtrip every tag on every option.
// This is the path the tenant spec uses to drive EntersPickTag.
func TestPicklistOptions_UnmarshalStructured_WithTags(t *testing.T) {
	input := []byte(`[
		{"value":"No Engagement","label":"No Engagement"},
		{"value":"Open","label":"Open"},
		{"value":"Working","label":"Working","tags":["test_tag_alpha"]},
		{"value":"Customer","label":"Customer","tags":["test_tag_alpha","test_tag_beta"]}
	]`)

	var opts PicklistOptions
	if err := opts.UnmarshalJSON(input); err != nil {
		t.Fatalf("UnmarshalJSON: %v", err)
	}
	if len(opts) != 4 {
		t.Fatalf("expected 4 options, got %d", len(opts))
	}
	if opts[0].Tags != nil {
		t.Errorf("No Engagement: expected nil Tags, got %v", opts[0].Tags)
	}
	if opts[1].Tags != nil {
		t.Errorf("Open: expected nil Tags, got %v", opts[1].Tags)
	}
	if !reflect.DeepEqual(opts[2].Tags, []string{"test_tag_alpha"}) {
		t.Errorf("Working Tags mismatch: %v", opts[2].Tags)
	}
	if !reflect.DeepEqual(opts[3].Tags, []string{"test_tag_alpha", "test_tag_beta"}) {
		t.Errorf("Customer Tags mismatch: %v", opts[3].Tags)
	}
}

// MarshalJSON → UnmarshalJSON must be a lossless roundtrip for tags.
// This protects canonical-JSON comparisons the tenant flow seeder
// relies on for idempotency.
func TestPicklistOptions_Roundtrip_PreservesTags(t *testing.T) {
	orig := PicklistOptions{
		{Value: "Open", Label: "Open"},
		{Value: "Working", Label: "Working", Tags: []string{"test_tag_alpha"}},
	}

	marshalled, err := json.Marshal(orig)
	if err != nil {
		t.Fatalf("json.Marshal: %v", err)
	}

	var roundtrip PicklistOptions
	if err := json.Unmarshal(marshalled, &roundtrip); err != nil {
		t.Fatalf("json.Unmarshal: %v", err)
	}
	if !reflect.DeepEqual(orig, roundtrip) {
		t.Errorf("roundtrip mismatch:\n orig: %+v\n  got: %+v", orig, roundtrip)
	}
}
