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

package models

import (
	"encoding/json"
	"fmt"
	"strconv"

	"github.com/veypi/vbase/cfg"
	"github.com/veypi/vigo"
)

// Setting 系统配置表（线上配置，存储在数据库）
type Setting struct {
	vigo.Model
	Key       string `gorm:"uniqueIndex;size:100;not null" json:"key"`
	Value     string `gorm:"" json:"value"`
	Type      string `gorm:"size:20;default:'string'" json:"type"` // string/int/bool/json
	Category  string `gorm:"index;size:50" json:"category"`
	Desc      string `gorm:"size:200" json:"desc"`
	UpdatedBy string `gorm:"size:36" json:"updated_by"`
}

// 配置分类常量
const (
	SettingCategoryAuth     = "auth"
	SettingCategoryEmail    = "email"
	SettingCategorySMS      = "sms"
	SettingCategorySecurity = "security"
	SettingCategoryOAuth    = "oauth"
	SettingCategoryApp      = "app"
)

// 配置键常量
const (
	// 应用配置
	SettingAppName = "app.name"
	SettingAppID   = "app.id"

	// JWT 配置
	SettingJWTSecret        = "jwt.secret"
	SettingJWTAccessExpiry  = "jwt.access_expiry"  // 单位：秒
	SettingJWTRefreshExpiry = "jwt.refresh_expiry" // 单位：秒
	SettingJWTIssuer        = "jwt.issuer"

	// 登录注册
	SettingAuthRegRequireEmail = "auth.reg.require_email"
	SettingAuthRegRequirePhone = "auth.reg.require_phone"
	SettingAuthLoginMethods    = "auth.login.methods"         // json: ["password", "email_code", "phone_code"]
	SettingAuthPasswordFields  = "auth.login.password_fields" // json: ["username", "email", "phone"]

	// 安全/验证码
	SettingSecurityBcryptCost       = "security.bcrypt_cost"
	SettingSecurityMaxLoginAttempts = "security.max_login_attempts"
	SettingSecurityCaptchaEnabled   = "security.captcha_enabled"
	SettingCodeExpiry               = "code.expiry" // 分钟
	SettingCodeLength               = "code.length"
	SettingCodeMaxAttempt           = "code.max_attempt"
	SettingCodeSendInterval         = "code.send_interval" // 秒
	SettingCodeMaxDailyCount        = "code.max_daily_count"

	// 邮件配置
	SettingEmailEnabled  = "email.enabled"
	SettingEmailProvider = "email.provider" // smtp/sendgrid
	SettingEmailSMTPHost = "email.smtp.host"
	SettingEmailSMTPPort = "email.smtp.port"
	SettingEmailSMTPUser = "email.smtp.user"
	SettingEmailSMTPPass = "email.smtp.pass"
	SettingEmailFrom     = "email.from"
	SettingEmailFromName = "email.from_name"

	// 短信配置
	SettingSMSEnabled      = "sms.enabled"
	SettingSMSProvider     = "sms.provider" // aliyun/tencent
	SettingSMSAccessKey    = "sms.access_key"
	SettingSMSAccessSecret = "sms.access_secret"
	SettingSMSSignName     = "sms.sign_name"
	SettingSMSTemplateCode = "sms.template_code"
	SettingSMSEndpoint     = "sms.endpoint"
)

