package mysql

import (
	"context"
	"testing"

	"hyapp/internal/testutil/mysqlschema"
	"hyapp/pkg/appcode"
	roomservice "hyapp/services/room-service/internal/room/service"
)

func TestEnsureGiftOperationDoesNotReactivateBeforeServicePayloadCheck(t *testing.T) {
	schema := mysqlschema.New(t, mysqlschema.Config{
		EnvVar:         "ROOM_SERVICE_MYSQL_TEST_DSN",
		InitDBPath:     mysqlschema.InitDBPath(t, mysqlschema.CallerFile(t, 1), "..", "..", "..", "deploy", "mysql", "initdb", "001_room_service.sql"),
		DatabasePrefix: "hyapp_room_gift_reactivate",
	})
	ctx := appcode.WithContext(context.Background(), appcode.Default)
	repository, err := Open(ctx, schema.DSN, 4, 4)
	if err != nil {
		t.Fatalf("open repository: %v", err)
	}
	defer repository.Close()

	stored := roomservice.GiftOperation{
		AppCode: appcode.Default, RoomID: "room-reactivate", CommandID: "cmd-reactivate", ActorUserID: 101,
		CommandPayload: []byte("stored-command"), RequestPayload: []byte("stored-request"),
		Status: roomservice.GiftOperationStatusCompensated, LastError: "insufficient balance",
		CreatedAtMS: 1_000, UpdatedAtMS: 1_000,
	}
	if _, created, err := repository.EnsureGiftOperation(ctx, stored); err != nil || !created {
		t.Fatalf("insert compensated operation: created=%v err=%v", created, err)
	}
	conflicting := stored
	conflicting.CommandPayload = []byte("different-command")
	conflicting.RequestPayload = []byte("different-request")
	conflicting.UpdatedAtMS = 2_000
	got, created, err := repository.EnsureGiftOperation(ctx, conflicting)
	if err != nil || created {
		t.Fatalf("read duplicate operation: created=%v err=%v", created, err)
	}
	if got.Status != roomservice.GiftOperationStatusCompensated || string(got.CommandPayload) != "stored-command" {
		t.Fatalf("Ensure mutated an unverified historical operation: %+v", got)
	}

	got, reactivated, err := repository.ReactivateCompensatedGiftOperation(ctx, stored.RoomID, stored.CommandID, 3_000)
	if err != nil || !reactivated || got.Status != roomservice.GiftOperationStatusPending {
		t.Fatalf("payload-checked CAS did not reactivate: reactivated=%v operation=%+v err=%v", reactivated, got, err)
	}
	got, reactivated, err = repository.ReactivateCompensatedGiftOperation(ctx, stored.RoomID, stored.CommandID, 4_000)
	if err != nil || reactivated || got.Status != roomservice.GiftOperationStatusPending {
		t.Fatalf("reactivation must be idempotent after status advances: reactivated=%v operation=%+v err=%v", reactivated, got, err)
	}
}
