package frontend

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

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

func SetupRoutes(r *gin.Engine) {
	auth := r.Group("/api/v1/auth")
	{
		auth.POST("/register", handleRegister)
		auth.POST("/login", handleLogin)
		auth.POST("/logout", handleLogout)
		auth.POST("/refresh", handleRefreshToken)
	}

	api := r.Group("/api/v1")
	{
		api.POST("/login", handleLogin)
		api.POST("/register", handleRegister)
		api.POST("/logout", handleLogout)
		api.POST("/refresh", handleRefreshToken)
		api.POST("/forgot-password", handleForgotPassword)
		api.POST("/reset-password", handleResetPassword)
		api.POST("/send-sms", handleSendSms)
		api.POST("/verify", handleCardVerification)
		api.GET("/verify/status", handleGetVerificationStatus)
	}

	docs := r.Group("/api/v1/docs")
	{
		docs.GET("", handleGetDocs)
		docs.GET("/:id", handleGetDoc)
		docs.GET("/slug/:slug", handleGetDocBySlug)
	}

	docCategories := r.Group("/api/v1/doc-categories")
	{
		docCategories.GET("", handleGetDocCategories)
	}

	pricing := r.Group("/api/v1/pricing")
	{
		pricing.GET("", handleGetPricing)
	}

	packages := r.Group("/api/v1/packages")
	{
		packages.GET("", handleGetPricing)
	}

	site := r.Group("/api/v1/site")
	{
		site.GET("/info", handleGetSiteInfo)
		site.GET("/contact", handleGetContact)
	}

	captcha := r.Group("/api/v1/captcha")
	{
		captcha.GET("", handleGetCaptcha)
	}

	settings := r.Group("/api/v1/settings")
	{
		settings.GET("", handleGetSettings)
		settings.GET("/payment-channels", handleGetActivePaymentChannels)
	}

	public := r.Group("/api/v1/public")
	{
		public.GET("/stats", handleGetPublicStats)
	}
}

func handleGetCaptcha(c *gin.Context) {
	authService := service.NewAuthService()
	result, err := authService.GetCaptcha()
	if err != nil {
		response.Error(c, 500, "获取验证码失败")
		return
	}
	response.Success(c, result)
}

func handleGetSettings(c *gin.Context) {
	settingService := service.NewSettingService()
	settings, err := settingService.GetSettings()
	if err != nil {
		response.Error(c, 500, "获取设置失败")
		return
	}
	response.Success(c, settings)
}

func handleGetActivePaymentChannels(c *gin.Context) {
	var channels []model.PaymentChannel
	if err := database.DB.Where("status = ?", "active").Order("sort asc, id asc").Find(&channels).Error; err != nil {
		response.Error(c, 500, "获取支付通道失败")
		return
	}
	response.Success(c, gin.H{"channels": channels})
}

