//
// Copyright (C) 2024 veypi <i@veypi.com>
// 2025-03-04 16:08:06
// Distributed under terms of the MIT license.
//

package models

import (
	"time"

	"github.com/veypi/vigo"
)

// VerificationCode 统一验证码表（邮箱 + 短信）
type VerificationCode struct {
	vigo.Model
	Target    string     `gorm:"index;size:100;not null" json:"target"`   // 邮箱或手机号
	Type      string     `gorm:"index;size:20;not null" json:"type"`      // "email" | "sms"
	Code      string     `gorm:"size:10;not null" json:"-"`                // 验证码（不返回）
	Purpose   string     `gorm:"index;size:20;not null" json:"purpose"`   // register/login/reset_password/bind
	Status    CodeStatus `gorm:"default:0" json:"status"`
	ExpiresAt time.Time  `gorm:"index;not null" json:"expires_at"`
	UsedAt    *time.Time `json:"used_at"`
	Attempts  int        `gorm:"default:0" json:"attempts"`
	SendCount int        `gorm:"default:1" json:"send_count"`
	RemoteIP  string     `gorm:"size:50" json:"remote_ip"`
}

// CodeStatus 验证码状态
type CodeStatus int

const (
	CodeStatusPending CodeStatus = iota // 待验证
	CodeStatusUsed                      // 已使用
	CodeStatusExpired                   // 已过期
	CodeStatusFailed                    // 验证失败（超过最大尝试次数）
)

// IsExpired 检查验证码是否过期
func (c *VerificationCode) IsExpired() bool {
	return time.Now().After(c.ExpiresAt)
}

// CanRetry 检查是否可以重试验证
func (c *VerificationCode) CanRetry(maxAttempts int) bool {
	return c.Status == CodeStatusPending && c.Attempts < maxAttempts && !c.IsExpired()
}

// IsUsed 检查是否已使用
func (c *VerificationCode) IsUsed() bool {
	return c.Status == CodeStatusUsed && c.UsedAt != nil
}

// 验证码用途常量
const (
	CodePurposeRegister      = "register"
	CodePurposeLogin         = "login"
	CodePurposeResetPassword = "reset_password"
	CodePurposeBind          = "bind"
)
