package models

import (
	"time"

	"github.com/veypi/vigo"
)

// SMSCode 短信验证码记录
type SMSCode struct {
	vigo.Model
	Phone     string     `gorm:"index;type:varchar(20);not null" json:"phone"`   // 手机号
	Code      string     `gorm:"type:varchar(10);not null" json:"code"`          // 验证码
	Region    string     `gorm:"index;type:varchar(10);not null" json:"region"`  // 区域
	Purpose   string     `gorm:"index;type:varchar(20);not null" json:"purpose"` // 用途（注册、登录、重置密码等）
	Status    CodeStatus `gorm:"default:0" json:"status"`                        // 状态
	ExpiresAt time.Time  `gorm:"index;not null" json:"expires_at"`               // 过期时间
	UsedAt    *time.Time `gorm:"index" json:"used_at"`                           // 使用时间
	Attempts  int        `gorm:"default:0" json:"attempts"`                      // 验证尝试次数
	SendCount int        `gorm:"default:1" json:"send_count"`                    // 发送次数
	RemoteIP  string     `gorm:"index;type:varchar(50)" json:"remote_ip"`        // 远程IP地址
}

// CodeStatus 验证码状态
type CodeStatus int

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

// SMSLog 短信发送日志
type SMSLog struct {
	vigo.Model
	Phone     string  `gorm:"index;type:varchar(20);not null" json:"phone"`
	Region    string  `gorm:"index;type:varchar(10);not null" json:"region"`
	Provider  string  `gorm:"type:varchar(20);not null" json:"provider"`
	MessageID string  `gorm:"index;type:varchar(100)" json:"message_id"` // 服务商返回的消息ID
	Content   string  `gorm:"type:text" json:"content"`                  // 短信内容
	Status    string  `gorm:"type:varchar(20);not null" json:"status"`   // 发送状态
	Error     string  `gorm:"type:text" json:"error"`                    // 错误信息
	Cost      float64 `json:"cost"`                                      // 费用
}

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

// IsUsed 检查验证码是否已使用
func (s *SMSCode) IsUsed() bool {
	return s.Status == CodeStatusUsed && s.UsedAt != nil
}

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