package admin

import (
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"
	"verification-platform-backend/internal/database"
	"verification-platform-backend/internal/model"
	"verification-platform-backend/pkg/response"

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

func SetupProfileRoutes(r *gin.RouterGroup) {
	profile := r.Group("/profile")
	{
		profile.GET("", handleGetProfile)
		profile.PUT("", handleUpdateProfile)
		profile.PUT("/password", handleChangePassword)
		profile.POST("/avatar", handleUploadAvatar)
		profile.POST("/api-token", handleGenerateApiToken)
	}
}

func handleGetProfile(c *gin.Context) {
	userID := c.GetUint("user_id")

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

	profile := struct {
		ID          uint       `json:"id"`
		Username    string     `json:"username"`
		Email       string     `json:"email"`
		Phone       string     `json:"phone"`
		Avatar      string     `json:"avatar"`
		Role        string     `json:"role"`
		Status      string     `json:"status"`
		ApiToken    string     `json:"api_token"`
		CreatedAt   time.Time  `json:"created_at"`
		LastLoginAt *time.Time `json:"last_login_at"`
	}{
		ID:          user.ID,
		Username:    user.Username,
		Email:       "",
		Phone:       "",
		Avatar:      user.Avatar,
		Role:        user.Role,
		Status:      user.Status,
		ApiToken:    user.ApiToken,
		CreatedAt:   user.CreatedAt,
		LastLoginAt: user.LastLoginAt,
	}

	if user.Email != nil {
		profile.Email = *user.Email
	}

	subscription := getSubscriptionInfo(&user)

	transactions := getRecentTransactions(userID)

	response.Success(c, gin.H{
		"user":        profile,
		"subscription": subscription,
		"transactions": transactions,
	})
}

func getSubscriptionInfo(user *model.User) gin.H {
	var pkg model.Package
	var packagePermission model.PackagePermission

	defaultQuota := 10000
	defaultStorage := int64(100 * 1024 * 1024)

	if user.CurrentPackageID != nil {
		if err := database.DB.First(&pkg, *user.CurrentPackageID).Error; err == nil {
			database.DB.Where("package_id = ?", pkg.ID).First(&packagePermission)
		}
	}

	planName := "基础版"
	if pkg.ID > 0 {
		planName = pkg.Name
	}

	apiQuota := defaultQuota
	if packagePermission.MaxApiCalls > 0 {
		apiQuota = packagePermission.MaxApiCalls
	}

	storageQuota := defaultStorage
	if packagePermission.MaxStorage > 0 {
		storageQuota = int64(packagePermission.MaxStorage) * 1024 * 1024
	}

	var expireDate string
	if pkg.Period == "monthly" {
		expireDate = time.Now().AddDate(0, 1, 0).Format("2006-01-02")
	} else if pkg.Period == "yearly" {
		expireDate = time.Now().AddDate(1, 0, 0).Format("2006-01-02")
	} else {
		expireDate = "永久有效"
	}

	return gin.H{
		"plan":         planName,
		"status":       "active",
		"expire_date":  expireDate,
		"api_quota":    apiQuota,
		"api_used":     user.ApiCallsUsed,
		"storage_quota": storageQuota,
		"storage_used": user.StorageUsed,
	}
}

func getRecentTransactions(userID uint) []gin.H {
	var orders []model.Order
	database.DB.Where("user_id = ? AND status = ?", userID, "paid").
		Order("created_at DESC").
		Limit(5).
		Find(&orders)

	transactions := make([]gin.H, 0, len(orders))
	for _, order := range orders {
		txType := "consume"
		if order.OrderType == "user_recharge" || order.OrderType == "card_recharge" {
			txType = "recharge"
		} else if order.OrderType == "refund" {
			txType = "refund"
		}

		transactions = append(transactions, gin.H{
			"id":          order.ID,
			"type":        txType,
			"amount":      order.Amount,
			"description": order.Title,
			"created_at":  order.CreatedAt,
		})
	}

	return transactions
}

type UpdateProfileRequest struct {
	Username string `json:"username"`
	Email    string `json:"email"`
	Phone    string `json:"phone"`
}

func handleUpdateProfile(c *gin.Context) {
	userID := c.GetUint("user_id")

	var req UpdateProfileRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "请求参数错误")
		return
	}

	if req.Username == "" {
		response.Error(c, 400, "用户名不能为空")
		return
	}

	if req.Email == "" {
		response.Error(c, 400, "邮箱不能为空")
		return
	}

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

	var existingUser model.User
	if err := database.DB.Where("username = ? AND id != ?", req.Username, userID).First(&existingUser).Error; err == nil {
		response.Error(c, 400, "用户名已被使用")
		return
	}

	if err := database.DB.Where("email = ? AND id != ?", req.Email, userID).First(&existingUser).Error; err == nil {
		response.Error(c, 400, "邮箱已被使用")
		return
	}

	user.Username = req.Username
	email := req.Email
	user.Email = &email

	if err := database.DB.Save(&user).Error; err != nil {
		log.Printf("更新用户信息失败: %v", err)
		response.Error(c, 500, "更新用户信息失败")
		return
	}

	response.Success(c, gin.H{
		"user": gin.H{
			"id":       user.ID,
			"username": user.Username,
			"email":    user.Email,
			"avatar":   user.Avatar,
			"role":     user.Role,
			"status":   user.Status,
		},
	})
}

