package handlers

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

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

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

type SiteInfoHandler struct {
	siteInfoService *services.SiteInfoService
}

func NewSiteInfoHandler(siteInfoService *services.SiteInfoService) *SiteInfoHandler {
	return &SiteInfoHandler{siteInfoService: siteInfoService}
}

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

// GetActiveSiteInfo godoc
// @Summary Get active site info
// @Description Retrieve the newest active site info entry
// @Tags site-info
// @Produce json
// @Success 200 {object} models.Setting
// @Failure 404 {object} map[string]string
// @Router /site-info/active [get]
func (h *SiteInfoHandler) GetActiveSiteInfo(c *gin.Context) {
	item, err := h.siteInfoService.GetFirstActiveSiteInfo()
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, item)
}

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

// AdminGetSiteInfoByID godoc
// @Summary Get site info by ID (Admin)
// @Description Retrieve details of a specific site info entry
// @Tags admin
// @Security ApiKeyAuth
// @Produce json
// @Param id path string true "Site Info ID"
// @Success 200 {object} models.Setting
// @Failure 404 {object} map[string]string
// @Router /admin/site-info/{id} [get]
func (h *SiteInfoHandler) AdminGetSiteInfoByID(c *gin.Context) {
	id := c.Param("id")
	item, err := h.siteInfoService.GetSiteInfoByID(id)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, item)
}

// CreateSiteInfo godoc
// @Summary Create site info (Admin)
// @Description Create a new site info entry
// @Tags admin
// @Security ApiKeyAuth
// @Accept multipart/form-data
// @Produce json
// @Param title formData string true "Title"
// @Param meta_title formData string false "Meta title"
// @Param meta_description formData string false "Meta description"
// @Param phone formData string true "Phone"
// @Param url formData string false "Site URL"
// @Param email formData string true "Email"
// @Param facebook formData string false "Facebook"
// @Param x formData string false "X"
// @Param instagram formData string false "Instagram"
// @Param whatsapp formData string false "Whatsapp"
// @Param pinterest formData string false "Pinterest"
// @Param linkedin formData string false "LinkedIn"
// @Param slogan formData string false "Slogan"
// @Param w_logo formData file false "White logo"
// @Param b_logo formData file false "Black logo"
// @Param is_active formData bool false "Is active"
// @Success 201 {object} models.Setting
// @Failure 400 {object} map[string]string
// @Router /admin/site-info [post]
func (h *SiteInfoHandler) CreateSiteInfo(c *gin.Context) {
	title := strings.TrimSpace(c.PostForm("title"))
	phone := strings.TrimSpace(c.PostForm("phone"))
	email := strings.TrimSpace(c.PostForm("email"))
	if title == "" || phone == "" || email == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "title, phone, and email are required"})
		return
	}

	metaTitle := strings.TrimSpace(c.PostForm("meta_title"))
	metaDescription := strings.TrimSpace(c.PostForm("meta_description"))
	url := strings.TrimSpace(c.PostForm("url"))
	facebook := strings.TrimSpace(c.PostForm("facebook"))
	xValue := strings.TrimSpace(c.PostForm("x"))
	instagram := strings.TrimSpace(c.PostForm("instagram"))
	whatsapp := strings.TrimSpace(c.PostForm("whatsapp"))
	pinterest := strings.TrimSpace(c.PostForm("pinterest"))
	linkedin := strings.TrimSpace(c.PostForm("linkedin"))
	slogan := strings.TrimSpace(c.PostForm("slogan"))
	address := strings.TrimSpace(c.PostForm("address"))
	copyright := strings.TrimSpace(c.PostForm("copyright"))
	mapEmbed := strings.TrimSpace(c.PostForm("map_embed"))

	isActive := false
	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
	}

	wLogo := ""
	wLogoFile, wLogoErr := c.FormFile("w_logo")
	if wLogoErr == nil {
		if wLogoFile.Size > 5*1024*1024 {
			c.JSON(http.StatusBadRequest, gin.H{"error": "w_logo size exceeds 5MB limit"})
			return
		}
		wLogo, err = utils.SaveOptimizedImage(wLogoFile, "./uploads/logo", "wlogo", &utils.ImageOptions{
			Width:   config.AppConfig.SettingsLogoWidth,
			Height:  config.AppConfig.SettingsLogoHeight,
			Quality: float32(config.AppConfig.SettingsLogoQuality),
			Format:  config.AppConfig.SettingsLogoFormat,
			Mode:    config.AppConfig.SettingsLogoMode,
		})
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save w_logo: " + err.Error()})
			return
		}
	}

	bLogo := ""
	bLogoFile, bLogoErr := c.FormFile("b_logo")
	if bLogoErr == nil {
		if bLogoFile.Size > 5*1024*1024 {
			c.JSON(http.StatusBadRequest, gin.H{"error": "b_logo size exceeds 5MB limit"})
			return
		}
		bLogo, err = utils.SaveOptimizedImage(bLogoFile, "./uploads/logo", "blogo", &utils.ImageOptions{
			Width:   config.AppConfig.SettingsLogoWidth,
			Height:  config.AppConfig.SettingsLogoHeight,
			Quality: float32(config.AppConfig.SettingsLogoQuality),
			Format:  config.AppConfig.SettingsLogoFormat,
			Mode:    config.AppConfig.SettingsLogoMode,
		})
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save b_logo: " + err.Error()})
			return
		}
	}

	item, err := h.siteInfoService.CreateSiteInfo(
		title,
		metaTitle,
		metaDescription,
		phone,
		url,
		email,
		facebook,
		xValue,
		instagram,
		whatsapp,
		pinterest,
		linkedin,
		slogan,
		wLogo,
		bLogo,
		isActive,
		address,
		copyright,
		mapEmbed,
	)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, item)
}

