package repositories_astrologer

import (
	config "astrology-api/configs"
	models "astrology-api/models/astrologermodel"
	"errors"
	"time"

	"gorm.io/gorm"
)

type offerRepository struct {
	db *gorm.DB
}

func NewOfferRepository() OfferRepository {
	return &offerRepository{
		db: config.DB,
	}
}

func NewOfferRepositoryWithDB(db *gorm.DB) OfferRepository {
	return &offerRepository{
		db: db,
	}
}

func (r *offerRepository) GetOffer(astrologerID uint) (*models.AstrologerOfferSetting, error) {
	var offer models.AstrologerOfferSetting
	err := r.db.
		Where("astrologer_id = ?", astrologerID).
		Where("is_delete = ?", false).
		First(&offer).Error
	if err != nil {
		// Create default offer if record does not exist
		if errors.Is(err, gorm.ErrRecordNotFound) {
			now := time.Now()
			offer = models.AstrologerOfferSetting{
				AstrologerID:        astrologerID,
				PO5Enabled:          false,
				PO5Amount:           0,
				FreeChatEnabled:     false,
				FreeChatMinutes:     0,
				FreeCallEnabled:     false,
				FreeCallMinutes:     0,
				CampaignEnabled:     false,
				CampaignTitle:       "",
				CampaignDescription: "",
				Priority:            0,
				IsActive:            true,
				IsDelete:            false,
				CreatedAt:           &now,
				UpdatedAt:           &now,
			}

			if err := r.db.Create(&offer).Error; err != nil {
				return nil, err
			}

			return &offer, nil
		}

		return nil, err
	}

	return &offer, nil
}

func (r *offerRepository) GetOfferByID(
	id uint,
) (*models.AstrologerOfferSetting, error) {

	var offer models.AstrologerOfferSetting

	err := r.db.
		Where("id = ?", id).
		Where("is_delete = ?", false).
		First(&offer).Error

	if err != nil {
		return nil, err
	}

	return &offer, nil
}

func (r *offerRepository) CreateOffer(offer *models.AstrologerOfferSetting) error {

	if offer == nil {
		return errors.New("offer cannot be nil")
	}

	now := time.Now()

	// Default values
	offer.IsActive = true
	offer.IsDelete = false

	if offer.Priority < 0 {
		offer.Priority = 0
	}

	if offer.CreatedAt == nil {
		offer.CreatedAt = &now
	}

	if offer.UpdatedAt == nil {
		offer.UpdatedAt = &now
	}
	// Prevent duplicate offer settings for an astrologer
	var count int64
	err := r.db.
		Model(&models.AstrologerOfferSetting{}).
		Where("astrologer_id = ?", offer.AstrologerID).
		Where("is_delete = ?", false).
		Count(&count).Error

	if err != nil {
		return err
	}

	if count > 0 {
		return errors.New("offer settings already exist for this astrologer")
	}
	return r.db.Create(offer).Error
}

func (r *offerRepository) UpdateOffer(offer *models.AstrologerOfferSetting) error {
	if offer == nil {
		return errors.New("offer cannot be nil")
	}
	now := time.Now()
	offer.UpdatedAt = &now
	return r.db.
		Model(&models.AstrologerOfferSetting{}).
		Where("id = ?", offer.ID).
		Where("is_delete = ?", false).
		Updates(offer).Error
}

func (r *offerRepository) DeleteOffer(id uint) error {
	now := time.Now()
	return r.db.
		Model(&models.AstrologerOfferSetting{}).
		Where("id = ?", id).
		Updates(map[string]interface{}{
			"is_active":  false,
			"is_delete":  true,
			"updated_at": &now,
		}).Error
}

func (r *offerRepository) EnablePO5Offer(astrologerID uint, amount float64) error {

	now := time.Now()

	return r.db.
		Model(&models.AstrologerOfferSetting{}).
		Where("astrologer_id = ?", astrologerID).
		Where("is_delete = ?", false).
		Updates(map[string]interface{}{
			"po5_enabled": true,
			"po5_amount":  amount,
			"is_active":   true,
			"updated_at":  &now,
		}).Error
}

func (r *offerRepository) DisablePO5Offer(astrologerID uint) error {
	now := time.Now()
	return r.db.
		Model(&models.AstrologerOfferSetting{}).
		Where("astrologer_id = ?", astrologerID).
		Where("is_delete = ?", false).
		Updates(map[string]interface{}{
			"po5_enabled": false,
			"po5_amount":  0,
			"updated_at":  &now,
		}).Error
}

