package handlers

import (
	"errors"
	"net/http"

	"gauth-central/internal/models"
	"gauth-central/internal/services"

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

type SettingsHandler struct {
	settingsService *services.SettingsService
}

func NewSettingsHandler(settingsService *services.SettingsService) *SettingsHandler {
	return &SettingsHandler{
		settingsService: settingsService,
	}
}

// ==================== CORS WHITELIST ====================

// GetAllWhitelist godoc
// @Summary Get all CORS whitelist entries
// @Tags Settings
// @Security ApiKeyAuth
// @Produce json
// @Success 200 {array} models.CorsWhitelist
// @Router /settings/cors/whitelist [get]
func (h *SettingsHandler) GetAllWhitelist(c *gin.Context) {
	whitelists, err := h.settingsService.GetAllCorsWhitelist()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch whitelist"})
		return
	}

	c.JSON(http.StatusOK, whitelists)
}

// CreateWhitelist godoc
// @Summary Create CORS whitelist entry
// @Tags Settings
// @Security ApiKeyAuth
// @Accept json
// @Produce json
// @Param whitelist body object true "Whitelist data"
// @Success 201 {object} models.CorsWhitelist
// @Router /settings/cors/whitelist [post]
func (h *SettingsHandler) CreateWhitelist(c *gin.Context) {
	var input struct {
		Origin      string `json:"origin" binding:"required"`
		Description string `json:"description"`
	}

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

	email := c.GetString("email")
	whitelist := &models.CorsWhitelist{
		Origin:      input.Origin,
		Description: input.Description,
		IsActive:    true,
		CreatedBy:   email,
	}

	err := h.settingsService.CreateCorsWhitelist(whitelist)
	if err != nil {
		if errors.Is(err, services.ErrCorsOriginExists) {
			c.JSON(http.StatusConflict, gin.H{"error": "Origin already exists"})
			return
		}
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create whitelist entry"})
		return
	}

	c.JSON(http.StatusCreated, whitelist)
}

// UpdateWhitelist godoc
// @Summary Update CORS whitelist entry
// @Tags Settings
// @Security ApiKeyAuth
// @Accept json
// @Produce json
// @Param id path string true "Whitelist ID"
// @Param whitelist body object true "Update data"
// @Success 200 {object} map[string]interface{}
// @Router /settings/cors/whitelist/{id} [put]
func (h *SettingsHandler) UpdateWhitelist(c *gin.Context) {
	id := c.Param("id")

	var input struct {
		Origin      *string `json:"origin"`
		Description *string `json:"description"`
		IsActive    *bool   `json:"is_active"`
	}

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

	updates := make(map[string]interface{})
	if input.Origin != nil {
		updates["origin"] = *input.Origin
	}
	if input.Description != nil {
		updates["description"] = *input.Description
	}
	if input.IsActive != nil {
		updates["is_active"] = *input.IsActive
	}

	err := h.settingsService.UpdateCorsWhitelist(id, updates)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update whitelist entry"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Whitelist updated successfully"})
}

// DeleteWhitelist godoc
// @Summary Delete CORS whitelist entry
// @Tags Settings
// @Security ApiKeyAuth
// @Param id path string true "Whitelist ID"
// @Success 200 {object} map[string]interface{}
// @Router /settings/cors/whitelist/{id} [delete]
func (h *SettingsHandler) DeleteWhitelist(c *gin.Context) {
	id := c.Param("id")

	err := h.settingsService.DeleteCorsWhitelist(id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete whitelist entry"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Whitelist entry deleted successfully"})
}

// ==================== CORS BLACKLIST ====================

// GetAllBlacklist godoc
// @Summary Get all CORS blacklist entries
// @Tags Settings
// @Security ApiKeyAuth
// @Produce json
// @Success 200 {array} models.CorsBlacklist
// @Router /settings/cors/blacklist [get]
func (h *SettingsHandler) GetAllBlacklist(c *gin.Context) {
	blacklists, err := h.settingsService.GetAllCorsBlacklist()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch blacklist"})
		return
	}

	c.JSON(http.StatusOK, blacklists)
}

