package handler

import (
	"net/http"
	"strconv"
	"strings"
	"time"

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

// NetworkHandler 网络管理 Handler
type NetworkHandler struct {
	networkService  *service.NetworkService
	meshSeedService *service.MeshSeedService // 新增：MeshSeed 服务
	store           *sqlite.Store            // 新增：用于存储 PendingJoin
	logger          *zap.Logger
}

// NewNetworkHandler 创建 Network Handler
func NewNetworkHandler(networkService *service.NetworkService, meshSeedService *service.MeshSeedService, store *sqlite.Store, logger *zap.Logger) *NetworkHandler {
	return &NetworkHandler{
		networkService:  networkService,
		meshSeedService: meshSeedService,
		store:           store,
		logger:          logger,
	}
}

// CreateNetworkResponse 创建网络响应（包含完整配置信息）
type CreateNetworkResponse struct {
	*model.Network
	STUNServers []model.Service `json:"stun_servers"`          // STUN 服务器列表
	TURNServers []model.Service `json:"turn_servers"`          // TURN 服务器列表
	DDNSConfig  *DDNSConfigInfo `json:"ddns_config,omitempty"` // DDNS 配置信息（如果启用）
}

// DDNSConfigInfo DDNS 配置信息
type DDNSConfigInfo struct {
	Provider   string `json:"provider"`    // 服务商
	Domain     string `json:"domain"`      // 域名
	RecordType string `json:"record_type"` // 记录类型
	Prefix     string `json:"prefix"`      // 前缀
}

// CreateNetwork 创建网络
// @Summary 创建新的 WireGuard 网络
// @Tags networks
// @Accept json
// @Produce json
// @Param network body model.Network true "网络配置"
// @Success 200 {object} CreateNetworkResponse
// @Router /api/v1/networks [post]
func (h *NetworkHandler) CreateNetwork(c *gin.Context) {
	var req model.Network
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数错误"})
		return
	}

	// 使用 Service 层创建网络
	network, err := h.networkService.CreateNetwork(&req)
	if err != nil {
		h.logger.Error("创建网络失败", zap.Error(err))
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// 查询关联的 STUN/TURN 服务器
	var stunServers []model.Service
	h.store.DB().Where("type = 'STUN' AND enabled = true").Find(&stunServers)

	var turnServers []model.Service
	h.store.DB().Where("type = 'TURN' AND enabled = true").Find(&turnServers)

	// 构建响应
	resp := &CreateNetworkResponse{
		Network:     network,
		STUNServers: stunServers,
		TURNServers: turnServers,
	}

	// 如果启用了 DDNS，查询 DDNS 配置
	if network.DDNSEnabled && network.DDNSServiceID != "" {
		var ddnsService model.Service
		if err := h.store.DB().First(&ddnsService, network.DDNSServiceID).Error; err == nil {
			resp.DDNSConfig = &DDNSConfigInfo{
				Provider:   ddnsService.Provider,
				Domain:     ddnsService.Domain,
				RecordType: ddnsService.RecordType,
				Prefix:     network.DDNSPrefix,
			}
		}
	}

	h.logger.Info("网络创建成功",
		zap.String("name", network.Name),
		zap.Uint64("id", network.ID),
		zap.Int("stun_count", len(stunServers)),
		zap.Int("turn_count", len(turnServers)))

	c.JSON(http.StatusOK, gin.H{
		"message": "网络创建成功",
		"data":    resp,
	})
}

// GetNetwork 获取网络详情
// @Summary 获取网络详细信息
// @Tags networks
// @Accept json
// @Produce json
// @Param id path string true "网络 ID"
// @Success 200 {object} model.Network
// @Router /api/v1/networks/:id [get]
func (h *NetworkHandler) GetNetwork(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 层获取网络
	network, err := h.networkService.GetNetwork(id)
	if err != nil {
		h.logger.Error("获取网络失败", zap.Error(err))
		c.JSON(http.StatusNotFound, gin.H{"error": "网络不存在"})
		return
	}

	// 使用 DTO 转换
	resp := dto.ToNetworkResponse(network)

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

// ListNetworks 获取网络列表
// @Summary 获取所有网络列表
// @Tags networks
// @Accept json
// @Produce json
// @Success 200 {array} model.Network
// @Router /api/v1/networks [get]
// ListNetworks 获取网络列表
func (h *NetworkHandler) ListNetworks(c *gin.Context) {
	networks, err := h.networkService.ListNetworks()
	if err != nil {
		h.logger.Error("查询网络列表失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "查询失败"})
		return
	}

	// 使用 DTO 批量转换
	respList := dto.ToNetworkResponseList(networks)

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

// DeleteNetwork 删除网络
// @Summary 删除指定网络
// @Tags networks
// @Accept json
// @Produce json
// @Param id path string true "网络 ID"
// @Success 200
// @Router /api/v1/networks/:id [delete]
func (h *NetworkHandler) DeleteNetwork(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
	}

	// 获取是否强制级联删除
	force := c.Query("force") == "true"

	// 使用 Service 层删除网络
	err = h.networkService.DeleteNetwork(id, force)
	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": "删除成功",
	})
}

// UpdateNetwork 更新网络
// @Summary 更新网络信息
// @Tags networks
// @Accept json
// @Produce json
// @Param id path string true "网络 ID"
// @Param network body model.Network true "网络配置"
// @Success 200 {object} model.Network
// @Router /api/v1/networks/:id [put]
func (h *NetworkHandler) UpdateNetwork(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 model.Network
	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.SubnetIPv4 != "" {
		updates["subnetIPv4"] = req.SubnetIPv4
	}
	if req.SubnetIPv6 != "" {
		updates["subnetIPv6"] = req.SubnetIPv6
	}
	if req.Mode != "" {
		updates["mode"] = req.Mode
	}
	updates["dhcpEnabled"] = req.DHCPEnabled

	// 使用 Service 层更新
	network, err := h.networkService.UpdateNetwork(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", id))
	c.JSON(http.StatusOK, gin.H{
		"message": "更新成功",
		"data":    network,
	})
}

// StartNetwork 启动网络（创建 WG 设备）
// @Summary 启动网络
// @Tags networks
// @Accept json
// @Produce json
// @Param id path string true "网络 ID"
// @Success 200
// @Router /api/v1/networks/:id/start [post]
func (h *NetworkHandler) StartNetwork(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.networkService.StartNetwork(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": "启动成功",
	})
}

// StopNetwork 停止网络
// @Summary 停止网络
// @Tags networks
// @Accept json
// @Produce json
// @Param id path string true "网络 ID"
// @Success 200
// @Router /api/v1/networks/:id/stop [post]
func (h *NetworkHandler) StopNetwork(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.networkService.StopNetwork(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": "停止成功",
	})
}

