package app

import (
	"fmt"
	"log"
	"math/rand"
	"strings"
	"time"

	"verification-platform-backend/internal/database"
	"verification-platform-backend/internal/model"
	"verification-platform-backend/internal/service"
	"verification-platform-backend/pkg/jwt"
	"verification-platform-backend/pkg/response"

	"github.com/gin-gonic/gin"
	"golang.org/x/crypto/bcrypt"
)

func getDeviceType(c *gin.Context, clientDeviceType string) string {
	validTypes := map[string]bool{
		"android": true,
		"ios":     true,
		"windows": true,
		"mac":     true,
		"linux":   true,
		"web":     true,
	}

	if clientDeviceType != "" && validTypes[clientDeviceType] {
		return clientDeviceType
	}

	userAgent := c.GetHeader("User-Agent")
	return parseDeviceTypeFromUserAgent(userAgent)
}

func parseDeviceTypeFromUserAgent(userAgent string) string {
	if userAgent == "" {
		return "unknown"
	}

	ua := strings.ToLower(userAgent)

	switch {
	case strings.Contains(ua, "android"):
		return "android"
	case strings.Contains(ua, "iphone") || strings.Contains(ua, "ipad") || strings.Contains(ua, "ipod"):
		return "ios"
	case strings.Contains(ua, "windows"):
		return "windows"
	case strings.Contains(ua, "macintosh") || strings.Contains(ua, "mac os x"):
		return "mac"
	case strings.Contains(ua, "linux"):
		return "linux"
	case strings.Contains(ua, "mozilla") || strings.Contains(ua, "webkit") || strings.Contains(ua, "chrome") || strings.Contains(ua, "safari"):
		return "web"
	default:
		return "unknown"
	}
}

func SetupAuthUserRoutes(r *gin.RouterGroup) {
	r.POST("/register", handleAppRegister)
	r.POST("/login", handleAppLogin)
	r.POST("/send-email-code", handleAppSendEmailCode)
	r.POST("/reset-password", handleAppResetPassword)
}

