package admin

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"
	"verification-platform-backend/internal/database"
	"verification-platform-backend/internal/model"

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

func SetupSystemSettingsRoutes(r *gin.RouterGroup) {
	settings := r.Group("/system-settings")
	{
		settings.GET("", handleGetSystemSettings)
		settings.PUT("", handleUpdateSystemSettings)
		settings.POST("/upload", handleUploadSystemImage)
		settings.GET("/payment", handleGetPaymentSettings)
		settings.PUT("/payment", handleUpdatePaymentSettings)
		settings.GET("/email", handleGetEmailSettings)
		settings.PUT("/email", handleUpdateEmailSettings)
	}

	paymentChannels := r.Group("/payment-channels")
	{
		paymentChannels.GET("", handleGetPaymentChannels)
		paymentChannels.POST("", handleCreatePaymentChannel)
		paymentChannels.GET("/:id", handleGetPaymentChannel)
		paymentChannels.PUT("/:id", handleUpdatePaymentChannel)
		paymentChannels.DELETE("/:id", handleDeletePaymentChannel)
		paymentChannels.PUT("/:id/status", handleUpdatePaymentChannelStatus)
		paymentChannels.PUT("/batch/status", handleBatchUpdatePaymentChannelStatus)
		paymentChannels.DELETE("/batch", handleBatchDeletePaymentChannels)
	}
}

type SystemSettingsResponse struct {
	SiteName    string `json:"site_name"`
	SiteLogo    string `json:"site_logo"`
	SiteFavicon string `json:"site_favicon"`
	SiteFooter  string `json:"site_footer"`

	EnableCaptcha        bool `json:"enable_captcha"`
	LoginFailLockCount   int  `json:"login_fail_lock_count"`
	LoginFailLockMinutes int  `json:"login_fail_lock_minutes"`
	PasswordMinLength    int  `json:"password_min_length"`
	SessionTimeout       int  `json:"session_timeout"`

	EnableBackup      bool   `json:"enable_backup"`
	BackupInterval    int    `json:"backup_interval"`
	BackupRetention   int    `json:"backup_retention"`
	BackupStorageType string `json:"backup_storage_type"`

	EnableTicketSystem bool `json:"enable_ticket_system"`
	DefaultTheme       string `json:"default_theme"`
	EnableMultiLang    bool `json:"enable_multi_lang"`

	EnableNotification   bool   `json:"enable_notification"`
	AdminNotifyEmail     string `json:"admin_notify_email"`
	NotifyOnLogin        bool   `json:"notify_on_login"`
	NotifyOnRecharge     bool   `json:"notify_on_recharge"`
	NotifyOnTicket       bool   `json:"notify_on_ticket"`
}

type PaymentSettingsResponse struct {
	EnabledPaymentTypes []string         `json:"enabled_payment_types"`
	PaymentChannels     []PaymentChannel `json:"payment_channels"`
}

type PaymentChannel struct {
	ID     uint   `json:"id"`
	Name   string `json:"name"`
	Type   string `json:"type"`
	Icon   string `json:"icon"`
	Status string `json:"status"`
	Sort   int    `json:"sort"`
}

type EmailSettingsResponse struct {
	SMTPHost     string `json:"smtp_host"`
	SMTPPort     int    `json:"smtp_port"`
	SMTPUser     string `json:"smtp_user"`
	SMTPPassword string `json:"smtp_password"`
	SMTPFrom     string `json:"smtp_from"`
	Enabled      bool   `json:"enabled"`
}