func (r *offerRepository) GetActiveOffer(astrologerID uint) (*models.AstrologerOfferSetting, error) {
	var offer models.AstrologerOfferSetting
	err := r.db.
		Where("astrologer_id = ?", astrologerID).
		Where("is_active = ?", true).
		Where("is_delete = ?", false).
		First(&offer).Error
	if err != nil {
		return nil, err
	}
	return &offer, nil
}

func (r *offerRepository) EnableFreeChatOffer(astrologerID uint, minutes int) error {
	now := time.Now()
	return r.db.
		Model(&models.AstrologerOfferSetting{}).
		Where("astrologer_id = ?", astrologerID).
		Where("is_delete = ?", false).
		Updates(map[string]interface{}{
			"free_chat_enabled": true,
			"free_chat_minutes": minutes,
			"is_active":         true,
			"updated_at":        &now,
		}).Error
}

func (r *offerRepository) DisableFreeChatOffer(astrologerID uint) error {
	now := time.Now()
	return r.db.
		Model(&models.AstrologerOfferSetting{}).
		Where("astrologer_id = ?", astrologerID).
		Where("is_delete = ?", false).
		Updates(map[string]interface{}{
			"free_chat_enabled": false,
			"free_chat_minutes": 0,
			"updated_at":        &now,
		}).Error
}

func (r *offerRepository) EnableFreeCallOffer(astrologerID uint, minutes int) error {
	now := time.Now()
	return r.db.
		Model(&models.AstrologerOfferSetting{}).
		Where("astrologer_id = ?", astrologerID).
		Where("is_delete = ?", false).
		Updates(map[string]interface{}{
			"free_call_enabled": true,
			"free_call_minutes": minutes,
			"is_active":         true,
			"updated_at":        &now,
		}).Error
}

func (r *offerRepository) DisableFreeCallOffer(astrologerID uint) error {
	now := time.Now()
	return r.db.
		Model(&models.AstrologerOfferSetting{}).
		Where("astrologer_id = ?", astrologerID).
		Where("is_delete = ?", false).
		Updates(map[string]interface{}{
			"free_call_enabled": false,
			"free_call_minutes": 0,
			"updated_at":        &now,
		}).Error
}

func (r *offerRepository) EnableCampaign(
	astrologerID uint,
	title string,
	description string,
) error {

	now := time.Now()

	return r.db.
		Model(&models.AstrologerOfferSetting{}).
		Where("astrologer_id = ?", astrologerID).
		Where("is_delete = ?", false).
		Updates(map[string]interface{}{
			"campaign_enabled":     true,
			"campaign_title":       title,
			"campaign_description": description,
			"is_active":            true,
			"updated_at":           &now,
		}).Error
}

func (r *offerRepository) DisableCampaign(
	astrologerID uint,
) error {

	now := time.Now()

	return r.db.
		Model(&models.AstrologerOfferSetting{}).
		Where("astrologer_id = ?", astrologerID).
		Where("is_delete = ?", false).
		Updates(map[string]interface{}{
			"campaign_enabled":     false,
			"campaign_title":       "",
			"campaign_description": "",
			"updated_at":           &now,
		}).Error
}

func (r *offerRepository) HasActiveOffer(
	astrologerID uint,
) (bool, error) {

	var count int64

	err := r.db.
		Model(&models.AstrologerOfferSetting{}).
		Where("astrologer_id = ?", astrologerID).
		Where("is_active = ?", true).
		Where("is_delete = ?", false).
		Where(
			r.db.
				Where("po5_enabled = ?", true).
				Or("free_chat_enabled = ?", true).
				Or("free_call_enabled = ?", true).
				Or("campaign_enabled = ?", true),
		).
		Count(&count).Error

	if err != nil {
		return false, err
	}

	return count > 0, nil
}

func (r *offerRepository) UpdatePriority(
	astrologerID uint,
	priority int,
) error {

	now := time.Now()

	return r.db.
		Model(&models.AstrologerOfferSetting{}).
		Where("astrologer_id = ?", astrologerID).
		Where("is_delete = ?", false).
		Updates(map[string]interface{}{
			"priority":   priority,
			"updated_at": &now,
		}).Error
}
