//
// validate.go
// Copyright (C) 2025 veypi <i@veypi.com>
//
// Distributed under terms of the MIT license.
//

package sms

import (
	"fmt"
	"time"

	"github.com/veypi/vbase/cfg"
	"github.com/veypi/vbase/libs/utils"
	"github.com/veypi/vbase/models"
	"github.com/veypi/vigo"
	"gorm.io/gorm"
)

// VerifyCode 验证验证码
func VerifyCode(Phone, Code, Region, Purpose string) error {
	normalizedPhone := utils.NormalizePhoneNumber(Phone)

	// 1. 查找最新的待验证码
	var smsCode models.SMSCode
	err := cfg.DB().Where("phone = ? AND region = ? AND purpose = ? AND status = ?",
		normalizedPhone, Region, Purpose, models.CodeStatusPending).
		Order("created_at DESC").
		First(&smsCode).Error

	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return vigo.NewError("verification code not found or already used").WithCode(404)
		}
		return vigo.NewError("failed to query sms code").WithError(err)
	}

	// 2. 检查验证码是否过期
	if smsCode.IsExpired() {
		cfg.DB().Model(&smsCode).Updates(map[string]any{
			"status": models.CodeStatusExpired,
		})
		return fmt.Errorf("verification code has expired")
	}

	// 3. 检查是否已达到最大尝试次数
	if !smsCode.CanRetry(cfg.Config.SMS.Global.MaxAttempts) {
		cfg.DB().Model(&smsCode).Updates(map[string]any{
			"status": models.CodeStatusFailed,
		})
		return fmt.Errorf("verification failed too many times")
	}

	// 4. 验证码不匹配
	if smsCode.Code != Code {
		cfg.DB().Model(&smsCode).Updates(map[string]any{
			"attempts": smsCode.Attempts + 1,
		})

		remaining := cfg.Config.SMS.Global.MaxAttempts - smsCode.Attempts - 1
		return fmt.Errorf("verification code incorrect, %d attempts remaining", remaining)
	}

	// 5. 验证成功
	now := time.Now()
	cfg.DB().Model(&smsCode).Updates(map[string]any{
		"status":  models.CodeStatusUsed,
		"used_at": &now,
	})

	return nil
}
