//go:build integration

package inttest

import (
	"context"
	"testing"
	"time"

	"github.com/google/uuid"

	"scrabble/backend/internal/account"
	"scrabble/backend/internal/engine"
	"scrabble/backend/internal/game"
)

// TestRobotFriendRequestIsPerGameAndReaped checks that sending a friend request to a
// disguised-robot opponent is recorded per-game in robot_friend_requests — never in the
// friendships table or against the shared robot account — that a re-send is idempotent, and
// that the reaper deletes the row once its game has been finished past the retention window
// while keeping the row for an active game.
func TestRobotFriendRequestIsPerGameAndReaped(t *testing.T) {
	ctx := context.Background()
	svc := newSocialService()
	accs := account.NewStore(testDB)
	human := provisionAccount(t)
	robot, err := accs.ProvisionRobot(ctx, "robot-friend-"+uuid.NewString(), "Robbie")
	if err != nil {
		t.Fatalf("provision robot: %v", err)
	}
	g, err := newGameService().Create(ctx, game.CreateParams{
		Variant: engine.VariantEnglish, Seats: []uuid.UUID{human, robot.ID},
		TurnTimeout: 24 * time.Hour, Seed: openingSeed(t),
	})
	if err != nil {
		t.Fatalf("create game: %v", err)
	}

	if err := svc.RequestInGame(ctx, human, robot.ID, g.ID); err != nil {
		t.Fatalf("request robot: %v", err)
	}
	rfr, err := svc.ListRobotFriendRequests(ctx, human)
	if err != nil {
		t.Fatalf("list robot friend requests: %v", err)
	}
	if len(rfr) != 1 || rfr[0].GameID != g.ID || rfr[0].Seat != 1 {
		t.Fatalf("robot friend requests = %v, want one for game %s seat 1", rfr, g.ID)
	}
	// The friendships table must stay empty: no outgoing request against the shared robot account.
	if out, _ := svc.ListOutgoingRequests(ctx, human); len(out) != 0 {
		t.Errorf("friendships outgoing must be empty for a robot request, got %v", out)
	}

	// A re-send to the same game+seat is idempotent (the UNIQUE constraint collapses it).
	if err := svc.RequestInGame(ctx, human, robot.ID, g.ID); err != nil {
		t.Fatalf("re-request robot: %v", err)
	}
	if rfr, _ := svc.ListRobotFriendRequests(ctx, human); len(rfr) != 1 {
		t.Fatalf("re-request must not duplicate, got %v", rfr)
	}

	// While the game is active the reaper keeps the row.
	if n, err := svc.ReapExpiredRobotFriendRequests(ctx); err != nil || n != 0 {
		t.Fatalf("reap on active game = (%d, %v), want (0, nil)", n, err)
	}
	if rfr, _ := svc.ListRobotFriendRequests(ctx, human); len(rfr) != 1 {
		t.Fatalf("active-game request must survive the reaper, got %v", rfr)
	}

	// Finish the game well past the retention window: the reaper now deletes the row.
	finished := time.Now().UTC().Add(-8 * 24 * time.Hour)
	if _, err := testDB.ExecContext(ctx,
		`UPDATE backend.games SET status='finished', finished_at=$1 WHERE game_id=$2`, finished, g.ID); err != nil {
		t.Fatalf("finish game: %v", err)
	}
	if n, err := svc.ReapExpiredRobotFriendRequests(ctx); err != nil || n != 1 {
		t.Fatalf("reap on long-finished game = (%d, %v), want (1, nil)", n, err)
	}
	if rfr, _ := svc.ListRobotFriendRequests(ctx, human); len(rfr) != 0 {
		t.Errorf("long-finished request not reaped: %v", rfr)
	}
}
