package handler

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

	"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"
)

// PendingJoinHandler 待审核 Handler
type PendingJoinHandler struct {
	service *service.PendingJoinService
	store   *sqlite.Store // ← 新增
	logger  *zap.Logger
}

// NewPendingJoinHandler 创建待审核 Handler
func NewPendingJoinHandler(service *service.PendingJoinService, store *sqlite.Store, logger *zap.Logger) *PendingJoinHandler {
	return &PendingJoinHandler{
		service: service,
		store:   store, // ← 新增
		logger:  logger,
	}
}

// ListPendingJoins 获取待审核列表
func (h *PendingJoinHandler) ListPendingJoins(c *gin.Context) {
	// 获取查询参数
	networkIDStr := c.DefaultQuery("network_id", "0")
	status := c.DefaultQuery("status", "pending")
	pageStr := c.DefaultQuery("page", "1")
	sizeStr := c.DefaultQuery("size", "20")

	// 转换参数
	networkID, _ := strconv.ParseUint(networkIDStr, 10, 32)
	page, _ := strconv.Atoi(pageStr)
	size, _ := strconv.Atoi(sizeStr)

	if page < 1 {
		page = 1
	}
	if size < 1 || size > 100 {
		size = 20
	}

	// 调用 Service
	list, total, err := h.service.ListPendingJoins(uint(networkID), status, page, size)
	if err != nil {
		h.logger.Error("获取待审核列表失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取失败"})
		return
	}

	// 转换为响应格式
	type ResponseItem struct {
		ID          uint   `json:"id"`
		SeedID      string `json:"seed_id"`
		DeviceName  string `json:"device_name"`
		RequestIP   string `json:"request_ip"`
		Status      string `json:"status"`
		ExpireAt    string `json:"expire_at"`
		ApprovedAt  string `json:"approved_at"`
		RejectedAt  string `json:"rejected_at"`
		Reason      string `json:"reason"`
		CreatedAt   string `json:"created_at"`
		UpdatedAt   string `json:"updated_at"`
		NetworkID   uint   `json:"network_id"`
		NetworkName string `json:"network_name"`
		ApplicantIP string `json:"applicant_ip"`
		ApplyTime   string `json:"apply_time"`
		Message     string `json:"message"`
	}

	var responseList []ResponseItem
	for _, item := range list {
		// 通过 SeedID 关联查询 MeshSeed 获取 NetworkID
		var meshSeed model.MeshSeed
		networkName := "未知网络"
		networkID := uint(0)
		if err := h.store.DB().Where("seed_id = ?", item.SeedID).First(&meshSeed).Error; err == nil {
			// 查询网络信息
			var network model.Network
			if err := h.store.DB().Where("id = ?", meshSeed.NetworkID).First(&network).Error; err == nil {
				networkName = network.Name
				networkID = uint(network.ID)
			}
		}

		responseList = append(responseList, ResponseItem{
			ID:          item.ID,
			SeedID:      item.SeedID,
			DeviceName:  item.DeviceName,
			RequestIP:   item.RequestIP,
			Status:      item.Status,
			ExpireAt:    item.ExpireAt.Format("2006-01-02 15:04:05"),
			ApprovedAt:  formatTime(item.ApprovedAt),
			RejectedAt:  formatTime(item.RejectedAt),
			Reason:      item.Reason,
			CreatedAt:   item.CreatedAt.Format("2006-01-02 15:04:05"),
			UpdatedAt:   item.UpdatedAt.Format("2006-01-02 15:04:05"),
			NetworkID:   networkID,
			NetworkName: networkName,
			ApplicantIP: item.RequestIP,
			ApplyTime:   item.CreatedAt.Format("2006-01-02 15:04:05"),
			Message:     "",
		})
	}

	c.JSON(http.StatusOK, gin.H{
		"data": gin.H{
			"list":  responseList,
			"total": total,
		},
	})
}

// ApproveJoin 审核通过
func (h *PendingJoinHandler) ApproveJoin(c *gin.Context) {
	idStr := c.Param("id")
	id, _ := strconv.ParseUint(idStr, 10, 32)

	result, err := h.service.ApproveJoin(uint(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", uint64(id)),
		zap.String("device_name", result.Device.Name),
		zap.String("device_ip", result.Device.VirtualIP))

	c.JSON(http.StatusOK, gin.H{
		"message": "审核通过",
		"data": gin.H{
			"device":           result.Device,
			"private_key":      result.PrivateKey,
			"network":          result.Network,
			"wireguard_config": result.ConfigText,
		},
	})
}

// RejectJoin 审核拒绝
func (h *PendingJoinHandler) RejectJoin(c *gin.Context) {
	idStr := c.Param("id")
	id, _ := strconv.ParseUint(idStr, 10, 32)

	var req struct {
		Reason string `json:"reason"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"})
		return
	}

	if err := h.service.RejectJoin(uint(id), req.Reason); err != nil {
		h.logger.Error("审核拒绝失败", zap.Error(err))
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "已拒绝"})
}

// CountPending 统计待审核数量
func (h *PendingJoinHandler) CountPending(c *gin.Context) {
	count, err := h.service.CountPending()
	if err != nil {
		h.logger.Error("统计待审核数量失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "统计失败"})
		return
	}

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

// DeleteExpired 清理过期记录
func (h *PendingJoinHandler) DeleteExpired(c *gin.Context) {
	if err := h.service.DeleteExpired(); err != nil {
		h.logger.Error("清理过期记录失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "清理失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "清理完成"})
}

func formatTime(t *time.Time) string {
	if t == nil {
		return ""
	}
	return t.Format("2006-01-02 15:04:05")
}
