package mysqlutil

import (
	"bytes"
	"context"
	"encoding/json"
	"reflect"
	"testing"

	"github.com/mem9-ai/drive9/pkg/testtidb"
)

// Pins interpolateParams wire behavior against MySQL 8: JSON []byte must
// insert into a JSON column without error 3144, and a brace-prefixed binary
// blob must still land in a BLOB column.
func TestOpenInstrumentedJSONBytesRoundTrip(t *testing.T) {
	ctx := context.Background()
	inst, err := testtidb.Start(ctx)
	if err != nil {
		t.Fatalf("start mysql: %v", err)
	}
	t.Cleanup(func() { _ = inst.Close(context.Background()) })

	db, err := OpenInstrumented(ctx, inst.DSN, RoleUser)
	if err != nil {
		t.Fatalf("OpenInstrumented: %v", err)
	}
	t.Cleanup(func() { _ = CloseInstrumented(db) })
	t.Cleanup(func() {
		_, _ = db.ExecContext(context.Background(), `DROP TABLE IF EXISTS interpolate_json_wire`)
	})

	if _, err := db.ExecContext(ctx, `DROP TABLE IF EXISTS interpolate_json_wire`); err != nil {
		t.Fatalf("drop table: %v", err)
	}
	if _, err := db.ExecContext(ctx, `CREATE TABLE interpolate_json_wire (
		id INT PRIMARY KEY,
		payload JSON NOT NULL,
		blob_col BLOB NOT NULL
	)`); err != nil {
		t.Fatalf("create table: %v", err)
	}

	jsonPayload := []byte(`{"k":1}`)
	blob := []byte{'{', 0xff, 0x00, 0xfe}
	if _, err := db.ExecContext(ctx, `INSERT INTO interpolate_json_wire (id, payload, blob_col) VALUES (?, ?, ?)`,
		1, jsonPayload, blob); err != nil {
		t.Fatalf("insert interpolated json/blob: %v", err)
	}

	var gotJSON, gotBlob []byte
	if err := db.QueryRowContext(ctx, `SELECT payload, blob_col FROM interpolate_json_wire WHERE id = ?`, 1).
		Scan(&gotJSON, &gotBlob); err != nil {
		t.Fatalf("select: %v", err)
	}
	var got, want any
	if err := json.Unmarshal(gotJSON, &got); err != nil {
		t.Fatalf("decode payload %q: %v", gotJSON, err)
	}
	if err := json.Unmarshal(jsonPayload, &want); err != nil {
		t.Fatalf("decode want: %v", err)
	}
	if !reflect.DeepEqual(got, want) {
		t.Fatalf("payload = %s, want %s", gotJSON, jsonPayload)
	}
	if !bytes.Equal(gotBlob, blob) {
		t.Fatalf("blob = %x, want %x", gotBlob, blob)
	}
}
