package admin

import (
	"NetworkAuth/config"
	"NetworkAuth/models"
	"NetworkAuth/services"
	"NetworkAuth/utils"
	"fmt"
	"net/http"
	"strconv"

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

// SubAccountSimpleListHandler 子账号简单列表API处理器 (Mock)
func SubAccountSimpleListHandler(c *gin.Context) {
	// Mock implementation for NetworkAuth which has no subaccounts
	c.JSON(http.StatusOK, gin.H{
		"code": 0,
		"msg":  "success",
		"data": []interface{}{},
	})
}

// SettingsQueryHandler 设置查询API
// - 返回所有设置项的 name:value 映射
func SettingsQueryHandler(c *gin.Context) {
	db, ok := authBaseController.GetDB(c)
	if !ok {
		return
	}

	var list []models.Settings
	if err := db.Find(&list).Error; err != nil {
		authBaseController.HandleInternalError(c, "查询失败", err)
		return
	}
	res := map[string]string{}
	for _, s := range list {
		res[s.Name] = s.Value
	}
	authBaseController.HandleSuccess(c, "ok", res)
}

// SettingsUpdateHandler 更新系统设置处理器
// - 接收JSON格式的设置数据，支持两种格式：
//  1. 直接字段格式: {"site_title": "值", "site_keywords": "值"}
//  2. 嵌套格式: {"settings": {"site_title": "值", "site_keywords": "值"}}
//
// - 自动创建不存在的设置项
// - 更新已存在的设置项
// - 更新完成后：
//  1. 删除对应的Redis缓存键，确保后续读取走数据库并重建缓存
//  2. 刷新SettingsService内存缓存
func SettingsUpdateHandler(c *gin.Context) {
	// 先尝试解析为直接字段格式
	var directBody map[string]interface{}
	if err := c.ShouldBindJSON(&directBody); err != nil {
		authBaseController.HandleValidationError(c, "请求体错误")
		return
	}

	var categoryStr string
	if category, ok := directBody["category"].(string); ok {
		categoryStr = category
	}

	// 提取设置数据
	var settingsData map[string]string

	// 检查是否为嵌套格式（包含settings字段）
	if settings, exists := directBody["settings"]; exists {
		if settingsMap, ok := settings.(map[string]interface{}); ok {
			settingsData = make(map[string]string)
			for k, v := range settingsMap {
				if str, ok := v.(string); ok {
					settingsData[k] = str
				}
			}
		} else {
			authBaseController.HandleValidationError(c, "settings字段格式错误")
			return
		}
	} else {
		// 直接字段格式
		settingsData = make(map[string]string)
		for k, v := range directBody {
			if k == "category" {
				continue // 忽略 category 字段，不保存到设置表
			}
			if str, ok := v.(string); ok {
				settingsData[k] = str
			} else if v != nil {
				// 转换其他类型为字符串
				settingsData[k] = fmt.Sprintf("%v", v)
			}
		}
	}

	if len(settingsData) == 0 {
		authBaseController.HandleValidationError(c, "无设置项")
		return
	}

	// 验证设置项值
	for k, v := range settingsData {
		if err := validateSettingValue(k, v); err != nil {
			authBaseController.HandleValidationError(c, err.Error())
			return
		}
	}

	db, ok := authBaseController.GetDB(c)
	if !ok {
		return
	}

	// 记录需要失效的缓存键，统一删除，减少与Redis交互次数
	keysToDel := make([]string, 0, len(settingsData))

	// 批量处理设置项
	for k, v := range settingsData {
		var s models.Settings
		if err := db.Where("name = ?", k).First(&s).Error; err != nil {
			// 不存在则创建
			s = models.Settings{Name: k, Value: v}
			if err := db.Create(&s).Error; err != nil {
				logrus.WithError(err).WithField("setting_name", k).Error("创建设置失败")
				authBaseController.HandleInternalError(c, fmt.Sprintf("保存设置 %s 失败", k), err)
				return
			}

		} else {
			// 存在则更新
			if err := db.Model(&models.Settings{}).Where("id = ?", s.ID).Update("value", v).Error; err != nil {
				logrus.WithError(err).WithField("setting_name", k).Error("更新设置失败")
				authBaseController.HandleInternalError(c, fmt.Sprintf("更新设置 %s 失败", k), err)
				return
			}

		}
		// 收集对应的Redis缓存键（与services/query.go中的键命名保持一致）
		keysToDel = append(keysToDel, fmt.Sprintf("setting:%s", k))
	}

	// 删除Redis缓存键（如果Redis不可用则静默跳过）
	_ = utils.RedisDel(c.Request.Context(), keysToDel...)

	// 刷新内存中的设置缓存，保证后续读取一致
	services.GetSettingsService().RefreshCache()

	// 获取当前操作人信息
	claims, _, err := GetCurrentAdminUserWithRefresh(c)
	var operator, operatorUUID string
	if err == nil && claims != nil {
		operator = claims.Username
		operatorUUID = claims.UUID
	} else {
		operator = "system"
	}

	// 解析详细的子分类日志名称
	categoryNameMap := map[string]string{
		"basic":    "基本信息",
		"security": "系统和安全",
		"log":      "日志清理",
		"cookie":   "Cookie 设置",
		"footer":   "页脚与备案",
		"style":    "模板样式",
	}

	// 记录操作日志
	logType := "系统设置"
	if categoryStr != "" {
		if mappedName, exists := categoryNameMap[categoryStr]; exists {
			logType = fmt.Sprintf("系统设置-%s", mappedName)
		} else {
			logType = fmt.Sprintf("系统设置-%s", categoryStr)
		}
	}
	services.RecordOperationLog(logType, operator, operatorUUID, fmt.Sprintf("管理员更新了系统设置，包含 %d 个配置项", len(settingsData)))

	authBaseController.HandleSuccess(c, "保存成功", nil)
}

// validateSettingValue 验证设置项值的合法性
func validateSettingValue(key, value string) error {
	switch key {
	case "jwt_refresh":
		// 验证JWT刷新时间：至少1小时
		hours, err := strconv.Atoi(value)
		if err != nil {
			return fmt.Errorf("JWT刷新阈值必须是整数")
		}
		if hours < 1 {
			return fmt.Errorf("JWT刷新阈值必须至少为1小时")
		}
	case "jwt_expire":
		// 验证JWT有效期：至少1小时
		hours, err := strconv.Atoi(value)
		if err != nil {
			return fmt.Errorf("JWT有效期必须是整数")
		}
		if hours < 1 {
			return fmt.Errorf("JWT有效期必须至少为1小时")
		}
	}
	return nil
}

// SettingsGenerateKeyHandler 生成安全密钥API
// - type: "jwt" 或 "encryption"
func SettingsGenerateKeyHandler(c *gin.Context) {
	keyType := c.Query("type")
	var key string
	var err error

	switch keyType {
	case "jwt":
		key, err = config.GenerateSecureJWTSecret()
	case "encryption":
		key, err = config.GenerateSecureEncryptionKey()
	default:
		authBaseController.HandleValidationError(c, "无效的密钥类型")
		return
	}

	if err != nil {
		authBaseController.HandleInternalError(c, "生成密钥失败: "+err.Error(), err)
		return
	}

	authBaseController.HandleSuccess(c, "生成成功", map[string]string{"key": key})
}

// SettingsPublicHandler 公开设置查询API
// - 仅返回允许公开的设置项以及所有前端平台配置
func SettingsPublicHandler(c *gin.Context) {
	db, ok := authBaseController.GetDB(c)
	if !ok {
		return
	}

	var list []models.Settings
	// 查询公开的基本信息、维护模式和所有前端平台配置
	if err := db.Where("name IN ? OR name LIKE ?", []string{
		"site_title",
		"site_description",
		"site_keywords",
		"site_logo",
		"contact_email",
		"maintenance_mode",
		"footer_text",
		"icp_record",
		"icp_record_link",
		"psb_record",
		"psb_record_link",
	}, "platform_%").Find(&list).Error; err != nil {
		authBaseController.HandleInternalError(c, "查询失败", err)
		return
	}
	res := map[string]string{}
	for _, s := range list {
		res[s.Name] = s.Value
	}
	authBaseController.HandleSuccess(c, "ok", res)
}