// 默认配置值
var defaultSettings = []Setting{
	// 应用
	{Key: SettingAppName, Value: "VBase IAM", Type: "string", Category: SettingCategoryApp, Desc: "应用名称"},
	{Key: SettingAppID, Value: "vbase", Type: "string", Category: SettingCategoryApp, Desc: "应用标识"},

	// JWT
	{Key: SettingJWTSecret, Value: "", Type: "string", Category: SettingCategorySecurity, Desc: "JWT密钥（为空则使用本地key配置）"},
	{Key: SettingJWTAccessExpiry, Value: "3600", Type: "int", Category: SettingCategorySecurity, Desc: "Access Token有效期(秒)"},
	{Key: SettingJWTRefreshExpiry, Value: "2592000", Type: "int", Category: SettingCategorySecurity, Desc: "Refresh Token有效期(秒)"},
	{Key: SettingJWTIssuer, Value: "vbase", Type: "string", Category: SettingCategorySecurity, Desc: "JWT签发者"},

	// 登录注册
	{Key: SettingAuthRegRequireEmail, Value: "false", Type: "bool", Category: SettingCategoryAuth, Desc: "注册是否要求邮箱"},
	{Key: SettingAuthRegRequirePhone, Value: "false", Type: "bool", Category: SettingCategoryAuth, Desc: "注册是否要求手机号"},
	{Key: SettingAuthLoginMethods, Value: `["password"]`, Type: "json", Category: SettingCategoryAuth, Desc: "启用的登录方式"},
	{Key: SettingAuthPasswordFields, Value: `["username"]`, Type: "json", Category: SettingCategoryAuth, Desc: "密码登录支持的身份标识"},

	// 安全
	{Key: SettingSecurityBcryptCost, Value: "12", Type: "int", Category: SettingCategorySecurity, Desc: "bcrypt加密强度"},
	{Key: SettingSecurityMaxLoginAttempts, Value: "5", Type: "int", Category: SettingCategorySecurity, Desc: "最大登录尝试次数"},
	{Key: SettingSecurityCaptchaEnabled, Value: "true", Type: "bool", Category: SettingCategorySecurity, Desc: "是否启用验证码"},

	// 验证码
	{Key: SettingCodeExpiry, Value: "5", Type: "int", Category: SettingCategorySecurity, Desc: "验证码有效期(分钟)"},
	{Key: SettingCodeLength, Value: "6", Type: "int", Category: SettingCategorySecurity, Desc: "验证码长度"},
	{Key: SettingCodeMaxAttempt, Value: "3", Type: "int", Category: SettingCategorySecurity, Desc: "验证码最大尝试次数"},
	{Key: SettingCodeSendInterval, Value: "60", Type: "int", Category: SettingCategorySecurity, Desc: "发送间隔(秒)"},
	{Key: SettingCodeMaxDailyCount, Value: "100", Type: "int", Category: SettingCategorySecurity, Desc: "单日最大发送次数(0禁用,-1不限制)"},

	// 邮件（默认关闭）
	{Key: SettingEmailEnabled, Value: "false", Type: "bool", Category: SettingCategoryEmail, Desc: "是否启用邮件服务"},
	{Key: SettingEmailProvider, Value: "smtp", Type: "string", Category: SettingCategoryEmail, Desc: "邮件服务商"},
	{Key: SettingEmailSMTPHost, Value: "", Type: "string", Category: SettingCategoryEmail, Desc: "SMTP服务器"},
	{Key: SettingEmailSMTPPort, Value: "587", Type: "int", Category: SettingCategoryEmail, Desc: "SMTP端口"},
	{Key: SettingEmailSMTPUser, Value: "", Type: "string", Category: SettingCategoryEmail, Desc: "SMTP用户名"},
	{Key: SettingEmailSMTPPass, Value: "", Type: "string", Category: SettingCategoryEmail, Desc: "SMTP密码"},
	{Key: SettingEmailFrom, Value: "", Type: "string", Category: SettingCategoryEmail, Desc: "发件人邮箱"},
	{Key: SettingEmailFromName, Value: "VBase", Type: "string", Category: SettingCategoryEmail, Desc: "发件人显示名"},

	// 短信（默认关闭）
	{Key: SettingSMSEnabled, Value: "false", Type: "bool", Category: SettingCategorySMS, Desc: "是否启用短信服务"},
	{Key: SettingSMSProvider, Value: "aliyun", Type: "string", Category: SettingCategorySMS, Desc: "短信服务商"},
	{Key: SettingSMSAccessKey, Value: "", Type: "string", Category: SettingCategorySMS, Desc: "AccessKey ID"},
	{Key: SettingSMSAccessSecret, Value: "", Type: "string", Category: SettingCategorySMS, Desc: "AccessKey Secret"},
	{Key: SettingSMSSignName, Value: "", Type: "string", Category: SettingCategorySMS, Desc: "短信签名"},
	{Key: SettingSMSTemplateCode, Value: "", Type: "string", Category: SettingCategorySMS, Desc: "验证码模板CODE"},
	{Key: SettingSMSEndpoint, Value: "", Type: "string", Category: SettingCategorySMS, Desc: "自定义接入点"},
}

// InitSettings 初始化默认配置
func InitSettings() error {
	db := cfg.DB()
	for _, s := range defaultSettings {
		var count int64
		if err := db.Model(&Setting{}).Where("`key` = ?", s.Key).Count(&count).Error; err != nil {
			return err
		}
		if count == 0 {
			if err := db.Create(&s).Error; err != nil {
				return fmt.Errorf("init setting %s failed: %w", s.Key, err)
			}
		}
	}
	return nil
}

// GetSetting 获取配置值
func GetSetting(key string) (string, error) {
	var s Setting
	if err := cfg.DB().Where("`key` = ?", key).First(&s).Error; err != nil {
		return "", err
	}
	return s.Value, nil
}

// GetSettingBool 获取布尔配置
func GetSettingBool(key string) (bool, error) {
	val, err := GetSetting(key)
	if err != nil {
		return false, err
	}
	return strconv.ParseBool(val)
}

// GetSettingInt 获取整数配置
func GetSettingInt(key string) (int, error) {
	val, err := GetSetting(key)
	if err != nil {
		return 0, err
	}
	return strconv.Atoi(val)
}

// GetSettingJSON 获取 JSON 配置
func GetSettingJSON(key string, v interface{}) error {
	val, err := GetSetting(key)
	if err != nil {
		return err
	}
	return json.Unmarshal([]byte(val), v)
}

// SetSetting 设置配置值
func SetSetting(key, value, updatedBy string) error {
	var s Setting
	db := cfg.DB()
	if err := db.Where("`key` = ?", key).First(&s).Error; err != nil {
		return err
	}
	s.Value = value
	s.UpdatedBy = updatedBy
	return db.Save(&s).Error
}
