package app

import (
	"fmt"
	"time"
	"verification-platform-backend/internal/database"
	"verification-platform-backend/internal/model"
	"verification-platform-backend/internal/service"
	"verification-platform-backend/pkg/response"

	"github.com/gin-gonic/gin"
)

func SetupDeviceRoutes(r *gin.RouterGroup) {
	r.GET("/devices", handleAppGetDevices)
	r.POST("/unbind-device", handleAppUnbindDevice)
	r.GET("/device-count", handleAppGetDeviceCount)
	r.GET("/instances", handleAppGetInstances)
	r.POST("/instances/:instance_id/offline", handleAppForceOfflineInstance)
}

func SetupDevicePublicRoutes(r *gin.RouterGroup) {
	r.POST("/unbind-device-with-auth", handleAppUnbindDeviceWithAuth)
	r.POST("/change-password", handleAppChangePassword)
}

func handleAppUnbindDeviceWithAuth(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 {
		Username string `json:"username"`
		Password string `json:"password"`
		DeviceID string `json:"device_id"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

	if req.Username == "" || req.Password == "" || req.DeviceID == "" {
		response.Error(c, 400, "用户名、密码和设备ID不能为空")
		return
	}

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

	if user.Password != req.Password {
		response.Error(c, 401, "密码错误")
		return
	}

	var device model.UserDevice
	if err := database.DB.Where("user_id = ? AND application_id = ? AND device_id = ?", user.ID, app.ID, req.DeviceID).First(&device).Error; err != nil {
		response.Error(c, 404, "设备不存在")
		return
	}

	database.DB.Where("device_id = ?", device.ID).Delete(&model.DeviceSession{})

	if err := database.DB.Delete(&device).Error; err != nil {
		response.Error(c, 500, "解绑设备失败")
		return
	}

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

	service.LogVerification(c, &app.ID, &user.ID, "unbind_device", fmt.Sprintf("用户解绑设备(认证): %s", req.DeviceID), req.DeviceID, nil)

	response.Success(c, gin.H{
		"message": "解绑成功",
	})
}

func handleAppGetDevices(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
	}

	userID, exists := c.Get("user_id")
	if !exists {
		response.Error(c, 401, "未授权")
		return
	}

	var devices []model.UserDevice
	if err := database.DB.Where("user_id = ? AND application_id = ?", userID, app.ID).Find(&devices).Error; err != nil {
		response.Error(c, 500, "获取设备列表失败")
		return
	}

	result := make([]gin.H, 0)
	for _, device := range devices {
		var onlineSessionCount int64
		tenMinutesAgo := time.Now().Add(-10 * time.Minute)
		database.DB.Model(&model.DeviceSession{}).
			Where("device_id = ? AND last_heartbeat > ?", device.ID, tenMinutesAgo).
			Count(&onlineSessionCount)

		result = append(result, gin.H{
			"id":               device.ID,
			"device_id":        device.DeviceID,
			"device_name":      device.DeviceName,
			"device_type":      device.DeviceType,
			"status":           device.Status,
			"online_sessions":  onlineSessionCount,
			"created_at":       device.CreatedAt,
		})
	}

	response.Success(c, result)
}

func handleAppGetDeviceCount(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 {
		UserID uint `json:"user_id"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

	var count int64
	if err := database.DB.Model(&model.UserDevice{}).Where("user_id = ? AND application_id = ?", req.UserID, app.ID).Count(&count).Error; err != nil {
		response.Error(c, 500, "获取设备数量失败")
		return
	}

	response.Success(c, gin.H{
		"count":       count,
		"max_devices": app.MaxDevices,
		"remaining":   app.MaxDevices - int(count),
	})
}

func handleAppUnbindDevice(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 {
		UserID   uint   `json:"user_id"`
		DeviceID string `json:"device_id"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

	var device model.UserDevice
	if err := database.DB.Where("user_id = ? AND application_id = ? AND device_id = ?", req.UserID, app.ID, req.DeviceID).First(&device).Error; err != nil {
		response.Error(c, 404, "设备不存在")
		return
	}

	database.DB.Where("device_id = ?", device.ID).Delete(&model.DeviceSession{})

	if err := database.DB.Delete(&device).Error; err != nil {
		response.Error(c, 500, "解绑设备失败")
		return
	}

	var user model.AppUser
	if err := database.DB.First(&user, req.UserID).Error; err == nil {
		if user.DeviceID == req.DeviceID {
			now := time.Now()
			database.DB.Model(&user).Updates(map[string]interface{}{
				"device_id":         "",
				"last_heartbeat_at": &now,
			})
		}
	}

	service.LogVerification(c, &app.ID, &user.ID, "unbind_device", fmt.Sprintf("用户解绑设备: %s", req.DeviceID), req.DeviceID, nil)

	response.Success(c, gin.H{
		"message": "解绑成功",
	})
}

func handleAppGetInstances(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 {
		UserID uint `json:"user_id"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

	var devices []model.UserDevice
	if err := database.DB.Where("user_id = ? AND application_id = ?", req.UserID, app.ID).Find(&devices).Error; err != nil {
		response.Error(c, 500, "获取设备列表失败")
		return
	}

	deviceIDs := make([]uint, len(devices))
	for i, d := range devices {
		deviceIDs[i] = d.ID
	}

	heartbeatTimeout := app.HeartbeatTimeout
	if heartbeatTimeout <= 0 {
		heartbeatTimeout = 10
	}
	timeoutThreshold := time.Now().Add(-time.Duration(heartbeatTimeout) * time.Minute)

	var sessions []model.DeviceSession
	if len(deviceIDs) > 0 {
		if err := database.DB.Where("device_id IN ?", deviceIDs).Order("last_heartbeat DESC").Find(&sessions).Error; err != nil {
			response.Error(c, 500, "获取实例列表失败")
			return
		}
	}

	result := make([]gin.H, 0)
	for _, session := range sessions {
		isOnline := session.LastHeartbeat != nil && session.LastHeartbeat.After(timeoutThreshold)

		var device model.UserDevice
		for _, d := range devices {
			if d.ID == session.DeviceID {
				device = d
				break
			}
		}

		result = append(result, gin.H{
			"id":             session.ID,
			"instance_id":    session.InstanceID,
			"device_id":      device.DeviceID,
			"device_name":    device.DeviceName,
			"is_online":      isOnline,
			"last_heartbeat": session.LastHeartbeat,
			"created_at":     session.CreatedAt,
		})
	}

	response.Success(c, result)
}

func handleAppForceOfflineInstance(c *gin.Context) {
	appKey := c.Param("appKey")
	instanceID := c.Param("instance_id")

	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 {
		UserID uint `json:"user_id"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

	var devices []model.UserDevice
	if err := database.DB.Where("user_id = ? AND application_id = ?", req.UserID, app.ID).Find(&devices).Error; err != nil {
		response.Error(c, 500, "获取设备列表失败")
		return
	}

	deviceIDs := make([]uint, len(devices))
	for i, d := range devices {
		deviceIDs[i] = d.ID
	}

	if len(deviceIDs) == 0 {
		response.Error(c, 404, "实例不存在")
		return
	}

	result := database.DB.Where("instance_id = ? AND device_id IN ?", instanceID, deviceIDs).Delete(&model.DeviceSession{})
	if result.RowsAffected == 0 {
		response.Error(c, 404, "实例不存在")
		return
	}

	service.LogVerification(c, &app.ID, &req.UserID, "force_offline", fmt.Sprintf("强制离线实例: %s", instanceID), instanceID, nil)

	response.Success(c, gin.H{
		"message": "已强制离线",
	})
}

func handleAppChangePassword(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
	}

	var req struct {
		Username    string `json:"username" binding:"required"`
		OldPassword string `json:"old_password" binding:"required"`
		NewPassword string `json:"new_password" binding:"required,min=6"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

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

	if user.Password != req.OldPassword {
		response.Error(c, 400, "原密码错误")
		return
	}

	user.Password = req.NewPassword
	if err := database.DB.Save(&user).Error; err != nil {
		response.Error(c, 500, "密码修改失败")
		return
	}

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