func handleRegister(c *gin.Context) {
	var req struct {
		Username string `json:"username"`
		Password string `json:"password"`
		Email    string `json:"email"`
		Phone    string `json:"phone"`
		Role     string `json:"role"`
		Type     string `json:"type"`
		Code     string `json:"code"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		fmt.Printf("注册参数错误: %v\n", err)
		response.Error(c, 400, "参数错误")
		return
	}

	fmt.Printf("注册请求: username=%s, email=%s, phone=%s, role=%s, type=%s\n",
		req.Username, req.Email, req.Phone, req.Role, req.Type)

	if req.Role == "" {
		req.Role = "admin"
	}

	username := req.Username
	email := req.Email
	phone := req.Phone
	password := req.Password

	if req.Type == "email" {
		username = email
		email = req.Email
		password = req.Password
	} else if req.Type == "sms" {
		username = phone
		phone = req.Phone
		password = req.Password
	}

	fmt.Printf("处理后的注册数据: username=%s, email=%s, phone=%s, password_len=%d, role=%s\n",
		username, email, phone, len(password), req.Role)

	authService := service.NewAuthService()
	err := authService.RegisterWithRole(username, email, phone, password, req.Role)
	if err != nil {
		fmt.Printf("注册失败: %v\n", err)
		response.Error(c, 400, err.Error())
		return
	}

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

func handleLogin(c *gin.Context) {
	var req struct {
		Username  string `json:"username"`
		Password  string `json:"password"`
		AgentPath string `json:"agent_path"`
		CaptchaID string `json:"captcha_id"`
		Captcha   string `json:"captcha"`
		Type      string `json:"type"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		fmt.Printf("登录参数错误: %v\n", err)
		response.Error(c, 400, "参数错误")
		return
	}

	fmt.Printf("登录请求: username=%s, password_len=%d, agent_path=%s\n",
		req.Username, len(req.Password), req.AgentPath)

	// 检查是否启用了验证码
	var enableCaptchaSetting model.Setting
	err := database.DB.Where("category = ? AND key = ?", "basic", "enableCaptcha").First(&enableCaptchaSetting).Error
	enableCaptcha := false
	if err == nil && enableCaptchaSetting.Value == "true" {
		enableCaptcha = true
	}

	// 如果启用了验证码，验证验证码
	if enableCaptcha {
		if req.CaptchaID == "" || req.Captcha == "" {
			response.Error(c, 400, "请输入验证码")
			return
		}

		// 查询验证码
		var captcha model.Captcha
		if err := database.DB.Where("captcha_id = ?", req.CaptchaID).First(&captcha).Error; err != nil {
			response.Error(c, 400, "验证码错误或已过期")
			return
		}

		// 检查验证码是否过期
		if time.Now().After(captcha.ExpiresAt) {
			database.DB.Delete(&captcha)
			response.Error(c, 400, "验证码已过期")
			return
		}

		// 验证码比较（忽略大小写和空格）
		if strings.ToLower(strings.TrimSpace(req.Captcha)) != strings.ToLower(strings.TrimSpace(captcha.Code)) {
			database.DB.Delete(&captcha)
			response.Error(c, 400, "验证码错误")
			return
		}

		// 删除已使用的验证码
		database.DB.Delete(&captcha)
	}

	authService := service.NewAuthService()
	result, err := authService.Login(req.Username, req.Password, req.AgentPath)
	if err != nil {
		fmt.Printf("登录失败: %v\n", err)
		response.Error(c, 401, err.Error())
		return
	}

	fmt.Printf("登录成功: username=%s\n", req.Username)
	response.Success(c, result)
}

func handleLogout(c *gin.Context) {
	response.Success(c, gin.H{
		"message": "登出成功",
	})
}

func handleRefreshToken(c *gin.Context) {
	response.Success(c, gin.H{
		"token": "",
	})
}

func handleGetDocs(c *gin.Context) {
	var docs []model.Doc
	if err := database.DB.Where("status = ?", "published").Preload("Category").Find(&docs).Error; err != nil {
		response.Error(c, 500, "获取文档列表失败")
		return
	}
	response.Success(c, docs)
}

func handleGetDoc(c *gin.Context) {
	id := c.Param("id")
	var doc model.Doc
	if err := database.DB.Where("id = ? AND status = ?", id, "published").Preload("Category").First(&doc).Error; err != nil {
		response.Error(c, 404, "文档不存在")
		return
	}
	response.Success(c, doc)
}

func handleGetDocBySlug(c *gin.Context) {
	slug := c.Param("slug")
	var doc model.Doc
	if err := database.DB.Where("slug = ? AND status = ?", slug, "published").Preload("Category").First(&doc).Error; err != nil {
		response.Error(c, 404, "文档不存在")
		return
	}
	response.Success(c, doc)
}

func handleGetDocCategories(c *gin.Context) {
	var categories []model.DocCategory
	if err := database.DB.Find(&categories).Error; err != nil {
		response.Error(c, 500, "获取文档分类失败")
		return
	}
	response.Success(c, categories)
}