// UpdateSiteInfo godoc
// @Summary Update site info (Admin)
// @Description Update an existing site info entry
// @Tags admin
// @Security ApiKeyAuth
// @Accept multipart/form-data
// @Produce json
// @Param id path string true "Site Info ID"
// @Param title formData string false "Title"
// @Param meta_title formData string false "Meta title"
// @Param meta_description formData string false "Meta description"
// @Param phone formData string false "Phone"
// @Param url formData string false "Site URL"
// @Param email formData string false "Email"
// @Param facebook formData string false "Facebook"
// @Param x formData string false "X"
// @Param instagram formData string false "Instagram"
// @Param whatsapp formData string false "Whatsapp"
// @Param pinterest formData string false "Pinterest"
// @Param linkedin formData string false "LinkedIn"
// @Param slogan formData string false "Slogan"
// @Param w_logo formData file false "White logo"
// @Param b_logo formData file false "Black logo"
// @Param is_active formData bool false "Is active"
// @Success 200 {object} models.Setting
// @Failure 400 {object} map[string]string
// @Failure 404 {object} map[string]string
// @Router /admin/site-info/{id} [put]
func (h *SiteInfoHandler) UpdateSiteInfo(c *gin.Context) {
	id := c.Param("id")

	title, hasTitle := getOptionalFormValue(c, "title")
	metaTitle, hasMetaTitle := getOptionalFormValue(c, "meta_title")
	metaDescription, hasMetaDescription := getOptionalFormValue(c, "meta_description")
	phone, hasPhone := getOptionalFormValue(c, "phone")
	url, hasURL := getOptionalFormValue(c, "url")
	email, hasEmail := getOptionalFormValue(c, "email")
	facebook, hasFacebook := getOptionalFormValue(c, "facebook")
	xValue, hasX := getOptionalFormValue(c, "x")
	instagram, hasInstagram := getOptionalFormValue(c, "instagram")
	whatsapp, hasWhatsapp := getOptionalFormValue(c, "whatsapp")
	pinterest, hasPinterest := getOptionalFormValue(c, "pinterest")
	linkedin, hasLinkedin := getOptionalFormValue(c, "linkedin")
	slogan, hasSlogan := getOptionalFormValue(c, "slogan")
	address, hasAddress := getOptionalFormValue(c, "address")
	copyright, hasCopyright := getOptionalFormValue(c, "copyright")
	mapEmbed, hasMapEmbed := getOptionalFormValue(c, "map_embed")

	var titlePtr *string
	var metaTitlePtr *string
	var metaDescriptionPtr *string
	var phonePtr *string
	var urlPtr *string
	var emailPtr *string
	var facebookPtr *string
	var xPtr *string
	var instagramPtr *string
	var whatsappPtr *string
	var pinterestPtr *string
	var linkedinPtr *string
	var sloganPtr *string
	var addressPtr *string
	var copyrightPtr *string
	var mapEmbedPtr *string

	if hasTitle {
		titlePtr = &title
	}
	if hasMetaTitle {
		metaTitlePtr = &metaTitle
	}
	if hasMetaDescription {
		metaDescriptionPtr = &metaDescription
	}
	if hasPhone {
		phonePtr = &phone
	}
	if hasURL {
		urlPtr = &url
	}
	if hasEmail {
		emailPtr = &email
	}
	if hasFacebook {
		facebookPtr = &facebook
	}
	if hasX {
		xPtr = &xValue
	}
	if hasInstagram {
		instagramPtr = &instagram
	}
	if hasWhatsapp {
		whatsappPtr = &whatsapp
	}
	if hasPinterest {
		pinterestPtr = &pinterest
	}
	if hasLinkedin {
		linkedinPtr = &linkedin
	}
	if hasSlogan {
		sloganPtr = &slogan
	}
	if hasAddress {
		addressPtr = &address
	}
	if hasCopyright {
		copyrightPtr = &copyright
	}
	if hasMapEmbed {
		mapEmbedPtr = &mapEmbed
	}

	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 wLogoPtr *string
	wLogoFile, wLogoErr := c.FormFile("w_logo")
	if wLogoErr == nil {
		if wLogoFile.Size > 5*1024*1024 {
			c.JSON(http.StatusBadRequest, gin.H{"error": "w_logo size exceeds 5MB limit"})
			return
		}
		item, fetchErr := h.siteInfoService.GetSiteInfoByID(id)
		if fetchErr != nil {
			c.JSON(http.StatusNotFound, gin.H{"error": fetchErr.Error()})
			return
		}
		if item.WLogo != "" && strings.HasPrefix(item.WLogo, "/uploads/") {
			_ = os.Remove("." + item.WLogo)
		}
		wLogo, saveErr := utils.SaveOptimizedImage(wLogoFile, "./uploads/logo", id+"_w", &utils.ImageOptions{
			Width:   config.AppConfig.SettingsLogoWidth,
			Height:  config.AppConfig.SettingsLogoHeight,
			Quality: float32(config.AppConfig.SettingsLogoQuality),
			Format:  config.AppConfig.SettingsLogoFormat,
			Mode:    config.AppConfig.SettingsLogoMode,
		})
		if saveErr != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save w_logo: " + saveErr.Error()})
			return
		}
		wLogoPtr = &wLogo
	}

	var bLogoPtr *string
	bLogoFile, bLogoErr := c.FormFile("b_logo")
	if bLogoErr == nil {
		if bLogoFile.Size > 5*1024*1024 {
			c.JSON(http.StatusBadRequest, gin.H{"error": "b_logo size exceeds 5MB limit"})
			return
		}
		item, fetchErr := h.siteInfoService.GetSiteInfoByID(id)
		if fetchErr != nil {
			c.JSON(http.StatusNotFound, gin.H{"error": fetchErr.Error()})
			return
		}
		if item.BLogo != "" && strings.HasPrefix(item.BLogo, "/uploads/") {
			_ = os.Remove("." + item.BLogo)
		}
		bLogo, saveErr := utils.SaveOptimizedImage(bLogoFile, "./uploads/logo", id+"_b", &utils.ImageOptions{
			Width:   config.AppConfig.SettingsLogoWidth,
			Height:  config.AppConfig.SettingsLogoHeight,
			Quality: float32(config.AppConfig.SettingsLogoQuality),
			Format:  config.AppConfig.SettingsLogoFormat,
			Mode:    config.AppConfig.SettingsLogoMode,
		})
		if saveErr != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save b_logo: " + saveErr.Error()})
			return
		}
		bLogoPtr = &bLogo
	}

	item, err := h.siteInfoService.UpdateSiteInfo(
		id,
		titlePtr,
		metaTitlePtr,
		metaDescriptionPtr,
		phonePtr,
		urlPtr,
		emailPtr,
		facebookPtr,
		xPtr,
		instagramPtr,
		whatsappPtr,
		pinterestPtr,
		linkedinPtr,
		sloganPtr,
		wLogoPtr,
		bLogoPtr,
		isActivePtr,
		addressPtr,
		copyrightPtr,
		mapEmbedPtr,
	)
	if err != nil {
		status := http.StatusInternalServerError
		if err.Error() == "site info not found" {
			status = http.StatusNotFound
		}
		c.JSON(status, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, item)
}

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