package models

import (
	"time"

	"gorm.io/datatypes"
	"gorm.io/gorm"
)

// ContactMessage represents a message sent through the contact form
type ContactMessage struct {
	BaseModel
	Name      string    `json:"name" gorm:"not null"`
	Email     string    `json:"email" gorm:"not null"`
	Subject   string    `json:"subject" gorm:"not null"`
	Message   string    `json:"message" gorm:"type:text;not null"`
	Source    string    `json:"source" gorm:"size:50;default:contact"` // e.g., "contact", "sponsor"
	IPAddress string    `json:"ip_address" gorm:"size:45"`
	UserAgent string    `json:"user_agent" gorm:"type:text"`
	IsRead    bool      `json:"is_read" gorm:"default:false"`
	ReadAt    time.Time `json:"read_at,omitempty"`
}

// TableName specifies the table name for the ContactMessage model
func (ContactMessage) TableName() string {
	return "contact_messages"
}

// NewsletterSubscription represents a user subscription to the newsletter
type NewsletterSubscription struct {
	BaseModel
	Email    string `json:"email" gorm:"uniqueIndex;not null"`
	IsActive bool   `json:"is_active" gorm:"default:true"`
	// Preferences stores subscriber choices (e.g. matches, scores, events, blog) as JSON
	// Use datatypes.JSONMap so GORM/driver can marshal/unmarshal JSONB correctly
	Preferences datatypes.JSONMap `json:"preferences" gorm:"type:jsonb;default:'{}'::jsonb"`
	CreatedAt   time.Time         `json:"created_at"`
	UpdatedAt   time.Time         `json:"updated_at"`
}

// TableName specifies the table name for the NewsletterSubscription model
func (NewsletterSubscription) TableName() string {
	return "newsletter_subscriptions"
}

// CreateContactMessage creates a new contact message in the database
func CreateContactMessage(db *gorm.DB, message *ContactMessage) error {
	return db.Create(message).Error
}

// GetContactMessages retrieves a paginated list of contact messages
func GetContactMessages(db *gorm.DB, page, limit int) ([]ContactMessage, int64, error) {
	var messages []ContactMessage
	var count int64

	offset := (page - 1) * limit

	// Get total count
	if err := db.Model(&ContactMessage{}).Count(&count).Error; err != nil {
		return nil, 0, err
	}

	// Get paginated results
	err := db.Offset(offset).
		Limit(limit).
		Order("created_at DESC").
		Find(&messages).Error

	return messages, count, err
}

// MarkMessageAsRead marks a contact message as read
func MarkMessageAsRead(db *gorm.DB, id uint) error {
	return db.Model(&ContactMessage{}).
		Where("id = ?", id).
		Updates(map[string]interface{}{
			"is_read": true,
			"read_at": time.Now(),
		}).Error
}

// SubscribeToNewsletter subscribes an email to the newsletter
func SubscribeToNewsletter(db *gorm.DB, email string) error {
	subscription := NewsletterSubscription{
		Email:     email,
		IsActive:  true,
		CreatedAt: time.Now(),
		UpdatedAt: time.Now(),
	}

	return db.Where(NewsletterSubscription{Email: email}).
		Attrs(subscription).
		FirstOrCreate(&subscription).
		Update("is_active", true).
		Error
}

// UnsubscribeFromNewsletter unsubscribes an email from the newsletter
func UnsubscribeFromNewsletter(db *gorm.DB, email string) error {
	return db.Model(&NewsletterSubscription{}).
		Where("email = ?", email).
		Update("is_active", false).
		Error
}

// GetActiveSubscribers returns a list of all active newsletter subscribers
func GetActiveSubscribers(db *gorm.DB) ([]string, error) {
	var subscribers []string
	err := db.Model(&NewsletterSubscription{}).
		Where("is_active = ?", true).
		Pluck("email", &subscribers).
		Error

	return subscribers, err
}