func handleGetPricing(c *gin.Context) {
	var packages []model.Package
	if err := database.DB.Where("status = ?", "active").Find(&packages).Error; err != nil {
		response.Error(c, 500, "获取价格信息失败")
		return
	}

	var result []gin.H
	for _, pkg := range packages {
		var permission model.PackagePermission
		database.DB.Where("package_id = ?", pkg.ID).First(&permission)

		result = append(result, gin.H{
			"id":             pkg.ID,
			"name":           pkg.Name,
			"name_en":        pkg.NameEn,
			"price":          pkg.Price,
			"currency":       pkg.Currency,
			"period":         pkg.Period,
			"description":    pkg.Description,
			"description_en": pkg.DescriptionEn,
			"status":         pkg.Status,
			"sort":           pkg.Sort,
			"is_recommended": pkg.IsRecommended,
			"allow_upgrade":  pkg.AllowUpgrade,
			"created_at":     pkg.CreatedAt,
			"updated_at":     pkg.UpdatedAt,
			"permissions":    permission,
		})
	}

	response.Success(c, gin.H{
		"packages": result,
	})
}

func handleGetSiteInfo(c *gin.Context) {
	response.Success(c, gin.H{
		"site_name":     "验证平台",
		"site_url":      "http://localhost:3000",
		"description":   "专业的应用验证平台",
		"contact_email": "admin@example.com",
	})
}

func handleGetContact(c *gin.Context) {
	response.Success(c, gin.H{
		"email":  "admin@example.com",
		"qq":     "123456789",
		"wechat": "example_wechat",
		"phone":  "400-123-4567",
	})
}