func handleGetSystemSettings(c *gin.Context) {
	var settings []model.Setting
	database.DB.Where("category = ?", "system").Find(&settings)

	response := SystemSettingsResponse{
		SiteName:             "验证平台",
		SiteLogo:             "",
		SiteFavicon:          "",
		SiteFooter:           "",
		EnableCaptcha:        true,
		LoginFailLockCount:   5,
		LoginFailLockMinutes: 30,
		PasswordMinLength:    6,
		SessionTimeout:       24,
		EnableBackup:         false,
		BackupInterval:       24,
		BackupRetention:      7,
		BackupStorageType:    "local",
		EnableTicketSystem:   true,
		DefaultTheme:         "system",
		EnableMultiLang:      false,
		EnableNotification:   false,
		AdminNotifyEmail:     "",
		NotifyOnLogin:        false,
		NotifyOnRecharge:     true,
		NotifyOnTicket:       true,
	}

	for _, s := range settings {
		switch s.Key {
		case "site_name":
			response.SiteName = s.Value
		case "site_logo":
			response.SiteLogo = s.Value
		case "site_favicon":
			response.SiteFavicon = s.Value
		case "site_footer":
			response.SiteFooter = s.Value
		case "enable_captcha":
			response.EnableCaptcha = s.Value == "true"
		case "login_fail_lock_count":
			response.LoginFailLockCount = parseSettingInt(s.Value, 5)
		case "login_fail_lock_minutes":
			response.LoginFailLockMinutes = parseSettingInt(s.Value, 30)
		case "password_min_length":
			response.PasswordMinLength = parseSettingInt(s.Value, 6)
		case "session_timeout":
			response.SessionTimeout = parseSettingInt(s.Value, 24)
		case "enable_backup":
			response.EnableBackup = s.Value == "true"
		case "backup_interval":
			response.BackupInterval = parseSettingInt(s.Value, 24)
		case "backup_retention":
			response.BackupRetention = parseSettingInt(s.Value, 7)
		case "backup_storage_type":
			response.BackupStorageType = s.Value
		case "enable_ticket_system":
			response.EnableTicketSystem = s.Value == "true"
		case "default_theme":
			response.DefaultTheme = s.Value
		case "enable_multi_lang":
			response.EnableMultiLang = s.Value == "true"
		case "enable_notification":
			response.EnableNotification = s.Value == "true"
		case "admin_notify_email":
			response.AdminNotifyEmail = s.Value
		case "notify_on_login":
			response.NotifyOnLogin = s.Value == "true"
		case "notify_on_recharge":
			response.NotifyOnRecharge = s.Value == "true"
		case "notify_on_ticket":
			response.NotifyOnTicket = s.Value == "true"
		}
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"data": response,
	})
}

func parseSettingInt(value string, defaultValue int) int {
	if value == "" {
		return defaultValue
	}
	var result int
	if _, err := fmt.Sscanf(value, "%d", &result); err != nil {
		return defaultValue
	}
	return result
}

func handleUpdateSystemSettings(c *gin.Context) {
	var req SystemSettingsResponse
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的请求数据",
		})
		return
	}

	settings := []struct {
		Key   string
		Value string
	}{
		{"site_name", req.SiteName},
		{"site_logo", req.SiteLogo},
		{"site_favicon", req.SiteFavicon},
		{"site_footer", req.SiteFooter},
		{"enable_captcha", fmt.Sprintf("%v", req.EnableCaptcha)},
		{"login_fail_lock_count", fmt.Sprintf("%d", req.LoginFailLockCount)},
		{"login_fail_lock_minutes", fmt.Sprintf("%d", req.LoginFailLockMinutes)},
		{"password_min_length", fmt.Sprintf("%d", req.PasswordMinLength)},
		{"session_timeout", fmt.Sprintf("%d", req.SessionTimeout)},
		{"enable_backup", fmt.Sprintf("%v", req.EnableBackup)},
		{"backup_interval", fmt.Sprintf("%d", req.BackupInterval)},
		{"backup_retention", fmt.Sprintf("%d", req.BackupRetention)},
		{"backup_storage_type", req.BackupStorageType},
		{"enable_ticket_system", fmt.Sprintf("%v", req.EnableTicketSystem)},
		{"default_theme", req.DefaultTheme},
		{"enable_multi_lang", fmt.Sprintf("%v", req.EnableMultiLang)},
		{"enable_notification", fmt.Sprintf("%v", req.EnableNotification)},
		{"admin_notify_email", req.AdminNotifyEmail},
		{"notify_on_login", fmt.Sprintf("%v", req.NotifyOnLogin)},
		{"notify_on_recharge", fmt.Sprintf("%v", req.NotifyOnRecharge)},
		{"notify_on_ticket", fmt.Sprintf("%v", req.NotifyOnTicket)},
	}

	for _, s := range settings {
		var setting model.Setting
		result := database.DB.Where("category = ? AND key = ?", "system", s.Key).First(&setting)
		if result.Error == nil {
			setting.Value = s.Value
			database.DB.Save(&setting)
		} else {
			setting = model.Setting{
				Category: "system",
				Key:      s.Key,
				Value:    s.Value,
			}
			database.DB.Create(&setting)
		}
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "保存成功",
	})
}

