package handler

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

	"github.com/gin-gonic/gin"

	vulnmodel "vul-backend/internal/modules/vuln/model"
	channelservice "vul-backend/internal/modules/vuln/service"
	"vul-backend/internal/pkg/response"
)

type DiscoveryChannelHandler struct {
	service *channelservice.DiscoveryChannelService
}

func NewDiscoveryChannelHandler(service *channelservice.DiscoveryChannelService) *DiscoveryChannelHandler {
	return &DiscoveryChannelHandler{service: service}
}

func (h *DiscoveryChannelHandler) RegisterRoutes(view *gin.RouterGroup, manage *gin.RouterGroup) {
	view.GET("", h.List)
	if manage != nil {
		manage.POST("", h.Create)
		manage.PUT(":id", h.Update)
		manage.DELETE(":id", h.Delete)
	} else {
		view.POST("", h.Create)
		view.PUT(":id", h.Update)
		view.DELETE(":id", h.Delete)
	}
}

func (h *DiscoveryChannelHandler) List(c *gin.Context) {
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
	q := strings.TrimSpace(c.Query("q"))

	var systemOnly *bool
	if value := c.Query("system_only"); value != "" {
		parsed := value == "true" || value == "1"
		systemOnly = &parsed
	}

	result, err := h.service.List(c.Request.Context(), channelservice.DiscoveryChannelListQuery{
		Page:       page,
		PageSize:   pageSize,
		Query:      q,
		SystemOnly: systemOnly,
	})
	if err != nil {
		response.Error(c, http.StatusInternalServerError, err.Error())
		return
	}

	response.Success(c, response.PaginatedResponse{
		Items:      result.Items,
		Total:      result.Total,
		Page:       page,
		PageSize:   pageSize,
		TotalPages: int((result.Total + int64(pageSize) - 1) / int64(pageSize)),
	})
}

func (h *DiscoveryChannelHandler) Create(c *gin.Context) {
	var payload struct {
		Name        string `json:"name" binding:"required"`
		Label       string `json:"label" binding:"required"`
		Description string `json:"description"`
		IsSystem    bool   `json:"is_system"`
	}
	if err := c.ShouldBindJSON(&payload); err != nil {
		response.Error(c, http.StatusBadRequest, err.Error())
		return
	}

	channel := &vulnmodel.DiscoveryChannel{
		Name:        payload.Name,
		Label:       payload.Label,
		Description: payload.Description,
		IsSystem:    payload.IsSystem,
	}
	if err := h.service.Create(c.Request.Context(), channel); err != nil {
		response.Error(c, http.StatusBadRequest, err.Error())
		return
	}
	response.Success(c, channel)
}

func (h *DiscoveryChannelHandler) Update(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil || id == 0 {
		response.Error(c, http.StatusBadRequest, "invalid id")
		return
	}

	var payload struct {
		Name        string `json:"name" binding:"required"`
		Label       string `json:"label" binding:"required"`
		Description string `json:"description"`
	}
	if err := c.ShouldBindJSON(&payload); err != nil {
		response.Error(c, http.StatusBadRequest, err.Error())
		return
	}

	channel := &vulnmodel.DiscoveryChannel{
		ID:          id,
		Name:        payload.Name,
		Label:       payload.Label,
		Description: payload.Description,
	}
	if err := h.service.Update(c.Request.Context(), channel); err != nil {
		response.Error(c, http.StatusBadRequest, err.Error())
		return
	}
	response.Success(c, channel)
}

func (h *DiscoveryChannelHandler) Delete(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil || id == 0 {
		response.Error(c, http.StatusBadRequest, "invalid id")
		return
	}
	// 简化版：允许删除系统渠道（在独立API中由外部控制权限）
	allowSystem := true
	if err := h.service.Delete(c.Request.Context(), id, allowSystem); err != nil {
		response.Error(c, http.StatusBadRequest, err.Error())
		return
	}
	response.Success(c, gin.H{"success": true})
}