func handleForgotPassword(c *gin.Context) {
	var req struct {
		Email string `json:"email"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

	authService := service.NewAuthService()
	err := authService.ForgotPassword(req.Email)
	if err != nil {
		response.Error(c, 400, err.Error())
		return
	}

	response.Success(c, gin.H{
		"message": "重置链接已发送到您的邮箱",
	})
}

func handleResetPassword(c *gin.Context) {
	var req struct {
		Token    string `json:"token"`
		Password string `json:"password"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

	authService := service.NewAuthService()
	err := authService.ResetPassword(req.Token, req.Password)
	if err != nil {
		response.Error(c, 400, err.Error())
		return
	}

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

func handleSendSms(c *gin.Context) {
	var req struct {
		Phone string `json:"phone"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

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

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

	authService := service.NewAuthService()
	user, err := authService.GetProfile(userID.(uint))
	if err != nil {
		response.Error(c, 404, "用户不存在")
		return
	}

	response.Success(c, user)
}

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

	var req struct {
		Email string `json:"email"`
		Phone string `json:"phone"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

	authService := service.NewAuthService()
	err := authService.UpdateProfile(userID.(uint), req.Email, req.Phone)
	if err != nil {
		response.Error(c, 400, err.Error())
		return
	}

	response.Success(c, gin.H{
		"message": "资料更新成功",
	})
}

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

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

	authService := service.NewAuthService()
	err := authService.ChangePassword(userID.(uint), req.OldPassword, req.NewPassword)
	if err != nil {
		response.Error(c, 400, err.Error())
		return
	}

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

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

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

	filename := fmt.Sprintf("avatar_%d_%s", userID, file.Filename)
	if err := c.SaveUploadedFile(file, "uploads/"+filename); err != nil {
		response.Error(c, 500, "文件保存失败")
		return
	}

	response.Success(c, gin.H{
		"avatar": "/uploads/" + filename,
	})
}

func handleCardVerification(c *gin.Context) {
	var req struct {
		CardKey  string `json:"card_key"`
		Username string `json:"username"`
		DeviceID string `json:"device_id"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

	var card model.Card
	if err := database.DB.Where("card_key = ?", req.CardKey).First(&card).Error; err != nil {
		response.Error(c, 404, "卡密不存在")
		return
	}

	if card.Status != "unused" {
		response.Error(c, 400, "卡密已被使用或已禁用")
		return
	}

	response.Success(c, gin.H{
		"message":   "验证成功",
		"card_id":   card.ID,
		"card_type": card.CardType,
	})
}

func handleGetVerificationStatus(c *gin.Context) {
	cardKey := c.Query("card_key")
	if cardKey == "" {
		response.Error(c, 400, "请提供卡密")
		return
	}

	var card model.Card
	if err := database.DB.Where("card_key = ?", cardKey).First(&card).Error; err != nil {
		response.Error(c, 404, "卡密不存在")
		return
	}

	response.Success(c, gin.H{
		"status":  card.Status,
		"card_id": card.ID,
		"used_at": card.UsedAt,
	})
}

func HandleCreateOrder(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		response.Error(c, 401, "请先登录")
		return
	}

	var req struct {
		PackageID        uint `json:"package_id"`
		PaymentChannelID uint `json:"payment_channel_id"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

	if req.PackageID == 0 {
		response.Error(c, 400, "请选择套餐")
		return
	}

	var pkg model.Package
	if err := database.DB.Where("id = ? AND status = ?", req.PackageID, "active").First(&pkg).Error; err != nil {
		response.Error(c, 404, "套餐不存在或已下架")
		return
	}

	orderNo := fmt.Sprintf("ORD%d%d", time.Now().Unix(), userID.(uint))

	if pkg.Price == 0 {
		now := time.Now()
		pkgID := pkg.ID
		order := model.Order{
			OrderNo:     orderNo,
			UserID:      userID.(uint),
			PackageID:   &pkgID,
			OrderType:   "package",
			Title:       fmt.Sprintf("领取套餐 - %s", pkg.Name),
			Amount:      0,
			PaymentType: "free",
			Status:      "paid",
			PaymentAt:   &now,
			Description: fmt.Sprintf("免费套餐: %s, 周期: %s", pkg.Name, pkg.Period),
		}

		if err := database.DB.Create(&order).Error; err != nil {
			response.Error(c, 500, "创建订单失败")
			return
		}

		var expiredAt *time.Time
		if pkg.Period != "" && pkg.Period != "permanent" {
			duration := parsePeriod(pkg.Period)
			if duration > 0 {
				exp := now.Add(duration)
				expiredAt = &exp
			}
		}

		userPackage := model.UserPackage{
			UserID:    userID.(uint),
			PackageID: pkg.ID,
			ExpiredAt: expiredAt,
			Status:    "active",
		}

		if err := database.DB.Create(&userPackage).Error; err != nil {
			response.Error(c, 500, "创建套餐授权失败")
			return
		}

		if err := database.DB.Model(&model.User{}).Where("id = ?", userID).Update("current_package_id", pkg.ID).Error; err != nil {
			response.Error(c, 500, "更新用户套餐失败")
			return
		}

		response.Success(c, gin.H{
			"order_no": order.OrderNo,
			"order_id": order.ID,
			"amount":   0,
			"status":   "paid",
			"message":  "免费套餐领取成功",
		})
		return
	}

	if req.PaymentChannelID == 0 {
		response.Error(c, 400, "请选择支付方式")
		return
	}

	var paymentChannel model.PaymentChannel
	if err := database.DB.Where("id = ? AND status = ?", req.PaymentChannelID, "active").First(&paymentChannel).Error; err != nil {
		response.Error(c, 404, "支付通道不存在或已禁用")
		return
	}

	pkgID := pkg.ID
	order := model.Order{
		OrderNo:       orderNo,
		UserID:        userID.(uint),
		PackageID:     &pkgID,
		OrderType:     "package",
		Title:         fmt.Sprintf("购买套餐 - %s", pkg.Name),
		Amount:        pkg.Price,
		PaymentType:   paymentChannel.Type,
		PaymentMethod: paymentChannel.Type,
		Status:        "pending",
		Description:   fmt.Sprintf("套餐ID: %d, 套餐名称: %s, 周期: %s, 支付通道: %s", pkg.ID, pkg.Name, pkg.Period, paymentChannel.Name),
	}

	if err := database.DB.Create(&order).Error; err != nil {
		response.Error(c, 500, "创建订单失败")
		return
	}

	scheme := "http"
	if c.Request.TLS != nil {
		scheme = "https"
	}
	host := c.Request.Host
	callbackBaseURL := fmt.Sprintf("%s://%s", scheme, host)

	switch paymentChannel.Type {
	case "bepusdt":
		paymentService, err := payment.GetPaymentService(paymentChannel, callbackBaseURL)
		if err != nil {
			response.Error(c, 500, "支付服务初始化失败: "+err.Error())
			return
		}

		notifyURL := fmt.Sprintf("%s/api/v1/payment/callback/bepusdt", callbackBaseURL)
		redirectURL := fmt.Sprintf("%s/admin/finance?order=%s", callbackBaseURL, orderNo)

		result, err := paymentService.CreateOrder(orderNo, pkg.Price, notifyURL, redirectURL, order.Title)
		if err != nil {
			response.Error(c, 500, "创建支付订单失败: "+err.Error())
			return
		}

		extraData := map[string]interface{}{
			"trade_id":        result.TradeID,
			"payment_url":     result.PaymentURL,
			"actual_amount":   result.ActualAmount,
			"token":           result.Token,
			"expiration_time": result.ExpirationTime,
			"channel_id":      paymentChannel.ID,
		}
		extraJSON, _ := json.Marshal(extraData)
		order.ExtraData = string(extraJSON)
		database.DB.Save(&order)

		response.Success(c, gin.H{
			"order_no":        order.OrderNo,
			"order_id":        order.ID,
			"amount":          order.Amount,
			"actual_amount":   result.ActualAmount,
			"payment_url":     result.PaymentURL,
			"trade_id":        result.TradeID,
			"token":           result.Token,
			"expiration_time": result.ExpirationTime,
		})
		return
	}

	response.Success(c, gin.H{
		"order_no": order.OrderNo,
		"order_id": order.ID,
		"amount":   order.Amount,
		"pay_url":  "",
	})
}

func HandleGetOrder(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		response.Error(c, 401, "请先登录")
		return
	}

	orderNo := c.Param("order_no")
	if orderNo == "" {
		response.Error(c, 400, "订单号不能为空")
		return
	}

	var order model.Order
	if err := database.DB.Where("order_no = ? AND user_id = ?", orderNo, userID).First(&order).Error; err != nil {
		response.Error(c, 404, "订单不存在")
		return
	}

	response.Success(c, gin.H{
		"order": gin.H{
			"id":           order.ID,
			"order_no":     order.OrderNo,
			"amount":       order.Amount,
			"status":       order.Status,
			"payment_type": order.PaymentType,
			"title":        order.Title,
			"extra_data":   order.ExtraData,
			"created_at":   order.CreatedAt,
			"payment_at":   order.PaymentAt,
		},
	})
}

func HandleGetOrderStatus(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		response.Error(c, 401, "请先登录")
		return
	}

	orderNo := c.Param("order_no")
	if orderNo == "" {
		response.Error(c, 400, "订单号不能为空")
		return
	}

	var order model.Order
	if err := database.DB.Where("order_no = ? AND user_id = ?", orderNo, userID).First(&order).Error; err != nil {
		response.Error(c, 404, "订单不存在")
		return
	}

	response.Success(c, gin.H{
		"status":     order.Status,
		"payment_at": order.PaymentAt,
	})
}

func parsePeriod(period string) time.Duration {
	switch period {
	case "daily":
		return 24 * time.Hour
	case "weekly":
		return 7 * 24 * time.Hour
	case "monthly":
		return 30 * 24 * time.Hour
	case "quarterly":
		return 90 * 24 * time.Hour
	case "yearly":
		return 365 * 24 * time.Hour
	default:
		return 0
	}
}

func handleGetPublicStats(c *gin.Context) {
	var totalApps, totalUsers, totalVerifications int64

	database.DB.Model(&model.Application{}).Count(&totalApps)
	database.DB.Model(&model.User{}).Where("role = ?", "admin").Count(&totalUsers)
	database.DB.Model(&model.Card{}).Where("status = ?", "used").Count(&totalVerifications)

	response.Success(c, gin.H{
		"totalApps":         totalApps,
		"totalUsers":        totalUsers,
		"totalVerifications": totalVerifications,
	})
}
