package usecase_test

import (
	"context"
	"testing"
	"time"

	"apps/backend/internal/module/usage/domain"
	"apps/backend/internal/module/usage/repository"
	"apps/backend/internal/module/usage/usecase"

	"github.com/stretchr/testify/require"
)

func analyticsNano(t *testing.T, value string) int64 {
	t.Helper()
	parsed, err := time.Parse(time.RFC3339, value)
	require.NoError(t, err)
	return parsed.UnixNano()
}

func TestParseAnalyticsQueryValidationAndCaps(t *testing.T) {
	_, err := usecase.ParseAnalyticsQuery("week", "2026-01-01", "2026-01-02")
	require.ErrorIs(t, err, domain.ErrInvalidRange)
	_, err = usecase.ParseAnalyticsQuery("day", "2026-01-03", "2026-01-02")
	require.ErrorIs(t, err, domain.ErrInvalidRange)
	_, err = usecase.ParseAnalyticsQuery("day", "2026-01-01", "2026-04-04")
	require.ErrorIs(t, err, domain.ErrInvalidRange)
	_, err = usecase.ParseAnalyticsQuery("month", "2023-01-01", "2025-12-31")
	require.NoError(t, err)
}

func TestTenantAnalyticsUsesInclusiveUTCBoundsAndSeparateModes(t *testing.T) {
	repo := repository.NewMemory()
	for _, event := range []*domain.Event{
		{ID: "before", UID: 1, Meter: domain.MeterAICopy, Credits: 9, KeyMode: domain.KeyModePlatform, CreatedAt: analyticsNano(t, "2026-01-31T23:59:59Z")},
		{ID: "first", UID: 1, Meter: domain.MeterAICopy, Credits: 2, KeyMode: domain.KeyModePlatform, CreatedAt: analyticsNano(t, "2026-02-01T00:00:00Z")},
		{ID: "byok", UID: 1, Meter: domain.MeterWebSearch, Credits: 99, KeyMode: domain.KeyModeByok, CreatedAt: analyticsNano(t, "2026-02-02T12:00:00Z")},
		{ID: "last", UID: 1, Meter: domain.MeterWebSearch, Credits: 1, KeyMode: domain.KeyModePlatform, CreatedAt: analyticsNano(t, "2026-02-02T23:59:59.999999999Z")},
		{ID: "after", UID: 1, Meter: domain.MeterAICopy, Credits: 9, KeyMode: domain.KeyModePlatform, CreatedAt: analyticsNano(t, "2026-02-03T00:00:00Z")},
	} {
		require.NoError(t, repo.InsertEvent(context.Background(), event))
	}
	query, err := usecase.ParseAnalyticsQuery("day", "2026-02-01", "2026-02-02")
	require.NoError(t, err)
	result, err := usecase.New(repo, nil).TenantAnalytics(context.Background(), query, []domain.AnalyticsMember{{UID: 1, Email: "one@example.test", DisplayName: "One"}})
	require.NoError(t, err)

	require.Equal(t, 3, result.ConsumedCredits)
	require.Equal(t, 1, result.AICalls)
	require.Equal(t, 1, result.SearchCalls)
	require.Equal(t, 1, result.Byok.CallCount)
	require.Equal(t, 0, result.Byok.ByMeter[domain.MeterWebSearch].Credits)
	require.Equal(t, 1, result.Byok.ByMeter[domain.MeterWebSearch].Count)
	require.Len(t, result.Series, 2)
	require.Equal(t, 2, result.Series[0].ConsumedCredits)
	require.Equal(t, 1, result.Series[1].ConsumedCredits)
	require.Equal(t, 1, result.Series[1].ByokCallCount)
	require.Equal(t, 3, result.Members[0].TotalCredits)
	require.Equal(t, 1, result.Members[0].ByokCallCount)
}

func TestMemoryListEventsRangeUsesExclusiveUpperBound(t *testing.T) {
	repo := repository.NewMemory()
	for i, nano := range []int64{99, 100, 199, 200} {
		require.NoError(t, repo.InsertEvent(context.Background(), &domain.Event{ID: string(rune('a' + i)), CreatedAt: nano}))
	}
	list, err := repo.ListEventsRange(context.Background(), 100, 200)
	require.NoError(t, err)
	require.Len(t, list, 2)
	require.Equal(t, int64(100), list[0].CreatedAt)
	require.Equal(t, int64(199), list[1].CreatedAt)
}
