package handlers

import (
	"net/http"
	"strconv"

	"sale/internal/models"
	"sale/internal/utils"

	"github.com/gin-gonic/gin"
)

type PaymentChannelHandler struct{}

func NewPaymentChannelHandler() *PaymentChannelHandler {
	return &PaymentChannelHandler{}
}

func (h *PaymentChannelHandler) PublicList(c *gin.Context) {
	var channels []models.PaymentChannel
	utils.DB.Where("is_enabled = ?", true).Order("sort_order ASC, id ASC").Find(&channels)

	type publicChannel struct {
		ID        uint    `json:"id"`
		Name      string  `json:"name"`
		Code      string  `json:"code"`
		Type      string  `json:"type"`
		Icon      string  `json:"icon"`
		FeeRate   float64 `json:"fee_rate"`
		MinAmount float64 `json:"min_amount"`
		MaxAmount float64 `json:"max_amount"`
		SortOrder int     `json:"sort_order"`
	}

	var result []publicChannel
	for _, ch := range channels {
		result = append(result, publicChannel{
			ID:        ch.ID,
			Name:      ch.Name,
			Code:      ch.Code,
			Type:      ch.Type,
			Icon:      ch.Icon,
			FeeRate:   ch.FeeRate,
			MinAmount: ch.MinAmount,
			MaxAmount: ch.MaxAmount,
			SortOrder: ch.SortOrder,
		})
	}

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

func (h *PaymentChannelHandler) List(c *gin.Context) {
	var channels []models.PaymentChannel
	utils.DB.Order("sort_order ASC, id ASC").Find(&channels)
	c.JSON(http.StatusOK, gin.H{"data": channels})
}

func (h *PaymentChannelHandler) GetByID(c *gin.Context) {
	id, _ := strconv.Atoi(c.Param("id"))
	var channel models.PaymentChannel
	if err := utils.DB.First(&channel, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Payment channel not found"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"data": channel})
}

func (h *PaymentChannelHandler) Create(c *gin.Context) {
	var req struct {
		Name      string  `json:"name"`
		Code      string  `json:"code"`
		Type      string  `json:"type"`
		Icon      string  `json:"icon"`
		FeeRate   float64 `json:"fee_rate"`
		MinAmount float64 `json:"min_amount"`
		MaxAmount float64 `json:"max_amount"`
		Config    string  `json:"config"`
		IsEnabled bool    `json:"is_enabled"`
		SortOrder int     `json:"sort_order"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	var existing models.PaymentChannel
	if err := utils.DB.Where("code = ?", req.Code).First(&existing).Error; err == nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "支付通道代码已存在"})
		return
	}

	channel := models.PaymentChannel{
		Name:      req.Name,
		Code:      req.Code,
		Type:      req.Type,
		Icon:      req.Icon,
		FeeRate:   req.FeeRate,
		MinAmount: req.MinAmount,
		MaxAmount: req.MaxAmount,
		Config:    req.Config,
		IsEnabled: req.IsEnabled,
		SortOrder: req.SortOrder,
	}

	if err := utils.DB.Create(&channel).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create payment channel"})
		return
	}

	c.JSON(http.StatusCreated, gin.H{"data": channel})
}

func (h *PaymentChannelHandler) Update(c *gin.Context) {
	id, _ := strconv.Atoi(c.Param("id"))
	var channel models.PaymentChannel
	if err := utils.DB.First(&channel, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Payment channel not found"})
		return
	}

	var req struct {
		Name      *string  `json:"name"`
		Code      *string  `json:"code"`
		Type      *string  `json:"type"`
		Icon      *string  `json:"icon"`
		FeeRate   *float64 `json:"fee_rate"`
		MinAmount *float64 `json:"min_amount"`
		MaxAmount *float64 `json:"max_amount"`
		Config    *string  `json:"config"`
		IsEnabled *bool    `json:"is_enabled"`
		SortOrder *int     `json:"sort_order"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	updates := make(map[string]interface{})
	if req.Name != nil {
		updates["name"] = *req.Name
	}
	if req.Code != nil && *req.Code != channel.Code {
		var existing models.PaymentChannel
		if err := utils.DB.Where("code = ? AND id != ?", *req.Code, id).First(&existing).Error; err == nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "支付通道代码已存在"})
			return
		}
		updates["code"] = *req.Code
	}
	if req.Type != nil {
		updates["type"] = *req.Type
	}
	if req.Icon != nil {
		updates["icon"] = *req.Icon
	}
	if req.FeeRate != nil {
		updates["fee_rate"] = *req.FeeRate
	}
	if req.MinAmount != nil {
		updates["min_amount"] = *req.MinAmount
	}
	if req.MaxAmount != nil {
		updates["max_amount"] = *req.MaxAmount
	}
	if req.Config != nil {
		updates["config"] = *req.Config
	}
	if req.IsEnabled != nil {
		updates["is_enabled"] = *req.IsEnabled
	}
	if req.SortOrder != nil {
		updates["sort_order"] = *req.SortOrder
	}

	utils.DB.Model(&channel).Updates(updates)
	c.JSON(http.StatusOK, gin.H{"data": channel})
}

func (h *PaymentChannelHandler) Delete(c *gin.Context) {
	id, _ := strconv.Atoi(c.Param("id"))
	if err := utils.DB.Delete(&models.PaymentChannel{}, id).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete payment channel"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "Payment channel deleted successfully"})
}

func (h *PaymentChannelHandler) Toggle(c *gin.Context) {
	id, _ := strconv.Atoi(c.Param("id"))
	var channel models.PaymentChannel
	if err := utils.DB.First(&channel, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Payment channel not found"})
		return
	}
	channel.IsEnabled = !channel.IsEnabled
	utils.DB.Save(&channel)
	c.JSON(http.StatusOK, gin.H{"data": channel})
}
