package app

import (
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"

	"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"
	"github.com/google/uuid"
)

func SetupUserRoutes(r *gin.RouterGroup) {
	r.POST("/logout", handleAppLogout)
	r.GET("/user-info", handleAppGetUserInfo)
	r.POST("/avatar", handleAppUploadAvatar)
}

func handleAppLogout(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 req struct {
		DeviceID   string `json:"device_id" binding:"required"`
		InstanceID string `json:"instance_id" binding:"required"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "device_id 和 instance_id 为必填参数")
		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
	}

	if len(devices) == 0 {
		response.Success(c, gin.H{"message": "登出成功"})
		return
	}

	// 查找指定设备
	var targetDeviceID uint
	for _, d := range devices {
		if d.DeviceID == req.DeviceID {
			targetDeviceID = d.ID
			break
		}
	}

	if targetDeviceID == 0 {
		response.Error(c, 404, "设备不存在")
		return
	}

	// 清除指定实例
	result := database.DB.Where("device_id = ? AND instance_id = ?", targetDeviceID, req.InstanceID).Delete(&model.DeviceSession{})
	deletedCount := result.RowsAffected
	log.Printf("[INFO] Logout: user %d, device %s, instance %s, deleted %d", userID, req.DeviceID, req.InstanceID, deletedCount)

	service.LogVerification(c, &app.ID, uintPtr(userID.(uint)), "logout", fmt.Sprintf("用户登出，清除 %d 个实例", deletedCount), req.DeviceID, nil)

	response.Success(c, gin.H{
		"message":       "登出成功",
		"deleted_count": deletedCount,
	})
}

func handleAppGetUserInfo(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 user model.AppUser
	if err := database.DB.First(&user, userID).Error; err != nil {
		response.Error(c, 404, "用户不存在")
		return
	}

	result := gin.H{
		"user_id":   user.ID,
		"username":  user.Username,
		"email":     user.Email,
		"avatar":    user.Avatar,
		"status":    user.Status,
	}

	if user.Balance == -1 {
		result["is_permanent"] = true
	} else if app.BillingType == "subscription" {
		if user.ExpiryAt != nil {
			result["expiry_at"] = user.ExpiryAt.Format("2006-01-02 15:04:05")
			result["expiry_timestamp"] = user.ExpiryAt.Unix()
		}
	} else if app.BillingType != "free" {
		result["balance"] = user.Balance
	}

	response.Success(c, result)
}

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

	file, header, err := c.Request.FormFile("avatar")
	if err != nil {
		response.Error(c, 400, "请上传头像文件")
		return
	}
	defer file.Close()

	if !isValidImageFile(header.Filename) {
		response.Error(c, 400, "只支持JPG、PNG、GIF格式的图片")
		return
	}

	const maxSize = 2 << 20
	if header.Size > maxSize {
		response.Error(c, 400, "头像文件大小不能超过2MB")
		return
	}

	avatarDir := filepath.Join("uploads", "avatars")
	if err := os.MkdirAll(avatarDir, 0755); err != nil {
		response.Error(c, 500, "创建目录失败")
		return
	}

	ext := filepath.Ext(header.Filename)
	filename := fmt.Sprintf("avatar_%d_%s%s", userID.(uint), uuid.New().String()[:8], ext)
	dst := filepath.Join(avatarDir, filename)

	dstFile, err := os.Create(dst)
	if err != nil {
		response.Error(c, 500, "创建文件失败")
		return
	}
	defer dstFile.Close()

	if _, err := io.Copy(dstFile, file); err != nil {
		response.Error(c, 500, "保存文件失败")
		return
	}

	avatarURL := fmt.Sprintf("/uploads/avatars/%s", filename)

	var user model.AppUser
	if err := database.DB.First(&user, userID).Error; err != nil {
		response.Error(c, 404, "用户不存在")
		return
	}

	oldAvatar := user.Avatar
	user.Avatar = avatarURL
	if err := database.DB.Save(&user).Error; err != nil {
		response.Error(c, 500, "保存头像失败")
		return
	}

	if oldAvatar != "" && strings.HasPrefix(oldAvatar, "/uploads/avatars/") {
		oldPath := filepath.Join(".", oldAvatar)
		os.Remove(oldPath)
	}

	response.Success(c, gin.H{
		"avatar_url": avatarURL,
	})
}

func isValidImageFile(filename string) bool {
	ext := strings.ToLower(filepath.Ext(filename))
	validExts := map[string]bool{
		".jpg":  true,
		".jpeg": true,
		".png":  true,
		".gif":  true,
		".webp": true,
	}
	return validExts[ext]
}

func uintPtr(v uint) *uint {
	return &v
}