func handleUploadSystemImage(c *gin.Context) {
	file, header, err := c.Request.FormFile("file")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "请选择要上传的文件",
		})
		return
	}
	defer file.Close()

	uploadType := c.PostForm("type")
	if uploadType != "logo" && uploadType != "favicon" {
		uploadType = "logo"
	}

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

	if !allowedExts[ext] {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "不支持的文件格式",
		})
		return
	}

	const maxSize = 2 * 1024 * 1024
	if header.Size > maxSize {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "文件大小不能超过2MB",
		})
		return
	}

	uploadDir := "uploads/system"
	if err := os.MkdirAll(uploadDir, 0755); err != nil {
		log.Printf("创建上传目录失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "创建上传目录失败",
		})
		return
	}

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

	dst, err := os.Create(filePath)
	if err != nil {
		log.Printf("创建文件失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "创建文件失败",
		})
		return
	}
	defer dst.Close()

	if _, err := io.Copy(dst, file); err != nil {
		log.Printf("保存文件失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "保存文件失败",
		})
		return
	}

	imageURL := "/uploads/system/" + filename

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"data": gin.H{
			"url": imageURL,
		},
	})
}

func handleGetPaymentSettings(c *gin.Context) {
	var channels []model.PaymentChannel
	database.DB.Order("sort asc").Find(&channels)

	var paymentChannels []PaymentChannel
	for _, ch := range channels {
		paymentChannels = append(paymentChannels, PaymentChannel{
			ID:     ch.ID,
			Name:   ch.Name,
			Type:   ch.Type,
			Icon:   ch.Icon,
			Status: ch.Status,
			Sort:   ch.Sort,
		})
	}

	var enabledTypes []string
	var setting model.Setting
	if err := database.DB.Where("category = ? AND key = ?", "payment", "enabled_types").First(&setting).Error; err == nil {
		if setting.Value != "" {
			enabledTypes = []string{setting.Value}
		}
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"data": gin.H{
			"enabled_payment_types": enabledTypes,
			"payment_channels":      paymentChannels,
		},
	})
}

