package handlers

import (
	"net/http"
	"os"
	"strings"

	"gauth-central/config"
	"gauth-central/internal/services"
	"gauth-central/pkg/utils"

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

type BannerHandler struct {
	bannerService *services.BannerService
}

func NewBannerHandler(bannerService *services.BannerService) *BannerHandler {
	return &BannerHandler{bannerService: bannerService}
}

// GetAllBanners godoc
// @Summary Get all active banners
// @Description Retrieve a list of active banners
// @Tags banners
// @Produce json
// @Success 200 {array} models.Banner
// @Failure 500 {object} map[string]string
// @Router /banners [get]
func (h *BannerHandler) GetAllBanners(c *gin.Context) {
	items, err := h.bannerService.GetAllBanners(true)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, items)
}

// GetActiveBanner godoc
// @Summary Get active banner
// @Description Retrieve the newest active banner
// @Tags banners
// @Produce json
// @Success 200 {object} models.Banner
// @Failure 404 {object} map[string]string
// @Router /banners/active [get]
func (h *BannerHandler) GetActiveBanner(c *gin.Context) {
	item, err := h.bannerService.GetFirstActiveBanner()
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, item)
}

// AdminGetAllBanners godoc
// @Summary Get all banners (Admin)
// @Description Retrieve a list of all banners including inactive ones
// @Tags admin
// @Security ApiKeyAuth
// @Produce json
// @Success 200 {array} models.Banner
// @Failure 500 {object} map[string]string
// @Router /admin/banners [get]
func (h *BannerHandler) AdminGetAllBanners(c *gin.Context) {
	items, err := h.bannerService.GetAllBanners(false)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, items)
}

// AdminGetBannerByID godoc
// @Summary Get banner by ID (Admin)
// @Description Retrieve details of a specific banner
// @Tags admin
// @Security ApiKeyAuth
// @Produce json
// @Param id path string true "Banner ID"
// @Success 200 {object} models.Banner
// @Failure 404 {object} map[string]string
// @Router /admin/banners/{id} [get]
func (h *BannerHandler) AdminGetBannerByID(c *gin.Context) {
	id := c.Param("id")
	item, err := h.bannerService.GetBannerByID(id)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, item)
}

// CreateBanner godoc
// @Summary Create a new banner (Admin)
// @Description Create a new banner entry
// @Tags admin
// @Security ApiKeyAuth
// @Accept multipart/form-data
// @Produce json
// @Param color formData string false "Text color"
// @Param title formData string false "Title"
// @Param text1 formData string false "Text 1"
// @Param text2 formData string false "Text 2"
// @Param text4 formData string false "Text 4"
// @Param text5 formData string false "Text 5"
// @Param image formData file true "Image"
// @Param image_k formData file false "Small image"
// @Param image_k_txt formData string false "Small image text"
// @Param is_active formData bool false "Is active"
// @Success 201 {object} models.Banner
// @Failure 400 {object} map[string]string
// @Router /admin/banners [post]
func (h *BannerHandler) CreateBanner(c *gin.Context) {
	color := strings.TrimSpace(c.PostForm("color"))
	title := strings.TrimSpace(c.PostForm("title"))
	text1 := strings.TrimSpace(c.PostForm("text1"))
	text2 := strings.TrimSpace(c.PostForm("text2"))
	text4 := strings.TrimSpace(c.PostForm("text4"))
	text5 := strings.TrimSpace(c.PostForm("text5"))
	imageKTxt := strings.TrimSpace(c.PostForm("image_k_txt"))

	isActive := true
	isActivePtr, err := parseOptionalBool(c, "is_active")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "is_active must be true or false"})
		return
	}
	if isActivePtr != nil {
		isActive = *isActivePtr
	}

	imageFile, imageErr := c.FormFile("image")
	if imageErr != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "image is required"})
		return
	}
	if imageFile.Size > 5*1024*1024 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Image size exceeds 5MB limit"})
		return
	}

	imageURL, err := utils.SaveOptimizedImage(imageFile, "./uploads/banner", "banner", &utils.ImageOptions{
		Width:   config.AppConfig.BannerImageWidth,
		Height:  config.AppConfig.BannerImageHeight,
		Quality: float32(config.AppConfig.BannerImageQuality),
		Format:  config.AppConfig.BannerImageFormat,
		Mode:    config.AppConfig.BannerImageMode,
	})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save image: " + err.Error()})
		return
	}

	imageKURL := ""
	imageKFile, imageKErr := c.FormFile("image_k")
	if imageKErr == nil {
		if imageKFile.Size > 5*1024*1024 {
			c.JSON(http.StatusBadRequest, gin.H{"error": "image_k size exceeds 5MB limit"})
			return
		}
		imageKURL, err = utils.SaveOptimizedImage(imageKFile, "./uploads/banner/kucuk", "banner_k", &utils.ImageOptions{
			Width:   config.AppConfig.BannerThumbWidth,
			Height:  config.AppConfig.BannerThumbHeight,
			Quality: float32(config.AppConfig.BannerThumbQuality),
			Format:  config.AppConfig.BannerThumbFormat,
			Mode:    config.AppConfig.BannerThumbMode,
		})
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save image_k: " + err.Error()})
			return
		}
	}

	item, err := h.bannerService.CreateBanner(
		color,
		title,
		text1,
		text2,
		text4,
		text5,
		imageURL,
		imageKURL,
		imageKTxt,
		isActive,
	)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, item)
}