type ChangePasswordRequest struct {
	CurrentPassword string `json:"current_password"`
	NewPassword     string `json:"new_password"`
}

func handleChangePassword(c *gin.Context) {
	userID := c.GetUint("user_id")

	var req ChangePasswordRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "请求参数错误")
		return
	}

	if req.CurrentPassword == "" {
		response.Error(c, 400, "请输入当前密码")
		return
	}

	if req.NewPassword == "" {
		response.Error(c, 400, "请输入新密码")
		return
	}

	if len(req.NewPassword) < 6 {
		response.Error(c, 400, "密码长度至少6位")
		return
	}

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

	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.CurrentPassword)); err != nil {
		response.Error(c, 400, "当前密码错误")
		return
	}

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

	user.Password = string(hashedPassword)
	if err := database.DB.Save(&user).Error; err != nil {
		log.Printf("更新密码失败: %v", err)
		response.Error(c, 500, "更新密码失败")
		return
	}

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

func handleUploadAvatar(c *gin.Context) {
	userID := c.GetUint("user_id")

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

	ext := strings.ToLower(filepath.Ext(header.Filename))
	allowedExts := map[string]bool{
		".jpg":  true,
		".jpeg": true,
		".png":  true,
		".gif":  true,
		".webp": true,
	}

	if !allowedExts[ext] {
		response.Error(c, 400, "不支持的文件格式，仅支持 JPG、PNG、GIF、WEBP")
		return
	}

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

	uploadDir := "uploads/avatars"
	if err := os.MkdirAll(uploadDir, 0755); err != nil {
		log.Printf("创建上传目录失败: %v", err)
		response.Error(c, 500, "创建上传目录失败")
		return
	}

	filename := fmt.Sprintf("%d_%d%s", userID, time.Now().UnixNano(), ext)
	filePath := filepath.Join(uploadDir, filename)

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

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

	avatarURL := "/uploads/avatars/" + filename

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

	if user.Avatar != "" && strings.HasPrefix(user.Avatar, "/uploads/avatars/") {
		oldPath := "." + user.Avatar
		if _, err := os.Stat(oldPath); err == nil {
			os.Remove(oldPath)
		}
	}

	user.Avatar = avatarURL
	if err := database.DB.Save(&user).Error; err != nil {
		log.Printf("更新头像失败: %v", err)
		response.Error(c, 500, "更新头像失败")
		return
	}

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

func handleGenerateApiToken(c *gin.Context) {
	userID := c.GetUint("user_id")

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

	bytes := make([]byte, 32)
	if _, err := rand.Read(bytes); err != nil {
		log.Printf("生成API Token失败: %v", err)
		response.Error(c, 500, "生成API Token失败")
		return
	}
	apiToken := hex.EncodeToString(bytes)

	user.ApiToken = apiToken
	if err := database.DB.Save(&user).Error; err != nil {
		log.Printf("保存API Token失败: %v", err)
		response.Error(c, 500, "保存API Token失败")
		return
	}

	response.Success(c, gin.H{
		"api_token": apiToken,
	})
}
