package handler

import (
	"net/http"
	"os"
	"os/exec"
	"time"

	"git.zkcoi.com/zkcoi/meshray/internal/service"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

// SystemConfigHandler 系统配置处理器
type SystemConfigHandler struct {
	configService *service.SystemConfigService
	logger        *zap.Logger
}

// NewSystemConfigHandler 创建系统配置处理器
func NewSystemConfigHandler(configService *service.SystemConfigService, logger *zap.Logger) *SystemConfigHandler {
	return &SystemConfigHandler{
		configService: configService,
		logger:        logger,
	}
}

// GetWGMode 获取当前 WG 运行模式
// @Summary 获取当前 WG 运行模式
// @Tags system-config
// @Accept json
// @Produce json
// @Success 200 {object} object{wg_mode=string,wg_mode_display=string,actual_mode=string}
// @Router /api/v1/system-config/wg-mode [get]
func (h *SystemConfigHandler) GetWGMode(c *gin.Context) {
	// 获取配置的模式（用户设置）
	configMode, err := h.configService.GetWGMode()
	if err != nil {
		h.logger.Error("获取 WG 配置失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取失败"})
		return
	}

	// ✅ 固定使用用户态模式
	actualMode := "userspace"
	h.logger.Debug("WG 模式：固定使用 wireguard-go 用户态")

	c.JSON(http.StatusOK, gin.H{
		"wg_mode":         configMode,                 // 配置的模式（已废弃，保留兼容）
		"wg_mode_display": getModeDisplay(actualMode), // 实际运行的模式显示
		"actual_mode":     actualMode,                 // 实际运行的模式代码
	})
}

// getModeDisplay 获取模式的中文显示
func getModeDisplay(mode string) string {
	switch mode {
	case "kernel":
		return "内核态"
	case "userspace":
		return "用户态"
	default:
		return mode
	}
}

// SetWGMode 设置 WG 运行模式
// @Summary 设置 WG 运行模式（需要重启 MeshRay 才能生效）
// @Tags system-config
// @Accept json
// @Produce json
// @Param mode body object{mode string} true "WG 模式 (auto|kernel|userspace)"
// @Success 200 {object} object{message=string}
// @Router /api/v1/system-config/wg-mode [put]
func (h *SystemConfigHandler) SetWGMode(c *gin.Context) {
	var req struct {
		Mode string `json:"mode"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数错误"})
		return
	}

	if err := h.configService.SetWGMode(req.Mode); err != nil {
		h.logger.Error("设置 WG 模式失败", zap.Error(err))
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	h.logger.Info("WG 模式已更新，需要重启 MeshRay 才能生效", zap.String("mode", req.Mode))
	c.JSON(http.StatusOK, gin.H{
		"message": "设置成功，请重启 MeshRay 使新配置生效",
		"wg_mode": req.Mode,
	})
}

// ==================== 系统运维功能（P1/P2） ====================

// ChangePasswordRequest 修改密码请求
type ChangePasswordRequest struct {
	OldPassword string `json:"old_password"`
	NewPassword string `json:"new_password"`
}

// ChangePassword 修改密码（P1）
func (h *SystemConfigHandler) ChangePassword(c *gin.Context) {
	var req ChangePasswordRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数错误"})
		return
	}

	// 验证密码长度
	if len(req.NewPassword) < 6 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "密码至少 6 个字符"})
		return
	}

	// 从上下文获取用户 ID
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "未认证"})
		return
	}

	// 调用服务层修改密码
	err := h.configService.ChangePassword(userID.(uint), req.OldPassword, req.NewPassword)
	if err != nil {
		h.logger.Error("修改密码失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	h.logger.Info("密码修改成功", zap.Uint("user_id", userID.(uint)))
	c.JSON(http.StatusOK, gin.H{"message": "密码修改成功"})
}

// RestartCoreRequest 重启核心服务请求
type RestartCoreRequest struct {
	Graceful bool `json:"graceful"` // 是否优雅重启
}

// RestartCore 重启核心服务（P1 - Windows 下通过重启进程实现）
func (h *SystemConfigHandler) RestartCore(c *gin.Context) {
	var req RestartCoreRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数错误"})
		return
	}

	h.logger.Info("收到重启核心服务请求", zap.Bool("graceful", req.Graceful))

	// 获取当前可执行文件路径
	execPath, err := os.Executable()
	if err != nil {
		h.logger.Error("获取可执行文件路径失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "无法获取程序路径"})
		return
	}

	// 在后台启动新进程
	cmd := exec.Command(execPath)
	if err := cmd.Start(); err != nil {
		h.logger.Error("启动新进程失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "重启失败"})
		return
	}

	// 延迟退出，让新进程有时间启动
	go func() {
		time.Sleep(2 * time.Second)
		os.Exit(0)
	}()

	h.logger.Info("核心服务将在 2 秒后重启")
	c.JSON(http.StatusOK, gin.H{"message": "核心服务正在重启..."})
}