// UpdateBanner godoc
// @Summary Update a banner (Admin)
// @Description Update an existing banner entry
// @Tags admin
// @Security ApiKeyAuth
// @Accept multipart/form-data
// @Produce json
// @Param id path string true "Banner ID"
// @Param color formData string false "Text color"
// @Param title formData string false "Title"
// @Param text1 formData string false "Text 1"
// @Param text2 formData string false "Text 2"
// @Param text4 formData string false "Text 4"
// @Param text5 formData string false "Text 5"
// @Param image formData file false "Image"
// @Param image_k formData file false "Small image"
// @Param image_k_txt formData string false "Small image text"
// @Param is_active formData bool false "Is active"
// @Success 200 {object} models.Banner
// @Failure 400 {object} map[string]string
// @Failure 404 {object} map[string]string
// @Router /admin/banners/{id} [put]
func (h *BannerHandler) UpdateBanner(c *gin.Context) {
	id := c.Param("id")

	color, hasColor := getOptionalFormValue(c, "color")
	title, hasTitle := getOptionalFormValue(c, "title")
	text1, hasText1 := getOptionalFormValue(c, "text1")
	text2, hasText2 := getOptionalFormValue(c, "text2")
	text4, hasText4 := getOptionalFormValue(c, "text4")
	text5, hasText5 := getOptionalFormValue(c, "text5")
	imageKTxt, hasImageKTxt := getOptionalFormValue(c, "image_k_txt")

	var colorPtr *string
	var titlePtr *string
	var text1Ptr *string
	var text2Ptr *string
	var text4Ptr *string
	var text5Ptr *string
	var imageKTxtPtr *string

	if hasColor {
		colorPtr = &color
	}
	if hasTitle {
		titlePtr = &title
	}
	if hasText1 {
		text1Ptr = &text1
	}
	if hasText2 {
		text2Ptr = &text2
	}
	if hasText4 {
		text4Ptr = &text4
	}
	if hasText5 {
		text5Ptr = &text5
	}
	if hasImageKTxt {
		imageKTxtPtr = &imageKTxt
	}

	isActivePtr, err := parseOptionalBool(c, "is_active")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "is_active must be true or false"})
		return
	}

	var imagePtr *string
	imageFile, imageErr := c.FormFile("image")
	if imageErr == nil {
		if imageFile.Size > 5*1024*1024 {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Image size exceeds 5MB limit"})
			return
		}
		item, fetchErr := h.bannerService.GetBannerByID(id)
		if fetchErr != nil {
			c.JSON(http.StatusNotFound, gin.H{"error": fetchErr.Error()})
			return
		}
		if item.Image != "" && strings.HasPrefix(item.Image, "/uploads/") {
			_ = os.Remove("." + item.Image)
		}
		imageURL, saveErr := utils.SaveOptimizedImage(imageFile, "./uploads/banner", id, &utils.ImageOptions{
			Width:   config.AppConfig.BannerImageWidth,
			Height:  config.AppConfig.BannerImageHeight,
			Quality: float32(config.AppConfig.BannerImageQuality),
			Format:  config.AppConfig.BannerImageFormat,
			Mode:    config.AppConfig.BannerImageMode,
		})
		if saveErr != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save image: " + saveErr.Error()})
			return
		}
		imagePtr = &imageURL
	}

	var imageKPtr *string
	imageKFile, imageKErr := c.FormFile("image_k")
	if imageKErr == nil {
		if imageKFile.Size > 5*1024*1024 {
			c.JSON(http.StatusBadRequest, gin.H{"error": "image_k size exceeds 5MB limit"})
			return
		}
		item, fetchErr := h.bannerService.GetBannerByID(id)
		if fetchErr != nil {
			c.JSON(http.StatusNotFound, gin.H{"error": fetchErr.Error()})
			return
		}
		if item.ImageK != "" && strings.HasPrefix(item.ImageK, "/uploads/") {
			_ = os.Remove("." + item.ImageK)
		}
		imageKURL, saveErr := utils.SaveOptimizedImage(imageKFile, "./uploads/banner/kucuk", id+"_k", &utils.ImageOptions{
			Width:   config.AppConfig.BannerThumbWidth,
			Height:  config.AppConfig.BannerThumbHeight,
			Quality: float32(config.AppConfig.BannerThumbQuality),
			Format:  config.AppConfig.BannerThumbFormat,
			Mode:    config.AppConfig.BannerThumbMode,
		})
		if saveErr != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save image_k: " + saveErr.Error()})
			return
		}
		imageKPtr = &imageKURL
	}

	item, err := h.bannerService.UpdateBanner(
		id,
		colorPtr,
		titlePtr,
		text1Ptr,
		text2Ptr,
		text4Ptr,
		text5Ptr,
		imagePtr,
		imageKPtr,
		imageKTxtPtr,
		isActivePtr,
	)
	if err != nil {
		status := http.StatusInternalServerError
		if err.Error() == "banner not found" {
			status = http.StatusNotFound
		}
		c.JSON(status, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, item)
}

// DeleteBanner godoc
// @Summary Delete a banner (Admin)
// @Description Delete a banner by ID
// @Tags admin
// @Security ApiKeyAuth
// @Param id path string true "Banner ID"
// @Success 200 {object} map[string]string
// @Failure 404 {object} map[string]string
// @Router /admin/banners/{id} [delete]
func (h *BannerHandler) DeleteBanner(c *gin.Context) {
	id := c.Param("id")
	if err := h.bannerService.DeleteBanner(id); err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "Banner deleted successfully"})
}