func handleUpdatePaymentSettings(c *gin.Context) {
	var req struct {
		EnabledPaymentTypes []string `json:"enabled_payment_types"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的请求数据",
		})
		return
	}

	enabledTypes := ""
	if len(req.EnabledPaymentTypes) > 0 {
		enabledTypes = req.EnabledPaymentTypes[0]
	}

	var setting model.Setting
	result := database.DB.Where("category = ? AND key = ?", "payment", "enabled_types").First(&setting)
	if result.Error == nil {
		setting.Value = enabledTypes
		database.DB.Save(&setting)
	} else {
		setting = model.Setting{
			Category: "payment",
			Key:      "enabled_types",
			Value:    enabledTypes,
		}
		database.DB.Create(&setting)
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "保存成功",
	})
}

func handleGetEmailSettings(c *gin.Context) {
	var settings []model.Setting
	database.DB.Where("category = ?", "email").Find(&settings)

	response := EmailSettingsResponse{
		SMTPHost:     "",
		SMTPPort:     587,
		SMTPUser:     "",
		SMTPPassword: "",
		SMTPFrom:     "",
		Enabled:      false,
	}

	for _, s := range settings {
		switch s.Key {
		case "smtp_host":
			response.SMTPHost = s.Value
		case "smtp_port":
			var port int
			if _, err := fmt.Sscanf(s.Value, "%d", &port); err == nil {
				response.SMTPPort = port
			}
		case "smtp_user":
			response.SMTPUser = s.Value
		case "smtp_password":
			response.SMTPPassword = s.Value
		case "smtp_from":
			response.SMTPFrom = s.Value
		case "enabled":
			response.Enabled = s.Value == "true"
		}
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"data": response,
	})
}

func handleUpdateEmailSettings(c *gin.Context) {
	var req EmailSettingsRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的请求数据",
		})
		return
	}

	settings := []struct {
		Key   string
		Value string
	}{
		{"smtp_host", req.SMTPHost},
		{"smtp_port", fmt.Sprintf("%d", req.SMTPPort)},
		{"smtp_user", req.SMTPUser},
		{"smtp_password", req.SMTPPassword},
		{"smtp_from", req.SMTPFrom},
		{"enabled", fmt.Sprintf("%v", req.Enabled)},
	}

	for _, s := range settings {
		var setting model.Setting
		result := database.DB.Where("category = ? AND key = ?", "email", s.Key).First(&setting)
		if result.Error == nil {
			setting.Value = s.Value
			database.DB.Save(&setting)
		} else {
			setting = model.Setting{
				Category: "email",
				Key:      s.Key,
				Value:    s.Value,
			}
			database.DB.Create(&setting)
		}
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "保存成功",
	})
}

type EmailSettingsRequest struct {
	SMTPHost     string `json:"smtp_host"`
	SMTPPort     int    `json:"smtp_port"`
	SMTPUser     string `json:"smtp_user"`
	SMTPPassword string `json:"smtp_password"`
	SMTPFrom     string `json:"smtp_from"`
	Enabled      bool   `json:"enabled"`
}

func handleGetPaymentChannels(c *gin.Context) {
	var channels []model.PaymentChannel
	database.DB.Order("sort asc").Find(&channels)

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"data": channels,
	})
}

type CreatePaymentChannelRequest struct {
	Name   string `json:"name" binding:"required"`
	Type   string `json:"type" binding:"required"`
	Icon   string `json:"icon"`
	Config string `json:"config"`
	Sort   int    `json:"sort"`
	Remark string `json:"remark"`
}

func handleCreatePaymentChannel(c *gin.Context) {
	var req CreatePaymentChannelRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的请求数据",
		})
		return
	}

	channel := model.PaymentChannel{
		Name:   req.Name,
		Type:   req.Type,
		Icon:   req.Icon,
		Config: req.Config,
		Sort:   req.Sort,
		Status: "active",
		Remark: req.Remark,
	}

	if err := database.DB.Create(&channel).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "创建失败",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "创建成功",
		"data":    channel,
	})
}

func handleGetPaymentChannel(c *gin.Context) {
	id := c.Param("id")

	var channel model.PaymentChannel
	if err := database.DB.First(&channel, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "支付渠道不存在",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"data": channel,
	})
}

type UpdatePaymentChannelRequest struct {
	Name   string `json:"name"`
	Type   string `json:"type"`
	Icon   string `json:"icon"`
	Config string `json:"config"`
	Sort   int    `json:"sort"`
	Remark string `json:"remark"`
}

func handleUpdatePaymentChannel(c *gin.Context) {
	id := c.Param("id")

	var channel model.PaymentChannel
	if err := database.DB.First(&channel, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "支付渠道不存在",
		})
		return
	}

	var req UpdatePaymentChannelRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的请求数据",
		})
		return
	}

	if req.Name != "" {
		channel.Name = req.Name
	}
	if req.Type != "" {
		channel.Type = req.Type
	}
	channel.Icon = req.Icon
	channel.Config = req.Config
	channel.Sort = req.Sort
	channel.Remark = req.Remark

	if err := database.DB.Save(&channel).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "更新失败",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "更新成功",
		"data":    channel,
	})
}

func handleDeletePaymentChannel(c *gin.Context) {
	id := c.Param("id")

	var channel model.PaymentChannel
	if err := database.DB.First(&channel, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "支付渠道不存在",
		})
		return
	}

	if err := database.DB.Delete(&channel).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "删除失败",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "删除成功",
	})
}

type UpdatePaymentChannelStatusRequest struct {
	Status string `json:"status" binding:"required"`
}

func handleUpdatePaymentChannelStatus(c *gin.Context) {
	id := c.Param("id")

	var channel model.PaymentChannel
	if err := database.DB.First(&channel, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "支付渠道不存在",
		})
		return
	}

	var req UpdatePaymentChannelStatusRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的请求数据",
		})
		return
	}

	channel.Status = req.Status
	if err := database.DB.Save(&channel).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "更新失败",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "更新成功",
	})
}

type BatchUpdatePaymentChannelStatusRequest struct {
	IDs    []uint `json:"ids"`
	Status string `json:"status"`
}

func handleBatchUpdatePaymentChannelStatus(c *gin.Context) {
	var req BatchUpdatePaymentChannelStatusRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "参数错误",
		})
		return
	}

	if req.Status != "active" && req.Status != "inactive" {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的状态",
		})
		return
	}

	if len(req.IDs) == 0 {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "请选择要更新的支付渠道",
		})
		return
	}

	if err := database.DB.Model(&model.PaymentChannel{}).Where("id IN ?", req.IDs).Update("status", req.Status).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "批量更新失败",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "批量更新成功",
	})
}

type BatchDeletePaymentChannelsRequest struct {
	IDs []uint `json:"ids"`
}

func handleBatchDeletePaymentChannels(c *gin.Context) {
	var req BatchDeletePaymentChannelsRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "参数错误",
		})
		return
	}

	if len(req.IDs) == 0 {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "请选择要删除的支付渠道",
		})
		return
	}

	if err := database.DB.Where("id IN ?", req.IDs).Delete(&model.PaymentChannel{}).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "批量删除失败",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "批量删除成功",
	})
}