// SwitchMode 切换组网模式
// @Summary 切换组网模式
// @Tags networks
// @Accept json
// @Produce json
// @Param id path string true "网络 ID"
// @Param mode body object{mesh_mode string} true "组网模式 (native|enhanced)"
// @Success 200
// @Router /api/v1/networks/:id/switch-mode [post]
func (h *NetworkHandler) SwitchMode(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 {
		MeshMode string `json:"mesh_mode"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数错误"})
		return
	}

	// 使用 Service 层切换模式
	err = h.networkService.SwitchMode(id, req.MeshMode)
	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), zap.String("mesh_mode", req.MeshMode))
	c.JSON(http.StatusOK, gin.H{
		"message": "切换成功",
	})
}

// GenerateMeshSeed 生成 MeshSeed
// @Summary 生成 MeshSeed
// @Tags networks
// @Accept json
// @Produce json
// @Param id path string true "网络 ID"
// @Param params body object true "生成参数"
// @Success 200
// @Router /api/v1/networks/:id/meshseed [post]
func (h *NetworkHandler) GenerateMeshSeed(c *gin.Context) {
	idStr := c.Param("id")
	networkID, 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 {
		ExpiresInHours int  `json:"expires_in_hours"`
		MaxUses        int  `json:"max_uses"`
		DDNSEnabled    bool `json:"ddns_enabled"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数错误"})
		return
	}

	// 默认值
	if req.ExpiresInHours <= 0 {
		req.ExpiresInHours = 24 // 默认 24 小时
	}
	if req.MaxUses <= 0 {
		req.MaxUses = 10 // 默认 10 次
	}

	// 计算过期时间
	expiresAt := time.Now().Add(time.Duration(req.ExpiresInHours) * time.Hour)

	// 调用 MeshSeedService 生成真实的 MeshSeed
	meshSeed, err := h.meshSeedService.GenerateMeshSeed(networkID, req.MaxUses, expiresAt, req.DDNSEnabled)
	if err != nil {
		h.logger.Error("生成 MeshSeed 失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// 返回完整的 MeshSeed URL（包含 JoinToken 和 Signature）
	seedString := "meshray://" + meshSeed.JoinToken + "." + meshSeed.Signature
	c.JSON(http.StatusOK, gin.H{
		"data": gin.H{
			"seed_string":    seedString,
			"expires_at":     meshSeed.ExpiresAt.Format(time.RFC3339),
			"max_uses":       meshSeed.MaxUses,
			"ddns_enabled":   meshSeed.DDNSEnabled,
			"used_count":     meshSeed.UsedCount,
			"revoked":        meshSeed.Revoked,
			"issued_at":      time.Now().Format(time.RFC3339),
			"remaining_uses": meshSeed.MaxUses - meshSeed.UsedCount,
		},
	})
}

// PreviewMeshSeed 预览 MeshSeed 信息
// @Summary 预览 MeshSeed
// @Tags networks
// @Accept json
// @Produce json
// @Param req body object{seed string} true "MeshSeed 字符串"
// @Success 200
// @Router /api/v1/networks/preview [post]
func (h *NetworkHandler) PreviewMeshSeed(c *gin.Context) {
	var req struct {
		Seed string `json:"seed"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数错误"})
		return
	}

	// 解析 seed_string
	// 格式: meshray://<joinToken>.<signature>
	const prefix = "meshray://"
	if len(req.Seed) <= len(prefix) || string(req.Seed[:len(prefix)]) != prefix {
		c.JSON(http.StatusBadRequest, gin.H{"error": "MeshSeed 格式不正确"})
		return
	}

	seedContent := req.Seed[len(prefix):]
	parts := strings.SplitN(seedContent, ".", 2)
	if len(parts) != 2 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "MeshSeed 内容不完整"})
		return
	}
	joinToken, signature := parts[0], parts[1]

	meshSeed, err := h.meshSeedService.VerifyMeshSeed(joinToken, signature)
	if err != nil {
		h.logger.Error("MeshSeed 验证失败", zap.Error(err))
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// 查询网络名称和信息
	network, err := h.networkService.GetNetworkByID(meshSeed.NetworkID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取网络信息失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"data": gin.H{
			"name":        network.Name,
			"subnet_ipv4": network.SubnetIPv4,
			"mesh_mode":   network.Mode,
			// 在该应用逻辑中，如果是基于 MeshSeed 加入的设备默认进入待审核状态
			"require_approval": true,
		},
	})
}

// JoinNetwork 加入网络
// @Summary 加入网络
// @Tags networks
// @Accept json
// @Produce json
// @Param req body object{seed string, device_name string, message string} true "请求参数"
// @Success 200
// @Router /api/v1/networks/join [post]
func (h *NetworkHandler) JoinNetwork(c *gin.Context) {
	var req struct {
		Seed       string `json:"seed"`
		DeviceName string `json:"device_name"`
		Message    string `json:"message"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数错误"})
		return
	}

	const prefix = "meshray://"
	if len(req.Seed) <= len(prefix) || string(req.Seed[:len(prefix)]) != prefix {
		c.JSON(http.StatusBadRequest, gin.H{"error": "MeshSeed 格式不正确"})
		return
	}

	seedContent := req.Seed[len(prefix):]
	parts := strings.SplitN(seedContent, ".", 2)
	if len(parts) != 2 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "MeshSeed 内容不完整"})
		return
	}
	joinToken, signature := parts[0], parts[1]

	meshSeed, err := h.meshSeedService.VerifyMeshSeed(joinToken, signature)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// 记录一次使用次数
	if err := h.meshSeedService.IncrementUseCount(meshSeed.SeedID); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "处理失败"})
		return
	}

	// 在目前的 handler 这里，直接通过 store 存储记录
	pendingJoin := &model.PendingJoin{
		SeedID:     meshSeed.SeedID,
		DeviceName: req.DeviceName,
		RequestIP:  c.ClientIP(),
		Status:     "pending",
		ExpireAt:   time.Now().Add(72 * time.Hour), // 72小时过期
	}

	// 存入数据库
	db := h.store.DB()
	if db != nil {
		db.Create(pendingJoin)
	}

	c.JSON(http.StatusOK, gin.H{
		"message": "申请已提交，等待管理员审核",
		"data": gin.H{
			"success":      true,
			"needApproval": true,
		},
	})
}
