package sms

import (
	"context"
	"sync"
	"testing"

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

// recordingHook is a stub MockRedisHook for verifying mock SMS Redis writes.
type recordingHook struct {
	mu    sync.Mutex
	calls []hookCall
}

type hookCall struct {
	key     string
	value   string
	seconds int
}

func (h *recordingHook) SetexCtx(_ context.Context, key, value string, seconds int) error {
	h.mu.Lock()
	defer h.mu.Unlock()
	h.calls = append(h.calls, hookCall{key: key, value: value, seconds: seconds})
	return nil
}

func TestMockSender_RedisHookWritesBody(t *testing.T) {
	hook := &recordingHook{}
	s := NewMockSender(WithMockRedis(hook, 60))

	_, err := s.Send(context.Background(), &Message{PhoneNumber: "+886912345678", Body: "your code is 123456"})
	require.NoError(t, err)

	hook.mu.Lock()
	defer hook.mu.Unlock()
	require.Len(t, hook.calls, 1)
	assert.Equal(t, MockSMSRedisKeyPrefix+"+886912345678", hook.calls[0].key)
	assert.Equal(t, "your code is 123456", hook.calls[0].value)
	assert.Equal(t, 60, hook.calls[0].seconds)
}

func TestMockSender_RedisHookSkippedWithoutPhone(t *testing.T) {
	hook := &recordingHook{}
	s := NewMockSender(WithMockRedis(hook, 0))

	_, err := s.Send(context.Background(), &Message{PhoneNumber: "", Body: "x"})
	require.NoError(t, err)

	hook.mu.Lock()
	defer hook.mu.Unlock()
	assert.Empty(t, hook.calls)
}

func TestMockSender_NoHookByDefault(t *testing.T) {
	s := NewMockSender()
	_, err := s.Send(context.Background(), &Message{PhoneNumber: "+886900000000", Body: "x"})
	require.NoError(t, err)
}