// CreateBlacklist godoc
// @Summary Create CORS blacklist entry
// @Tags Settings
// @Security ApiKeyAuth
// @Accept json
// @Produce json
// @Param blacklist body object true "Blacklist data"
// @Success 201 {object} models.CorsBlacklist
// @Router /settings/cors/blacklist [post]
func (h *SettingsHandler) CreateBlacklist(c *gin.Context) {
	var input struct {
		Origin string `json:"origin" binding:"required"`
		Reason string `json:"reason"`
	}

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

	email := c.GetString("email")
	blacklist := &models.CorsBlacklist{
		Origin:    input.Origin,
		Reason:    input.Reason,
		IsActive:  true,
		CreatedBy: email,
	}

	err := h.settingsService.CreateCorsBlacklist(blacklist)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create blacklist entry"})
		return
	}

	c.JSON(http.StatusCreated, blacklist)
}

// UpdateBlacklist godoc
// @Summary Update CORS blacklist entry
// @Tags Settings
// @Security ApiKeyAuth
// @Accept json
// @Produce json
// @Param id path string true "Blacklist ID"
// @Param blacklist body object true "Update data"
// @Success 200 {object} map[string]interface{}
// @Router /settings/cors/blacklist/{id} [put]
func (h *SettingsHandler) UpdateBlacklist(c *gin.Context) {
	id := c.Param("id")

	var input struct {
		Origin   *string `json:"origin"`
		Reason   *string `json:"reason"`
		IsActive *bool   `json:"is_active"`
	}

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

	updates := make(map[string]interface{})
	if input.Origin != nil {
		updates["origin"] = *input.Origin
	}
	if input.Reason != nil {
		updates["reason"] = *input.Reason
	}
	if input.IsActive != nil {
		updates["is_active"] = *input.IsActive
	}

	err := h.settingsService.UpdateCorsBlacklist(id, updates)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update blacklist entry"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Blacklist updated successfully"})
}

// DeleteBlacklist godoc
// @Summary Delete CORS blacklist entry
// @Tags Settings
// @Security ApiKeyAuth
// @Param id path string true "Blacklist ID"
// @Success 200 {object} map[string]interface{}
// @Router /settings/cors/blacklist/{id} [delete]
func (h *SettingsHandler) DeleteBlacklist(c *gin.Context) {
	id := c.Param("id")

	err := h.settingsService.DeleteCorsBlacklist(id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete blacklist entry"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Blacklist entry deleted successfully"})
}

// InvalidateCorsCache godoc
// @Summary Invalidate CORS cache (whitelist + blacklist)
// @Tags Settings
// @Security ApiKeyAuth
// @Produce json
// @Success 200 {object} map[string]interface{}
// @Router /settings/cors/cache/invalidate [post]
func (h *SettingsHandler) InvalidateCorsCache(c *gin.Context) {
	h.settingsService.InvalidateCorsCache()
	c.JSON(http.StatusOK, gin.H{"message": "CORS cache invalidated"})
}

// ==================== RATE LIMIT SETTINGS ====================

// GetAllRateLimits godoc
// @Summary Get all rate limit settings
// @Tags Settings
// @Security ApiKeyAuth
// @Produce json
// @Success 200 {array} models.RateLimitSetting
// @Router /settings/ratelimit [get]
func (h *SettingsHandler) GetAllRateLimits(c *gin.Context) {
	settings, err := h.settingsService.GetAllRateLimitSettings()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch rate limit settings"})
		return
	}

	c.JSON(http.StatusOK, settings)
}

// UpdateRateLimit godoc
// @Summary Update rate limit setting
// @Tags Settings
// @Security ApiKeyAuth
// @Accept json
// @Produce json
// @Param id path string true "Setting ID"
// @Param setting body object true "Update data"
// @Success 200 {object} map[string]interface{}
// @Router /settings/ratelimit/{id} [put]
func (h *SettingsHandler) UpdateRateLimit(c *gin.Context) {
	id := c.Param("id")

	var input struct {
		MaxRequests   *int64  `json:"max_requests"`
		WindowSeconds *int    `json:"window_seconds"`
		Description   *string `json:"description"`
		IsActive      *bool   `json:"is_active"`
	}

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

	email := c.GetString("email")
	updates := make(map[string]interface{})

	if input.MaxRequests != nil {
		updates["max_requests"] = *input.MaxRequests
	}
	if input.WindowSeconds != nil {
		updates["window_seconds"] = *input.WindowSeconds
	}
	if input.Description != nil {
		updates["description"] = *input.Description
	}
	if input.IsActive != nil {
		updates["is_active"] = *input.IsActive
	}
	updates["updated_by"] = email

	err := h.settingsService.UpdateRateLimitSetting(id, updates)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update rate limit setting"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Rate limit setting updated successfully"})
}
