package utils

import (
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"regexp"
	"strconv"
	"strings"
	"time"

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

// HashPassword 对密码进行哈希加密
func HashPassword(password string) (string, error) {
	bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	return string(bytes), err
}

// CheckPasswordHash 验证密码哈希
func CheckPasswordHash(password, hash string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
	return err == nil
}

// GenerateUUID 生成UUID
func GenerateUUID() string {
	return uuid.New().String()
}

// GenerateRandomString 生成指定长度的随机字符串
func GenerateRandomString(length int) (string, error) {
	bytes := make([]byte, length/2)
	if _, err := rand.Read(bytes); err != nil {
		return "", err
	}
	return hex.EncodeToString(bytes), nil
}

// IsValidEmail 验证邮箱格式
func IsValidEmail(email string) bool {
	pattern := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`
	regex := regexp.MustCompile(pattern)
	return regex.MatchString(email)
}

// IsValidPhone 验证手机号格式（中国大陆）
func IsValidPhone(phone string) bool {
	pattern := `^1[3-9]\d{9}$`
	regex := regexp.MustCompile(pattern)
	return regex.MatchString(phone)
}

// IsStrongPassword 验证密码强度
func IsStrongPassword(password string) bool {
	if len(password) < 8 {
		return false
	}
	
	// 至少包含一个数字
	hasNumber := regexp.MustCompile(`[0-9]`).MatchString(password)
	// 至少包含一个小写字母
	hasLower := regexp.MustCompile(`[a-z]`).MatchString(password)
	// 至少包含一个大写字母
	hasUpper := regexp.MustCompile(`[A-Z]`).MatchString(password)
	// 至少包含一个特殊字符
	hasSpecial := regexp.MustCompile(`[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]`).MatchString(password)
	
	return hasNumber && hasLower && hasUpper && hasSpecial
}

// GetPaginationParams 从请求中获取分页参数
func GetPaginationParams(c *gin.Context) (page, pageSize int) {
	pageStr := c.DefaultQuery("page", "1")
	pageSizeStr := c.DefaultQuery("page_size", "20")
	
	page, err := strconv.Atoi(pageStr)
	if err != nil || page < 1 {
		page = 1
	}
	
	pageSize, err = strconv.Atoi(pageSizeStr)
	if err != nil || pageSize < 1 || pageSize > 100 {
		pageSize = 20
	}
	
	return page, pageSize
}

// CalculateOffset 计算数据库查询偏移量
func CalculateOffset(page, pageSize int) int {
	return (page - 1) * pageSize
}

// CalculateTotalPages 计算总页数
func CalculateTotalPages(total, pageSize int) int {
	if total == 0 {
		return 0
	}
	return (total + pageSize - 1) / pageSize
}

// StringToInt 字符串转整数，带默认值
func StringToInt(str string, defaultValue int) int {
	if str == "" {
		return defaultValue
	}
	value, err := strconv.Atoi(str)
	if err != nil {
		return defaultValue
	}
	return value
}

// StringToBool 字符串转布尔值，带默认值
func StringToBool(str string, defaultValue bool) bool {
	if str == "" {
		return defaultValue
	}
	value, err := strconv.ParseBool(str)
	if err != nil {
		return defaultValue
	}
	return value
}

// TrimSpaces 去除字符串前后空格
func TrimSpaces(str string) string {
	return strings.TrimSpace(str)
}

// FormatTime 格式化时间
func FormatTime(t time.Time) string {
	return t.Format("2006-01-02 15:04:05")
}

// ParseTime 解析时间字符串
func ParseTime(timeStr string) (time.Time, error) {
	return time.Parse("2006-01-02 15:04:05", timeStr)
}

// GetUserIDFromContext 从上下文中获取用户ID
func GetUserIDFromContext(c *gin.Context) (int64, bool) {
	userID, exists := c.Get("user_id")
	if !exists {
		return 0, false
	}
	if id, ok := userID.(int64); ok {
		return id, true
	}
	return 0, false
}

// SetUserIDToContext 设置用户ID到上下文
func SetUserIDToContext(c *gin.Context, userID int64) {
	c.Set("user_id", userID)
}

// Int64ToString 将int64转换为string
func Int64ToString(i int64) string {
	return strconv.FormatInt(i, 10)
}

// StringToInt64 将string转换为int64
func StringToInt64(str string) (int64, error) {
	return strconv.ParseInt(str, 10, 64)
}

// Contains 检查切片是否包含指定元素
func Contains(slice []string, item string) bool {
	for _, s := range slice {
		if s == item {
			return true
		}
	}
	return false
}

// RemoveDuplicates 去除字符串切片中的重复元素
func RemoveDuplicates(slice []string) []string {
	keys := make(map[string]bool)
	result := []string{}
	
	for _, item := range slice {
		if !keys[item] {
			keys[item] = true
			result = append(result, item)
		}
	}
	
	return result
}

// GenerateFileName 生成文件名
func GenerateFileName(originalName string) string {
	ext := ""
	if dotIndex := strings.LastIndex(originalName, "."); dotIndex != -1 {
		ext = originalName[dotIndex:]
	}
	return fmt.Sprintf("%d_%s%s", time.Now().Unix(), GenerateUUID()[:8], ext)
}

// GetClientIP 获取客户端IP地址
func GetClientIP(c *gin.Context) string {
	// 尝试从X-Forwarded-For头获取
	if ip := c.GetHeader("X-Forwarded-For"); ip != "" {
		if index := strings.Index(ip, ","); index != -1 {
			return strings.TrimSpace(ip[:index])
		}
		return strings.TrimSpace(ip)
	}
	
	// 尝试从X-Real-IP头获取
	if ip := c.GetHeader("X-Real-IP"); ip != "" {
		return strings.TrimSpace(ip)
	}
	
	// 使用RemoteAddr
	return c.ClientIP()
}