func handleAppSendEmailCode(c *gin.Context) {
	appKey := c.Param("appKey")

	var app model.Application
	if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil {
		response.Error(c, 404, "应用不存在")
		return
	}

	if service.GetApplicationDisabledStatus(app.ID) {
		response.Error(c, 403, "该应用已被禁用")
		return
	}

	var req struct {
		Email   string `json:"email" binding:"required,email"`
		Purpose string `json:"purpose"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "请输入有效的邮箱地址")
		return
	}

	if req.Purpose == "" {
		req.Purpose = "register"
	}

	if req.Purpose == "register" {
		if !app.EnableRegisterVerify {
			response.Error(c, 400, "该应用未启用注册验证")
			return
		}
	} else if req.Purpose == "reset_password" {
		if !app.EnablePasswordReset {
			response.Error(c, 400, "该应用未启用密码重置功能")
			return
		}
	}

	var smtpConfig model.AppSMTPConfig
	if err := database.DB.Where("application_id = ?", app.ID).First(&smtpConfig).Error; err != nil {
		response.Error(c, 400, "应用未配置SMTP")
		return
	}

	var template model.EmailTemplate
	database.DB.Where("application_id = ? AND type = ? AND status = ?", app.ID, req.Purpose, "active").
		Order("is_default DESC").First(&template)

	code := generateVerifyCode()
	expireAt := time.Now().Add(15 * time.Minute)

	verifyCode := model.EmailVerifyCode{
		ApplicationID: app.ID,
		Email:         req.Email,
		Code:          code,
		Purpose:       req.Purpose,
		ExpiresAt:     expireAt,
	}
	database.DB.Create(&verifyCode)

	emailService := service.NewEmailService()
	config := service.EmailConfig{
		Host:      smtpConfig.Host,
		Port:      smtpConfig.Port,
		User:      smtpConfig.User,
		Password:  smtpConfig.Password,
		FromName:  smtpConfig.FromName,
		FromEmail: smtpConfig.FromEmail,
		UseSSL:    smtpConfig.UseSSL,
	}

	subject := fmt.Sprintf("验证码 - %s", app.Name)
	content := fmt.Sprintf(`
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"></head>
<body style="font-family: Arial, sans-serif; padding: 20px; background-color: #f5f5f5;">
	<div style="max-width: 600px; margin: 0 auto; background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
		<h2 style="color: #333; margin-bottom: 20px;">邮箱验证</h2>
		<p style="color: #666; line-height: 1.6;">您的验证码是：<strong style="font-size: 24px; color: #1890ff;">%s</strong></p>
		<p style="color: #999; font-size: 12px;">验证码有效期为15分钟，请尽快使用。</p>
		<hr style="border: none; border-top: 1px solid #eee; margin: 20px 0;">
		<p style="color: #999; font-size: 12px;">此邮件由 %s 系统自动发送，请勿回复。</p>
	</div>
</body>
</html>
`, code, app.Name)

	if template.ID > 0 {
		subject = template.Subject
		content = template.Content
	}

	if err := emailService.SendEmail(config, req.Email, subject, content); err != nil {
		response.Error(c, 500, fmt.Sprintf("发送失败: %v", err))
		return
	}

	response.Success(c, gin.H{
		"message": "验证码已发送",
	})
}

func generateVerifyCode() string {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	return fmt.Sprintf("%06d", r.Intn(1000000))
}

func handleAppRegister(c *gin.Context) {
	appKey := c.Param("appKey")
	log.Printf("[DEBUG] Starting registration for appKey: %s", appKey)

	app, exists := c.Get("app")
	if !exists {
		var appModel model.Application
		if err := database.DB.Where("app_key = ?", appKey).First(&appModel).Error; err != nil {
			log.Printf("[DEBUG] Application not found for appKey: %s, error: %v", appKey, err)
			response.Error(c, 404, "应用不存在")
			return
		}
		app = &appModel
	}
	appModel := app.(*model.Application)
	log.Printf("[DEBUG] Found application: ID=%d, Status=%s", appModel.ID, appModel.Status)

	if service.GetApplicationDisabledStatus(appModel.ID) {
		response.Error(c, 403, "该应用已被禁用")
		return
	}

	var req struct {
		Username       string `json:"username"`
		Email          string `json:"email"`
		EmailCode      string `json:"email_code"`
		Phone          string `json:"phone"`
		SmsCode        string `json:"sms_code"`
		Password       string `json:"password"`
		DeviceID       string `json:"device_id"`
		DeviceName     string `json:"device_name"`
		DeviceType     string `json:"device_type"`
		InstanceID     string `json:"instance_id"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		log.Printf("[DEBUG] Invalid request parameters: %v", err)
		response.Error(c, 400, "参数错误")
		return
	}
	log.Printf("[DEBUG] Registration request for username: %s", req.Username)

	if blocked, reason := checkRiskControl(c, appModel.ID, req.DeviceID, req.Username); blocked {
		log.Printf("[DEBUG] Registration blocked by risk control: %s", reason)
		service.LogVerification(c, &appModel.ID, nil, "register_blocked", "注册被拦截: "+reason, req.DeviceID, fmt.Errorf(reason))
		response.Error(c, 403, reason)
		return
	}

	if !appModel.AllowRegister {
		log.Printf("[DEBUG] Registration disabled for app: %s", appKey)
		response.Error(c, 403, "注册功能已关闭")
		return
	}

	if appModel.EnableRegisterVerify {
		if appModel.VerifyMethod == "email" {
			if req.Email == "" {
				response.Error(c, 400, "请输入邮箱地址")
				return
			}
			if req.EmailCode == "" {
				response.Error(c, 400, "请输入邮箱验证码")
				return
			}

			var verifyCode model.EmailVerifyCode
			if err := database.DB.Where(
				"application_id = ? AND email = ? AND code = ? AND purpose = ? AND used = ?",
				appModel.ID, req.Email, req.EmailCode, "register", false,
			).First(&verifyCode).Error; err != nil {
				response.Error(c, 400, "验证码错误或已过期")
				return
			}

			if verifyCode.ExpiresAt.Before(time.Now()) {
				response.Error(c, 400, "验证码已过期")
				return
			}

			verifyCode.Used = true
			database.DB.Save(&verifyCode)
		} else if appModel.VerifyMethod == "sms" {
			if req.Phone == "" {
				response.Error(c, 400, "请输入手机号")
				return
			}
			if req.SmsCode == "" {
				response.Error(c, 400, "请输入短信验证码")
				return
			}

			var verifyCode model.SmsVerifyCode
			if err := database.DB.Where(
				"application_id = ? AND phone = ? AND code = ? AND purpose = ? AND used = ?",
				appModel.ID, req.Phone, req.SmsCode, "register", false,
			).First(&verifyCode).Error; err != nil {
				response.Error(c, 400, "验证码错误或已过期")
				return
			}

			if verifyCode.ExpiresAt.Before(time.Now()) {
				response.Error(c, 400, "验证码已过期")
				return
			}

			verifyCode.Used = true
			database.DB.Save(&verifyCode)
		}
	}

	var user model.AppUser
	if err := database.DB.Where("username = ? AND application_id = ?", req.Username, appModel.ID).First(&user).Error; err == nil {
		log.Printf("[DEBUG] User already exists: %s", req.Username)
		service.LogVerification(c, &appModel.ID, nil, "register_failed", "注册失败: 用户已存在 - "+req.Username, req.DeviceID, fmt.Errorf("用户已存在"))
		response.Error(c, 400, "用户已存在")
		return
	}

	user = model.AppUser{
		Username:      req.Username,
		Email:         req.Email,
		Password:      req.Password,
		DeviceID:      req.DeviceID,
		Avatar:        "",
		Status:        "active",
		ApplicationID: appModel.ID,
		IsTrialUser:   appModel.EnableTrial,
	}

	if appModel.EnableTrial {
		now := time.Now()
		user.TrialStartAt = &now
		if appModel.TrialBalance > 0 {
			user.Balance = appModel.TrialBalance
		}
	}

	if err := database.DB.Create(&user).Error; err != nil {
		log.Printf("[DEBUG] Failed to create user: %v", err)
		response.Error(c, 500, "注册失败")
		return
	}
	log.Printf("[DEBUG] Successfully created user with ID: %d", user.ID)

	if req.DeviceID != "" {
		now := time.Now()
		deviceType := getDeviceType(c, req.DeviceType)

		deviceName := req.DeviceName
		if deviceName == "" {
			deviceName = req.DeviceID
		}

		var device model.UserDevice
		if err := database.DB.Where("user_id = ? AND application_id = ? AND device_id = ?", user.ID, appModel.ID, req.DeviceID).First(&device).Error; err != nil {
			device = model.UserDevice{
				UserID:        user.ID,
				ApplicationID: appModel.ID,
				DeviceID:      req.DeviceID,
				DeviceName:    deviceName,
				DeviceType:    deviceType,
				Status:        "active",
			}
			if err := database.DB.Create(&device).Error; err != nil {
				log.Printf("[DEBUG] Failed to create device: %v", err)
			} else {
				log.Printf("[DEBUG] Successfully created device with ID: %d, type: %s", device.ID, deviceType)
			}
		}

		instanceID := req.InstanceID
		if instanceID == "" {
			instanceID = req.DeviceID
		}

		if device.ID > 0 {
			var session model.DeviceSession
			sessionErr := database.DB.Where("device_id = ? AND instance_id = ?", device.ID, instanceID).First(&session).Error

			if sessionErr != nil {
				session = model.DeviceSession{
					DeviceID:      device.ID,
					UserID:        user.ID,
					ApplicationID: appModel.ID,
					InstanceID:    instanceID,
					LastHeartbeat: &now,
				}
				if err := database.DB.Create(&session).Error; err != nil {
					log.Printf("[DEBUG] Failed to create session: %v", err)
				}
			} else {
				session.LastHeartbeat = &now
				if err := database.DB.Save(&session).Error; err != nil {
					log.Printf("[DEBUG] Failed to update session: %v", err)
				}
			}
		}
	}

	service.LogVerification(c, &appModel.ID, &user.ID, "register", "用户注册: "+req.Username, req.DeviceID, nil)

	response.SuccessWithMessage(c, "注册成功", gin.H{
		"user_id": user.ID,
	})
}

