package store_test

import (
	"context"
	"testing"

	"github.com/stretchr/testify/require"

	"git.d-ma.be/mathias/tapir/internal/adapters/store"
	"git.d-ma.be/mathias/tapir/internal/domain"
	"git.d-ma.be/mathias/tapir/internal/ports"
)

// Static check: Store satisfies the shared TranscriptStore port (ADR-021).
var _ ports.TranscriptStore = (*store.Store)(nil)

func TestSaveAndGetTranscript_RoundTrip(t *testing.T) {
	s := newStore(t)
	resetDB(t, rawPool(t))
	ctx := context.Background()

	want := domain.Transcript{Source: domain.SourceCaptions, Language: "en", Content: "the words"}
	require.NoError(t, s.SaveTranscript(ctx, "youtube", "vid-1", want))

	got, ok, err := s.GetTranscript(ctx, "youtube", "vid-1")
	require.NoError(t, err)
	require.True(t, ok, "a saved transcript must be found")
	require.Equal(t, domain.SourceCaptions, got.Source)
	require.Equal(t, "en", got.Language)
	require.Equal(t, "the words", got.Content)
	require.True(t, got.HasText())
}

func TestGetTranscript_Miss(t *testing.T) {
	s := newStore(t)
	resetDB(t, rawPool(t))

	_, ok, err := s.GetTranscript(context.Background(), "youtube", "absent")
	require.NoError(t, err, "a miss is not an error")
	require.False(t, ok)
}

// A stored "no captions" outcome is a real hit: callers must skip without
// re-fetching, so ok is true even though there is no text (ADR-021 / ADR-007).
func TestSaveAndGetTranscript_NoneIsAStoredHit(t *testing.T) {
	s := newStore(t)
	resetDB(t, rawPool(t))
	ctx := context.Background()

	require.NoError(t, s.SaveTranscript(ctx, "youtube", "vid-none", domain.Transcript{Source: domain.SourceNone}))

	got, ok, err := s.GetTranscript(ctx, "youtube", "vid-none")
	require.NoError(t, err)
	require.True(t, ok, "a stored SourceNone is a hit, not a miss")
	require.Equal(t, domain.SourceNone, got.Source)
	require.False(t, got.HasText())
}

// A transient 429 must never be persisted as a terminal transcript, or a later
// read would mask the rate-limit as a permanent "no transcript" (ADR-014).
func TestSaveTranscript_RejectsRateLimited(t *testing.T) {
	s := newStore(t)
	resetDB(t, rawPool(t))

	err := s.SaveTranscript(context.Background(), "youtube", "vid-429",
		domain.Transcript{Source: domain.SourceRateLimited})
	require.Error(t, err)

	_, ok, _ := s.GetTranscript(context.Background(), "youtube", "vid-429")
	require.False(t, ok, "a rejected rate-limited save must leave nothing stored")
}

func TestSaveTranscript_UpsertLastWriteWins(t *testing.T) {
	s := newStore(t)
	resetDB(t, rawPool(t))
	ctx := context.Background()

	require.NoError(t, s.SaveTranscript(ctx, "youtube", "vid-up", domain.Transcript{Source: domain.SourceNone}))
	require.NoError(t, s.SaveTranscript(ctx, "youtube", "vid-up",
		domain.Transcript{Source: domain.SourceCaptions, Language: "en", Content: "now resolved"}))

	got, ok, err := s.GetTranscript(ctx, "youtube", "vid-up")
	require.NoError(t, err)
	require.True(t, ok)
	require.Equal(t, domain.SourceCaptions, got.Source)
	require.Equal(t, "now resolved", got.Content)
}
