package executor

import (
	"testing"
	"time"
)

func TestBuildSelectJSONResult(t *testing.T) {
	ts := time.Date(2024, 1, 2, 3, 4, 5, 600*int(time.Millisecond), time.UTC)
	result := &QueryResult{
		Columns: []ColumnInfo{
			{Name: "id", Type: "int"},
			{Name: "name", Type: "text"},
			{Name: "active", Type: "boolean"},
			{Name: "payload", Type: "blob"},
			{Name: "created_at", Type: "timestamp"},
			{Name: "attrs", Type: "JSON"},
		},
		Rows: []Row{
			{Values: []interface{}{int32(7), "alice", true, []byte{0x01, 0x02}, ts, `{"a":1}`}},
		},
	}

	converted, err := buildSelectJSONResult(result)
	if err != nil {
		t.Fatalf("buildSelectJSONResult failed: %v", err)
	}
	if len(converted.Columns) != 1 {
		t.Fatalf("expected 1 column, got %d", len(converted.Columns))
	}
	if converted.Columns[0].Name != "json" || converted.Columns[0].Type != "text" {
		t.Fatalf("unexpected column metadata: %#v", converted.Columns[0])
	}
	if len(converted.Rows) != 1 {
		t.Fatalf("expected 1 row, got %d", len(converted.Rows))
	}
	got, ok := converted.Rows[0].Values[0].(string)
	if !ok {
		t.Fatalf("expected json string, got %T", converted.Rows[0].Values[0])
	}
	expected := `{"id":7,"name":"alice","active":true,"payload":"0x0102","created_at":"2024-01-02 03:04:05.600","attrs":{"a":1}}`
	if got != expected {
		t.Fatalf("unexpected JSON output: %s", got)
	}
}

func TestFormatJSONValue(t *testing.T) {
	ts := time.Date(2024, 6, 1, 12, 34, 56, 120*int(time.Millisecond), time.UTC)
	microTS := time.Date(2024, 6, 1, 12, 34, 56, 123456*int(time.Microsecond), time.UTC)
	testCases := []struct {
		name string
		val  interface{}
		typ  string
		want string
	}{
		{"text", "bob", "text", `"bob"`},
		{"boolean", true, "boolean", "true"},
		{"int", int32(42), "int", "42"},
		{"null", nil, "int", "null"},
		{"blob", []byte{0x0a}, "blob", `"0x0a"`},
		{"timestamp", ts, "timestamp", `"2024-06-01 12:34:56.120"`},
		{"timestamp micro", microTS, "timestamp", `"2024-06-01 12:34:56.123456"`},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			info := jsonTypeInfoFromCQL(tc.typ)
			got := formatJSONValue(tc.val, info)
			if got != tc.want {
				t.Fatalf("expected %s, got %s", tc.want, got)
			}
		})
	}
}
