package repository

import (
	"context"
	"fmt"
	"testing"

	"backend/pkg/member/domain"

	"github.com/alicebob/miniredis/v2"
	"github.com/stretchr/testify/assert"
	"github.com/zeromicro/go-zero/core/stores/redis"
)

func setupMiniRedis() (*miniredis.Miniredis, *redis.Redis) {
	// 啟動 setupMiniRedis 作為模擬的 Redis 服務
	mr, err := miniredis.Run()
	if err != nil {
		panic("failed to start miniRedis: " + err.Error())
	}

	// 使用 setupMiniRedis 的地址配置 go-zero Redis 客戶端
	redisConf := redis.RedisConf{
		Host: mr.Addr(),
		Type: "node",
	}
	r := redis.MustNewRedis(redisConf)

	return mr, r
}

func TestVerifyCodeRepository_IsVerifyCodeExist(t *testing.T) {
	mr, r := setupMiniRedis()
	defer mr.Close()

	repo := NewVerifyCodeRepository(r)
	ctx := context.Background()

	loginID := "test_user"
	checkType := "email"
	code := "123456"

	// 預設驗證碼不存在
	rk := domain.GetCheckVerifyKey(checkType, loginID)
	existingCode, err := repo.IsVerifyCodeExist(ctx, loginID, checkType)
	assert.NoError(t, err)
	assert.Equal(t, "", existingCode, "驗證碼應該不存在")

	// 設置驗證碼
	err = r.SetexCtx(ctx, rk, code, 600)
	assert.NoError(t, err)

	// 再次檢查驗證碼
	existingCode, err = repo.IsVerifyCodeExist(ctx, loginID, checkType)
	assert.NoError(t, err)
	assert.Equal(t, code, existingCode, "驗證碼應該正確存在")
}

func TestVerifyCodeRepository_DelVerifyCode(t *testing.T) {
	mr, r := setupMiniRedis()
	defer mr.Close()

	repo := NewVerifyCodeRepository(r)
	ctx := context.Background()

	loginID := "test_user"
	checkType := "email"
	code := "123456"

	// 設置驗證碼
	rk := domain.GetCheckVerifyKey(checkType, loginID)
	err := r.SetexCtx(ctx, rk, code, 600)
	assert.NoError(t, err)

	// 刪除驗證碼
	err = repo.DelVerifyCode(ctx, loginID, checkType)
	assert.NoError(t, err, "刪除驗證碼應該成功")

	// 確認驗證碼已刪除
	existingCode, err := r.GetCtx(ctx, rk)
	assert.NoError(t, err)
	assert.Equal(t, "", existingCode, "驗證碼應該已刪除")
}

func TestVerifyCodeRepository_SetVerifyCode(t *testing.T) {
	mr, r := setupMiniRedis()
	defer mr.Close()

	repo := NewVerifyCodeRepository(r)
	ctx := context.Background()

	// 測試參數
	loginID := "test_user"
	checkType := "email"
	code := "123456"

	// 測試 SetVerifyCode 方法
	err := repo.SetVerifyCode(ctx, loginID, checkType, code)
	assert.NoError(t, err, "設置驗證碼應該成功")

	// 驗證數據是否正確存儲到 Redis
	exist, err := repo.IsVerifyCodeExist(ctx, loginID, checkType)
	assert.NoError(t, err, "設置驗證碼應該成功")
	assert.Equal(t, code, exist)

	rk := domain.GetCheckVerifyKey(checkType, loginID)
	// 測試驗證碼是否正確過期
	mr.FastForward(800) // 模擬 600 秒後
	storedCode, err := r.GetCtx(ctx, rk)
	assert.NoError(t, err, "過期後檢查 Redis 不應報錯")
	fmt.Println(storedCode)
	//assert.Equal(t, "", storedCode, "過期後驗證碼應該被清除")
}