func handleAppLogin(c *gin.Context) {
	appKey := c.Param("appKey")
	log.Printf("[DEBUG] Login attempt for appKey: %s", appKey)

	app, exists := c.Get("app")
	if !exists {
		var appModel model.Application
		if err := database.DB.Where("app_key = ?", appKey).First(&appModel).Error; err != nil {
			log.Printf("[DEBUG] Application not found for appKey: %s, error: %v", appKey, err)
			response.Error(c, 404, "应用不存在")
			return
		}
		app = &appModel
	}
	appModel := app.(*model.Application)
	log.Printf("[DEBUG] Found application: ID=%d, Status=%s", appModel.ID, appModel.Status)

	var req struct {
		Username   string `json:"username"`
		Password   string `json:"password"`
		DeviceID   string `json:"device_id"`
		DeviceName string `json:"device_name"`
		DeviceType string `json:"device_type"`
		InstanceID string `json:"instance_id"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		log.Printf("[DEBUG] Invalid request parameters: %v", err)
		response.Error(c, 400, "参数错误")
		return
	}
	log.Printf("[DEBUG] Login request for username: %s", req.Username)

	if req.DeviceID == "" {
		response.Error(c, 400, "设备ID不能为空")
		return
	}

	var user model.AppUser
	if err := database.DB.Where("username = ? AND application_id = ?", req.Username, appModel.ID).First(&user).Error; err != nil {
		log.Printf("[DEBUG] User not found: %v", err)
		service.LogVerification(c, &appModel.ID, nil, "login_failed", "登录失败: 用户不存在 - "+req.Username, req.DeviceID, fmt.Errorf("用户不存在"))
		response.Error(c, 404, "用户不存在")
		return
	}

	if user.Password != req.Password {
		log.Printf("[DEBUG] Password mismatch for user: %s", req.Username)
		service.LogVerification(c, &appModel.ID, &user.ID, "login_failed", "登录失败: 密码错误 - "+req.Username, req.DeviceID, fmt.Errorf("密码错误"))
		response.Error(c, 400, "密码错误")
		return
	}

	if blocked, reason := checkRiskControl(c, appModel.ID, req.DeviceID, req.Username); blocked {
		log.Printf("[DEBUG] Login blocked by risk control: %s", reason)
		service.LogVerification(c, &appModel.ID, &user.ID, "login_blocked", "登录被拦截: "+reason, req.DeviceID, fmt.Errorf(reason))
		response.Error(c, 403, reason)
		return
	}

	if appModel.LoginPolicy == "strict" {
		log.Printf("[DEBUG] LoginPolicy is strict, checking free period and trial")
		isInFreePeriod := false
		if appModel.EnableFreePeriod {
			isInFreePeriod = checkFreePeriod(appModel)
		}
		log.Printf("[DEBUG] isInFreePeriod=%v", isInFreePeriod)

		if !isInFreePeriod {
			log.Printf("[DEBUG] Not in free period, checking trial")
			isTrialValid := false
			if user.IsTrialUser && user.TrialEndAt != nil && user.TrialEndAt.After(time.Now()) {
				isTrialValid = true
			}
			log.Printf("[DEBUG] isTrialValid=%v, IsTrialUser=%v, TrialEndAt=%v, Balance=%f", isTrialValid, user.IsTrialUser, user.TrialEndAt, user.Balance)

			if !isTrialValid {
				if appModel.BillingType != "free" {
					if user.Balance == -1 {
						log.Printf("[DEBUG] User %d is permanent member, allowing login", user.ID)
					} else if appModel.BillingType == "subscription" {
						if user.ExpiryAt == nil || user.ExpiryAt.Before(time.Now()) {
							log.Printf("[DEBUG] User %d subscription expired, ExpiryAt=%v", user.ID, user.ExpiryAt)
							service.LogVerification(c, &appModel.ID, &user.ID, "login_failed", "登录失败: 订阅已过期 - "+req.Username, req.DeviceID, fmt.Errorf("订阅已过期，请充值后继续使用"))
							response.Error(c, 403, "订阅已过期，请充值后继续使用")
							return
						}
					} else {
						if user.Balance <= 0 {
							log.Printf("[DEBUG] User %d has no balance remaining", user.ID)
							service.LogVerification(c, &appModel.ID, &user.ID, "login_failed", "登录失败: 余额不足 - "+req.Username, req.DeviceID, fmt.Errorf("余额不足，请充值后继续使用"))
							response.Error(c, 403, "余额不足，请充值后继续使用")
							return
						}
					}
				}
			}
		} else {
			log.Printf("[DEBUG] User is in free period, allowing login")
		}
	}

	if req.DeviceID != "" {
		heartbeatTimeout := time.Duration(appModel.HeartbeatTimeout) * time.Second
		timeoutThreshold := time.Now().Add(-heartbeatTimeout)
		database.DB.Where("user_id = ? AND application_id = ? AND last_heartbeat < ?", user.ID, appModel.ID, timeoutThreshold).Delete(&model.DeviceSession{})

		now := time.Now()
		deviceType := getDeviceType(c, req.DeviceType)
		
		deviceName := req.DeviceName
		if deviceName == "" {
			deviceName = req.DeviceID
		}

		clientIP := c.ClientIP()

		if appModel.BindType == "ip" || appModel.BindType == "mixed" {
			var userIP model.UserIP
			ipErr := database.DB.Where("user_id = ? AND application_id = ? AND ip_address = ?", user.ID, appModel.ID, clientIP).First(&userIP).Error

			if ipErr != nil {
				var ipCount int64
				database.DB.Model(&model.UserIP{}).
					Where("user_id = ? AND application_id = ?", user.ID, appModel.ID).
					Count(&ipCount)

				if appModel.MaxDevices > 0 && ipCount >= int64(appModel.MaxDevices) {
					log.Printf("[DEBUG] IP limit exceeded for user %d: %d/%d", user.ID, ipCount, appModel.MaxDevices)
					
					var userIPs []model.UserIP
					database.DB.Where("user_id = ? AND application_id = ?", user.ID, appModel.ID).Order("created_at DESC").Find(&userIPs)
					
					ipList := make([]gin.H, 0)
					for _, ip := range userIPs {
						ipList = append(ipList, gin.H{
							"id":         ip.ID,
							"ip_address": ip.IPAddress,
							"status":     ip.Status,
							"created_at": ip.CreatedAt,
						})
					}
					
					response.ErrorWithData(c, 403, "IP绑定数量已达上限，请解绑后再试", gin.H{
						"error_code":  "IP_LIMIT_EXCEEDED",
						"max_ips":     appModel.MaxDevices,
						"ip_count":    ipCount,
						"ips":         ipList,
					})
					service.LogVerification(c, &appModel.ID, &user.ID, "login_failed", "登录失败: IP绑定数量已达上限 - "+req.Username, req.DeviceID, fmt.Errorf("IP绑定数量已达上限"))
					return
				}

				userIP = model.UserIP{
					UserID:        user.ID,
					ApplicationID: appModel.ID,
					IPAddress:     clientIP,
					Status:        "active",
				}
				if err := database.DB.Create(&userIP).Error; err != nil {
					log.Printf("[DEBUG] Failed to create user IP: %v", err)
				} else {
					log.Printf("[DEBUG] Successfully created user IP with ID: %d, IP: %s", userIP.ID, clientIP)
				}
			}
		}
		
		var device model.UserDevice
		deviceErr := database.DB.Where("user_id = ? AND application_id = ? AND device_id = ?", user.ID, appModel.ID, req.DeviceID).First(&device).Error

		if deviceErr != nil {
			if (appModel.BindType == "device" || appModel.BindType == "mixed") && appModel.MaxDevices > 0 {
				var deviceCount int64
				database.DB.Model(&model.UserDevice{}).
					Where("user_id = ? AND application_id = ?", user.ID, appModel.ID).
					Count(&deviceCount)

				if deviceCount >= int64(appModel.MaxDevices) {
					log.Printf("[DEBUG] Device limit exceeded for user %d: %d/%d", user.ID, deviceCount, appModel.MaxDevices)
					
					var devices []model.UserDevice
					database.DB.Where("user_id = ? AND application_id = ?", user.ID, appModel.ID).Order("created_at DESC").Find(&devices)
					
					deviceList := make([]gin.H, 0)
					for _, d := range devices {
						var onlineSessions []model.DeviceSession
						database.DB.Where("device_id = ? AND last_heartbeat > ?", d.ID, timeoutThreshold).Find(&onlineSessions)
						
						deviceList = append(deviceList, gin.H{
							"id":             d.ID,
							"device_id":      d.DeviceID,
							"device_name":    d.DeviceName,
							"device_type":    d.DeviceType,
							"online_count":   len(onlineSessions),
							"created_at":     d.CreatedAt,
						})
					}
					
					response.ErrorWithData(c, 403, "设备绑定数量已达上限，请解绑后再试", gin.H{
						"error_code":   "DEVICE_LIMIT_EXCEEDED",
						"max_devices":  appModel.MaxDevices,
						"device_count": deviceCount,
						"devices":      deviceList,
					})
					service.LogVerification(c, &appModel.ID, &user.ID, "login_failed", "登录失败: 设备绑定数量已达上限 - "+req.Username, req.DeviceID, fmt.Errorf("设备绑定数量已达上限"))
					return
				}
			}
			
			device = model.UserDevice{
				UserID:        user.ID,
				ApplicationID: appModel.ID,
				DeviceID:      req.DeviceID,
				DeviceName:    deviceName,
				DeviceType:    deviceType,
				Status:        "active",
			}
			if err := database.DB.Create(&device).Error; err != nil {
				log.Printf("[DEBUG] Failed to create device: %v", err)
			} else {
				log.Printf("[DEBUG] Successfully created device with ID: %d, type: %s", device.ID, deviceType)
			}
		}

		instanceID := req.InstanceID
		if instanceID == "" {
			instanceID = req.DeviceID
		}

		if device.ID > 0 {
			if appModel.MultiOpenMode != "unlimited" && appModel.MaxInstances > 0 {
				var sessionCount int64
				database.DB.Model(&model.DeviceSession{}).
					Where("device_id = ? AND instance_id != ? AND last_heartbeat > ?", device.ID, instanceID, timeoutThreshold).
					Count(&sessionCount)

				if sessionCount >= int64(appModel.MaxInstances) {
					log.Printf("[DEBUG] Multi-instance limit exceeded for user %d device %s: %d/%d", user.ID, req.DeviceID, sessionCount, appModel.MaxInstances)
					
					var sessions []model.DeviceSession
					database.DB.Where("device_id = ? AND instance_id != ?", device.ID, instanceID).Order("last_heartbeat DESC").Find(&sessions)
					
					sessionList := make([]gin.H, 0)
					for _, s := range sessions {
						isOnline := s.LastHeartbeat != nil && s.LastHeartbeat.After(timeoutThreshold)
						sessionList = append(sessionList, gin.H{
							"id":             s.ID,
							"instance_id":    s.InstanceID,
							"is_online":      isOnline,
							"last_heartbeat": s.LastHeartbeat,
							"created_at":     s.CreatedAt,
						})
					}
					
					response.ErrorWithData(c, 403, "多开数量已达上限", gin.H{
						"error_code":     "MULTI_INSTANCE_LIMIT_EXCEEDED",
						"max_instances":  appModel.MaxInstances,
						"instance_count": sessionCount,
						"instances":      sessionList,
					})
					service.LogVerification(c, &appModel.ID, &user.ID, "login_failed", "登录失败: 多开数量已达上限 - "+req.Username, req.DeviceID, fmt.Errorf("多开数量已达上限"))
					return
				}
			}

			var session model.DeviceSession
			if err := database.DB.Where("device_id = ? AND instance_id = ?", device.ID, instanceID).First(&session).Error; err != nil {
				session = model.DeviceSession{
					DeviceID:      device.ID,
					UserID:        user.ID,
					ApplicationID: appModel.ID,
					InstanceID:    instanceID,
					LastHeartbeat: &now,
				}
				if err := database.DB.Create(&session).Error; err != nil {
					log.Printf("[DEBUG] Failed to create session: %v", err)
				} else {
					log.Printf("[DEBUG] Successfully created session with ID: %d, instance: %s", session.ID, instanceID)
				}
			} else {
				session.LastHeartbeat = &now
				if err := database.DB.Save(&session).Error; err != nil {
					log.Printf("[DEBUG] Failed to update session: %v", err)
				} else {
					log.Printf("[DEBUG] Successfully updated session %d last_heartbeat", session.ID)
				}
			}
		}
	}

	token, err := jwt.GenerateToken(user.ID, user.Username, "app_user")
	if err != nil {
		log.Printf("[DEBUG] Failed to generate token: %v", err)
	}

	now := time.Now()
	database.DB.Model(&user).Updates(map[string]interface{}{
		"last_login_at":     now,
		"last_heartbeat_at": now,
	})

	service.LogVerification(c, &appModel.ID, &user.ID, "login", "用户登录: "+req.Username, req.DeviceID, nil)

	response.SuccessWithMessage(c, "登录成功", gin.H{
		"user_id": user.ID,
		"token":   token,
	})
}

func checkFreePeriod(app *model.Application) bool {
	now := time.Now()
	log.Printf("[DEBUG] checkFreePeriod: EnableFreePeriod=%v, FreePeriodType=%s, FreePeriodStart=%s, FreePeriodEnd=%s, FreePeriodWeekdays=%s, FreePeriodStartTime=%s, FreePeriodEndTime=%s",
		app.EnableFreePeriod, app.FreePeriodType, app.FreePeriodStart, app.FreePeriodEnd, app.FreePeriodWeekdays, app.FreePeriodStartTime, app.FreePeriodEndTime)

	localLocation := time.Local

	if app.FreePeriodType == "range" {
		if app.FreePeriodStart == "" || app.FreePeriodEnd == "" {
			log.Printf("[DEBUG] checkFreePeriod: range type but missing start or end")
			return false
		}
		var startDate, endDate time.Time
		var err error

		if len(app.FreePeriodStart) > 10 {
			startDate, err = time.ParseInLocation("2006-01-02T15:04", app.FreePeriodStart, localLocation)
		} else {
			startDate, err = time.ParseInLocation("2006-01-02", app.FreePeriodStart, localLocation)
		}
		if err != nil {
			log.Printf("[DEBUG] checkFreePeriod: failed to parse start date: %v", err)
			return false
		}

		if len(app.FreePeriodEnd) > 10 {
			endDate, err = time.ParseInLocation("2006-01-02T15:04", app.FreePeriodEnd, localLocation)
		} else {
			endDate, err = time.ParseInLocation("2006-01-02", app.FreePeriodEnd, localLocation)
			if err == nil {
				endDate = endDate.Add(24 * time.Hour)
			}
		}
		if err != nil {
			log.Printf("[DEBUG] checkFreePeriod: failed to parse end date: %v", err)
			return false
		}
		result := now.After(startDate) && now.Before(endDate)
		log.Printf("[DEBUG] checkFreePeriod: range check result=%v, now=%v, start=%v, end=%v", result, now, startDate, endDate)
		return result
	} else if app.FreePeriodType == "weekdays" {
		if app.FreePeriodWeekdays == "" {
			log.Printf("[DEBUG] checkFreePeriod: weekdays type but missing weekdays")
			return false
		}
		weekday := int(now.Weekday())
		if weekday == 0 {
			weekday = 7
		}
		weekdayStr := string(rune('0' + weekday))
		if !contains(app.FreePeriodWeekdays, weekdayStr) {
			log.Printf("[DEBUG] checkFreePeriod: weekday %s not in %s", weekdayStr, app.FreePeriodWeekdays)
			return false
		}
		if app.FreePeriodStartTime != "" && app.FreePeriodEndTime != "" {
			currentTime := now.Format("15:04")
			result := currentTime >= app.FreePeriodStartTime && currentTime <= app.FreePeriodEndTime
			log.Printf("[DEBUG] checkFreePeriod: weekday time check result=%v, currentTime=%s, startTime=%s, endTime=%s", result, currentTime, app.FreePeriodStartTime, app.FreePeriodEndTime)
			return result
		}
		log.Printf("[DEBUG] checkFreePeriod: weekday check passed")
		return true
	}

	log.Printf("[DEBUG] checkFreePeriod: unknown type %s", app.FreePeriodType)
	return false
}

func checkRiskControl(c *gin.Context, appID uint, deviceID string, username string) (bool, string) {
	clientIP := c.ClientIP()

	var globalRules []model.RiskControlRule
	database.DB.Where("application_id IS NULL AND status = ?", "active").Find(&globalRules)

	var appRules []model.RiskControlRule
	database.DB.Where("application_id = ? AND status = ?", appID, "active").Find(&appRules)

	now := time.Now()

	for _, rule := range globalRules {
		if rule.ExpiresAt != nil && rule.ExpiresAt.Before(now) {
			continue
		}

		switch rule.Type {
		case "device":
			if deviceID != "" && rule.Value == deviceID {
				return true, "设备已被全局封禁: " + rule.Reason
			}
		case "ip":
			if rule.Value == clientIP {
				return true, "IP已被全局封禁: " + rule.Reason
			}
		case "region":
		}
	}

	for _, rule := range appRules {
		if rule.ExpiresAt != nil && rule.ExpiresAt.Before(now) {
			continue
		}

		switch rule.Type {
		case "device":
			if deviceID != "" && rule.Value == deviceID {
				return true, "设备已被封禁: " + rule.Reason
			}
		case "ip":
			if rule.Value == clientIP {
				return true, "IP已被封禁: " + rule.Reason
			}
		case "user":
			if username != "" && rule.Value == username {
				return true, "账号已被封禁: " + rule.Reason
			}
		case "region":
		}
	}

	return false, ""
}

func contains(s string, substr string) bool {
	for i := 0; i < len(s); i++ {
		if s[i:i+1] == substr {
			return true
		}
	}
	return false
}

func containsString(slice []string, str string) bool {
	for _, v := range slice {
		if v == str {
			return true
		}
	}
	return false
}

func checkAppEmailPermission(userID uint, permission *model.PackagePermission) bool {
	var userPackage model.UserPackage
	if err := database.DB.Where("user_id = ? AND status = ?", userID, "active").
		Preload("Package").First(&userPackage).Error; err != nil {
		return false
	}

	if userPackage.ExpiredAt != nil && userPackage.ExpiredAt.Before(time.Now()) {
		return false
	}

	if err := database.DB.Where("package_id = ?", userPackage.PackageID).First(permission).Error; err != nil {
		return false
	}

	return true
}

func handleAppResetPassword(c *gin.Context) {
	appKey := c.Param("appKey")

	var app model.Application
	if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil {
		response.Error(c, 404, "应用不存在")
		return
	}

	if service.GetApplicationDisabledStatus(app.ID) {
		response.Error(c, 403, "该应用已被禁用")
		return
	}

	if !app.EnablePasswordReset {
		response.Error(c, 400, "该应用未启用密码重置功能")
		return
	}

	var req struct {
		Email     string `json:"email" binding:"required,email"`
		Code      string `json:"code" binding:"required"`
		Password  string `json:"password" binding:"required,min=6"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

	var verifyCode model.EmailVerifyCode
	if err := database.DB.Where(
		"application_id = ? AND email = ? AND code = ? AND purpose = ? AND used = ?",
		app.ID, req.Email, req.Code, "reset_password", false,
	).First(&verifyCode).Error; err != nil {
		response.Error(c, 400, "验证码无效或已过期")
		return
	}

	if verifyCode.ExpiresAt.Before(time.Now()) {
		response.Error(c, 400, "验证码已过期")
		return
	}

	var user model.AppUser
	if err := database.DB.Where("email = ? AND application_id = ?", req.Email, app.ID).First(&user).Error; err != nil {
		response.Error(c, 404, "用户不存在")
		return
	}

	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
	if err != nil {
		response.Error(c, 500, "密码加密失败")
		return
	}

	user.Password = string(hashedPassword)
	if err := database.DB.Save(&user).Error; err != nil {
		response.Error(c, 500, "密码重置失败")
		return
	}

	verifyCode.Used = true
	database.DB.Save(&verifyCode)

	response.Success(c, gin.H{
		"message": "密码重置成功",
	})
}
