package store_test

import (
	"context"
	"testing"

	"github.com/jackc/pgx/v5/pgxpool"
	"github.com/stretchr/testify/require"
)

// countLoginEvents counts a user's login_events via the superuser pool, which
// bypasses RLS — so the assertion sees the true row count regardless of scope.
func countLoginEvents(t *testing.T, p *pgxpool.Pool, userID string) int {
	t.Helper()
	var n int
	require.NoError(t, p.QueryRow(context.Background(),
		`SELECT count(*) FROM login_events WHERE user_id = $1`, userID).Scan(&n))
	return n
}

// TestStampLoginThrottlesToOnePerDay: repeated stamps within the same day insert
// exactly one row — the throttle that keeps login_events one-row-per-active-day.
func TestStampLoginThrottlesToOnePerDay(t *testing.T) {
	ctx := context.Background()
	s := newStore(t)
	super := rawPool(t)
	resetDB(t, super)
	_, err := super.Exec(ctx, `INSERT INTO users (id) VALUES ($1)`, userA)
	require.NoError(t, err)

	for i := 0; i < 3; i++ {
		require.NoError(t, s.StampLogin(ctx, userA))
	}
	require.Equal(t, 1, countLoginEvents(t, super, userA),
		"three same-day stamps must collapse to one row")
}

// TestStampLoginRecordsOncePerNewDay: with yesterday's row already present, a
// stamp today is NOT throttled — it appends the day's row, so distinct active days
// accumulate (the substrate the gate's distinct-week count reads).
func TestStampLoginRecordsOncePerNewDay(t *testing.T) {
	ctx := context.Background()
	s := newStore(t)
	super := rawPool(t)
	resetDB(t, super)
	_, err := super.Exec(ctx, `INSERT INTO users (id) VALUES ($1)`, userA)
	require.NoError(t, err)

	// Seed an event dated yesterday (before today's start), so the throttle's
	// "row exists with seen_at >= start-of-today" probe finds nothing for today.
	_, err = super.Exec(ctx,
		`INSERT INTO login_events (user_id, seen_at) VALUES ($1, NOW() - INTERVAL '1 day')`, userA)
	require.NoError(t, err)

	require.NoError(t, s.StampLogin(ctx, userA))
	require.Equal(t, 2, countLoginEvents(t, super, userA),
		"a stamp on a new day must append a second row")

	// A second stamp the same day is throttled again.
	require.NoError(t, s.StampLogin(ctx, userA))
	require.Equal(t, 2, countLoginEvents(t, super, userA),
		"the same-day repeat must not add a third row")
}

// TestStampLoginIsUserScoped: one user's stamp lands only on that user's rows —
// the throttle probe is RLS-scoped, so user B's existing same-day row neither
// suppresses nor is touched by user A's stamp.
func TestStampLoginIsUserScoped(t *testing.T) {
	ctx := context.Background()
	s := newStore(t)
	super := rawPool(t)
	resetDB(t, super)
	_, err := super.Exec(ctx, `INSERT INTO users (id) VALUES ($1), ($2)`, userA, userB)
	require.NoError(t, err)

	// B already has a same-day row; it must not throttle A's first stamp.
	_, err = super.Exec(ctx, `INSERT INTO login_events (user_id) VALUES ($1)`, userB)
	require.NoError(t, err)

	require.NoError(t, s.StampLogin(ctx, userA))
	require.Equal(t, 1, countLoginEvents(t, super, userA), "A's stamp must record despite B's same-day row")
	require.Equal(t, 1, countLoginEvents(t, super, userB), "A's stamp must not touch B's rows")
}
