package db

import (
	"encoding/json"
	"time"

	"gorm.io/gorm"
)

// NotificationService represents a notification service configuration
type NotificationService struct {
	ID                uint              `json:"id" gorm:"primaryKey"`
	Name              string            `json:"name" gorm:"not null"`
	Type              string            `json:"type" gorm:"not null"` // email, webhook
	IsEnabled         *bool             `json:"is_enabled" gorm:"default:true"`
	Config            map[string]string `json:"config" gorm:"-"`
	ConfigJSON        string            `json:"-" gorm:"column:config"`
	Description       string            `json:"description"`
	EventTriggers     []string          `json:"event_triggers" gorm:"-"`
	EventTriggersJSON string            `json:"-" gorm:"column:event_triggers;default:'[]'"`
	PayloadTemplate   string            `json:"payload_template" gorm:"column:payload_template"`
	SecretKey         string            `json:"secret_key" gorm:"column:secret_key"`
	RetryPolicy       string            `json:"retry_policy" gorm:"column:retry_policy;default:'simple'"`
	LastUsed          time.Time         `json:"last_used" gorm:"column:last_used"`
	SuccessCount      int               `json:"success_count" gorm:"column:success_count;default:0"`
	FailureCount      int               `json:"failure_count" gorm:"column:failure_count;default:0"`
	CreatedBy         uint              `json:"created_by"`
	CreatedAt         time.Time         `json:"created_at"`
	UpdatedAt         time.Time         `json:"updated_at"`
}

// BeforeSave converts Config map and EventTriggers to JSON strings for storage
func (n *NotificationService) BeforeSave(tx *gorm.DB) error {
	configJSON, err := json.Marshal(n.Config)
	if err != nil {
		return err
	}
	n.ConfigJSON = string(configJSON)

	eventsJSON, err := json.Marshal(n.EventTriggers)
	if err != nil {
		return err
	}
	n.EventTriggersJSON = string(eventsJSON)

	return nil
}

// AfterFind converts JSON strings back to Config map and EventTriggers
func (n *NotificationService) AfterFind(tx *gorm.DB) error {
	if n.ConfigJSON != "" {
		if err := json.Unmarshal([]byte(n.ConfigJSON), &n.Config); err != nil {
			return err
		}
	}

	if n.EventTriggersJSON != "" {
		if err := json.Unmarshal([]byte(n.EventTriggersJSON), &n.EventTriggers); err != nil {
			return err
		}
	}

	return nil
}

// GetNotificationServices returns notification services, filtered by enabled status if specified
func (db *DB) GetNotificationServices(onlyEnabled bool) ([]NotificationService, error) {
	var services []NotificationService
	query := db.DB

	if onlyEnabled {
		// When using a pointer, we need to explicitly check for true
		// GORM handles the underlying SQL correctly for different dialects
		query = query.Where("is_enabled = ?", true)
	}

	if err := query.Find(&services).Error; err != nil {
		return nil, err
	}

	return services, nil
}

// GetNotificationService returns a notification service by ID
func (db *DB) GetNotificationService(id uint) (*NotificationService, error) {
	var service NotificationService
	if err := db.First(&service, id).Error; err != nil {
		return nil, err
	}
	return &service, nil
}

// CreateNotificationService creates a new notification service
func (db *DB) CreateNotificationService(service *NotificationService) error {
	return db.Create(service).Error
}

// UpdateNotificationService updates an existing notification service
func (db *DB) UpdateNotificationService(service *NotificationService) error {
	return db.Save(service).Error
}

// DeleteNotificationService deletes a notification service by ID
func (db *DB) DeleteNotificationService(id uint) error {
	return db.Delete(&NotificationService{}, id).Error
}

// --- NotificationService Helper Methods ---

// GetIsEnabled returns the value of IsEnabled with a default if nil
func (n *NotificationService) GetIsEnabled() bool {
	if n.IsEnabled == nil {
		// If the pointer is nil, GORM might not have set it,
		// or it was explicitly set to nil. We assume the DB default (true)
		// if it's nil, aligning with the original gorm tag default.
		return true
	}
	return *n.IsEnabled
}

// SetIsEnabled sets the IsEnabled field
func (n *NotificationService) SetIsEnabled(value bool) {
	n.IsEnabled = &value
}
