package handler

import (
	"net/http"
	"strconv"

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

// DeviceHandler 设备管理 Handler
type DeviceHandler struct {
	deviceService *service.DeviceService
	logger        *zap.Logger
}

// NewDeviceHandler 创建设备处理器
func NewDeviceHandler(deviceService *service.DeviceService, logger *zap.Logger) *DeviceHandler {
	return &DeviceHandler{
		deviceService: deviceService,
		logger:        logger,
	}
}

// CreateDevice 创建设备
// @Summary 在指定网络下创建设备
// @Tags devices
// @Accept json
// @Produce json
// @Param network_id path int true "网络 ID"
// @Param device body model.Device true "设备配置"
// @Success 200 {object} model.Device
// @Router /api/v1/networks/:network_id/devices [post]
func (h *DeviceHandler) CreateDevice(c *gin.Context) {
	// 从 Query 参数获取 network_id
	networkIDStr := c.Query("network_id")
	networkID, err := strconv.ParseUint(networkIDStr, 10, 64)
	if err != nil {
		h.logger.Error("解析网络 ID 失败", zap.Error(err))
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的网络 ID"})
		return
	}

	var req service.CreateDeviceRequest
	req.NetworkID = networkID
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数错误"})
		return
	}

	// 使用 Service 层创建设备（返回完整配置）
	result, err := h.deviceService.CreateDevice(&req)
	if err != nil {
		h.logger.Error("创建设备失败", zap.Error(err))
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	h.logger.Info("设备创建成功",
		zap.Uint64("id", result.Device.ID),
		zap.String("name", result.Device.Name),
		zap.Uint64("network_id", result.Device.NetworkID))

	// 返回完整配置（包含私钥和 WG 配置）
	c.JSON(http.StatusOK, gin.H{
		"message": "设备创建成功",
		"data": gin.H{
			"device":           result.Device,
			"private_key":      result.PrivateKey,
			"wireguard_config": result.ConfigText,
		},
	})
}

// GetDevice 获取设备详情
// @Summary 获取设备详细信息
// @Tags devices
// @Accept json
// @Produce json
// @Param id path int true "设备 ID"
// @Success 200 {object} model.Device
// @Router /api/v1/devices/:id [get]
// GetDevice 获取设备详情
func (h *DeviceHandler) GetDevice(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 64)
	if err != nil {
		h.logger.Error("解析设备 ID 失败", zap.Error(err))
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的设备 ID"})
		return
	}

	device, err := h.deviceService.GetDevice(id)
	if err != nil {
		h.logger.Error("获取设备失败", zap.Error(err))
		c.JSON(http.StatusNotFound, gin.H{"error": "设备不存在"})
		return
	}

	// 使用 DTO 转换
	resp := dto.ToDeviceResponse(device)

	c.JSON(http.StatusOK, gin.H{
		"data": resp,
	})
}

// ListDevices 获取设备列表
// @Summary 获取指定网络下的设备列表
// @Tags devices
// @Accept json
// @Produce json
// @Param network_id path int true "网络 ID"
// @Success 200 {array} model.Device
// @Router /api/v1/networks/:network_id/devices [get]
// ListDevices 获取设备列表
func (h *DeviceHandler) ListDevices(c *gin.Context) {
	networkIDStr := c.Query("network_id")

	var devices []model.Device
	var err error

	if networkIDStr != "" {
		networkID, err := strconv.ParseUint(networkIDStr, 10, 64)
		if err != nil {
			h.logger.Error("解析网络 ID 失败", zap.Error(err))
			c.JSON(http.StatusBadRequest, gin.H{"error": "无效的网络 ID"})
			return
		}
		devices, err = h.deviceService.ListDevicesByNetwork(networkID)
	} else {
		devices, err = h.deviceService.ListAllDevices()
	}
	if err != nil {
		h.logger.Error("查询设备列表失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "查询失败"})
		return
	}

	// 使用 DTO 批量转换
	respList := dto.ToDeviceResponseList(devices)

	c.JSON(http.StatusOK, gin.H{
		"data": respList,
	})
}

// UpdateDevice 更新设备
// @Summary 更新设备信息
// @Tags devices
// @Accept json
// @Produce json
// @Param id path int true "设备 ID"
// @Param device body model.Device true "设备配置"
// @Success 200 {object} model.Device
// @Router /api/v1/devices/:id [put]
func (h *DeviceHandler) UpdateDevice(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 64)
	if err != nil {
		h.logger.Error("解析设备 ID 失败", zap.Error(err))
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的设备 ID"})
		return
	}

	var req struct {
		Name      string `json:"name"`
		VirtualIP string `json:"virtual_ip"`
		Status    string `json:"status"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数错误"})
		return
	}

	// 构建更新字段
	updates := make(map[string]interface{})
	if req.Name != "" {
		updates["name"] = req.Name
	}
	if req.VirtualIP != "" {
		updates["virtual_ip"] = req.VirtualIP
	}
	if req.Status != "" {
		updates["status"] = req.Status
	}

	// 使用 Service 层更新
	device, err := h.deviceService.UpdateDevice(id, updates)
	if err != nil {
		h.logger.Error("更新设备失败", zap.Error(err))
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	h.logger.Info("设备更新成功", zap.Uint64("id", device.ID))
	c.JSON(http.StatusOK, gin.H{
		"message": "更新成功",
		"data":    device,
	})
}

// DeleteDevice 删除设备
// @Summary 删除指定设备
// @Tags devices
// @Accept json
// @Produce json
// @Param id path int true "设备 ID"
// @Success 200
// @Router /api/v1/devices/:id [delete]
func (h *DeviceHandler) DeleteDevice(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 64)
	if err != nil {
		h.logger.Error("解析设备 ID 失败", zap.Error(err))
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的设备 ID"})
		return
	}

	// 使用 Service 层删除
	err = h.deviceService.DeleteDevice(id)
	if err != nil {
		h.logger.Error("删除设备失败", zap.Error(err))
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	h.logger.Info("设备已删除", zap.Uint64("id", id))
	c.JSON(http.StatusOK, gin.H{
		"message": "删除成功",
	})
}

// GenerateDeviceConfig 生成设备配置文件
// @Summary 生成 WireGuard 设备配置
// @Tags devices
// @Accept json
// @Produce json
// @Param id path int true "设备 ID"
// @Success 200 {string} string "配置文件内容"
// @Router /api/v1/devices/:id/config [get]
func (h *DeviceHandler) GenerateDeviceConfig(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 64)
	if err != nil {
		h.logger.Error("解析设备 ID 失败", zap.Error(err))
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的设备 ID"})
		return
	}

	// 调用 Service 层生成配置（包含密钥生成）
	config, err := h.deviceService.GenerateDeviceConfig(id)
	if err != nil {
		h.logger.Error("生成配置失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.Data(http.StatusOK, "text/plain", []byte(config))
}
