package services

import (
	"errors"
	"strings"

	"gauth-central/internal/database"
	"gauth-central/internal/models"

	"gorm.io/gorm"
)

const (
	defaultMetaTitle       = "Meta Title"
	defaultMetaDescription = "Meta Description"
	defaultSiteURL         = "https://beyhanogur.com.tr"
	defaultFacebook        = "https://www.facebook.com"
	defaultX               = "https://www.twitter.com"
	defaultInstagram       = "https://www.instagram.com"
	defaultWhatsapp        = "https://www.whatsapp.com"
	defaultPinterest       = "https://www.pinterest.com"
	defaultLinkedin        = "https://www.linkedin.com"
	defaultSlogan          = "Dondurma"
)

type SiteInfoService struct{}

func NewSiteInfoService() *SiteInfoService {
	return &SiteInfoService{}
}

// CreateSiteInfo creates a new site info entry.
func (s *SiteInfoService) CreateSiteInfo(
	title string,
	metaTitle string,
	metaDescription string,
	phone string,
	url string,
	email string,
	facebook string,
	x string,
	instagram string,
	whatsapp string,
	pinterest string,
	linkedin string,
	slogan string,
	wLogo string,
	bLogo string,
	isActive bool,
	address string,
	copyright string,
	mapEmbed string,
) (*models.Setting, error) {
	metaTitle = applyDefault(metaTitle, defaultMetaTitle)
	metaDescription = applyDefault(metaDescription, defaultMetaDescription)
	url = applyDefault(url, defaultSiteURL)
	facebook = applyDefault(facebook, defaultFacebook)
	x = applyDefault(x, defaultX)
	instagram = applyDefault(instagram, defaultInstagram)
	whatsapp = applyDefault(whatsapp, defaultWhatsapp)
	pinterest = applyDefault(pinterest, defaultPinterest)
	linkedin = applyDefault(linkedin, defaultLinkedin)
	slogan = applyDefault(slogan, defaultSlogan)

	setting := models.Setting{
		Title:           title,
		MetaTitle:       metaTitle,
		MetaDescription: metaDescription,
		Phone:           phone,
		URL:             url,
		Email:           email,
		Facebook:        facebook,
		X:               x,
		Instagram:       instagram,
		Whatsapp:        whatsapp,
		Pinterest:       pinterest,
		Linkedin:        linkedin,
		Slogan:          slogan,
		WLogo:           wLogo,
		BLogo:           bLogo,
		IsActive:        isActive,
		Address:         address,
		Copyright:       copyright,
		MapEmbed:        mapEmbed,
	}

	if err := database.DB.Create(&setting).Error; err != nil {
		return nil, err
	}

	return s.GetSiteInfoByID(setting.ID.String())
}

// GetAllSiteInfos retrieves all site info entries. Use onlyActive to filter public data.
func (s *SiteInfoService) GetAllSiteInfos(onlyActive bool) ([]models.Setting, error) {
	var settings []models.Setting
	query := database.DB.Order("created_at desc")
	if onlyActive {
		query = query.Where("is_active = ?", true)
	}
	if err := query.Find(&settings).Error; err != nil {
		return nil, err
	}
	return settings, nil
}

// GetFirstActiveSiteInfo returns the newest active site info entry.
func (s *SiteInfoService) GetFirstActiveSiteInfo() (*models.Setting, error) {
	var setting models.Setting
	if err := database.DB.Where("is_active = ?", true).Order("created_at desc").First(&setting).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("site info not found")
		}
		return nil, err
	}
	return &setting, nil
}

// GetSiteInfoByID retrieves a site info entry by ID.
func (s *SiteInfoService) GetSiteInfoByID(id string) (*models.Setting, error) {
	var setting models.Setting
	if err := database.DB.Where("id = ?", id).First(&setting).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("site info not found")
		}
		return nil, err
	}
	return &setting, nil
}

// UpdateSiteInfo updates an existing site info entry.
func (s *SiteInfoService) UpdateSiteInfo(
	id string,
	title *string,
	metaTitle *string,
	metaDescription *string,
	phone *string,
	url *string,
	email *string,
	facebook *string,
	x *string,
	instagram *string,
	whatsapp *string,
	pinterest *string,
	linkedin *string,
	slogan *string,
	wLogo *string,
	bLogo *string,
	isActive *bool,
	address *string,
	copyright *string,
	mapEmbed *string,
) (*models.Setting, error) {
	setting, err := s.GetSiteInfoByID(id)
	if err != nil {
		return nil, err
	}

	updates := map[string]interface{}{}
	if title != nil {
		updates["title"] = *title
	}
	if metaTitle != nil {
		updates["meta_title"] = applyDefault(*metaTitle, defaultMetaTitle)
	}
	if metaDescription != nil {
		updates["meta_description"] = applyDefault(*metaDescription, defaultMetaDescription)
	}
	if phone != nil {
		updates["phone"] = *phone
	}
	if url != nil {
		updates["url"] = applyDefault(*url, defaultSiteURL)
	}
	if email != nil {
		updates["email"] = *email
	}
	if facebook != nil {
		updates["facebook"] = applyDefault(*facebook, defaultFacebook)
	}
	if x != nil {
		updates["x"] = applyDefault(*x, defaultX)
	}
	if instagram != nil {
		updates["instagram"] = applyDefault(*instagram, defaultInstagram)
	}
	if whatsapp != nil {
		updates["whatsapp"] = applyDefault(*whatsapp, defaultWhatsapp)
	}
	if pinterest != nil {
		updates["pinterest"] = applyDefault(*pinterest, defaultPinterest)
	}
	if linkedin != nil {
		updates["linkedin"] = applyDefault(*linkedin, defaultLinkedin)
	}
	if slogan != nil {
		updates["slogan"] = applyDefault(*slogan, defaultSlogan)
	}
	if wLogo != nil {
		updates["w_logo"] = *wLogo
	}
	if bLogo != nil {
		updates["b_logo"] = *bLogo
	}
	if isActive != nil {
		updates["is_active"] = *isActive
	}
	if address != nil {
		updates["address"] = *address
	}
	if copyright != nil {
		updates["copyright"] = *copyright
	}
	if mapEmbed != nil {
		updates["map_embed"] = *mapEmbed
	}

	if len(updates) > 0 {
		if err := database.DB.Model(setting).Updates(updates).Error; err != nil {
			return nil, err
		}
	}

	return s.GetSiteInfoByID(id)
}

// DeleteSiteInfo deletes a site info entry by ID.
func (s *SiteInfoService) DeleteSiteInfo(id string) error {
	result := database.DB.Delete(&models.Setting{}, "id = ?", id)
	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return errors.New("site info not found")
	}
	return nil
}

func applyDefault(value string, fallback string) string {
	clean := strings.TrimSpace(value)
	if clean == "" {
		return fallback
	}
	return clean
}
